How to configure ingress controller in kubernetes to run multi domain-subdomain application

In this article we are going to learn  how to configure ingress controller in kubernetes so that we could run multi domain or subdomain application within same kubernetes cluster.

In this demo we are going to run application with domain “nginx.example.com” and other two subdomain called
tea.myshop.com and coffee.myshop.com in kubernetes using Nginx ingress controller. Please note that, these domains and subdomains are local domains.
To show case this demo about “How to configure ingress controller in kubernetes” I am using lxc containers install on Ubuntu(Bare-metal installation). Basically I have four containers/vms running on the lxc host as below:
root@vbhost:~# lxc list
+———–+———+————————+———————————————–+————+———–+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+———–+———+————————+———————————————–+————+———–+
| haproxy | RUNNING | 10.253.121.146 (eth0) | fd42:38af:bc0d:704d:216:3eff:fefa:cb4c (eth0) | PERSISTENT | 0 |
+———–+———+————————+———————————————–+————+———–+
| kmaster | RUNNING | 172.17.0.1 (docker0) | fd42:38af:bc0d:704d:216:3eff:fe31:7a49 (eth0) | PERSISTENT | 0 |
| | | 10.253.121.39 (eth0) | | | |
| | | 10.244.0.0 (flannel.1) | | | |
+———–+———+————————+———————————————–+————+———–+
| kworker01 | RUNNING | 172.17.0.1 (docker0) | fd42:38af:bc0d:704d:216:3eff:fed4:8226 (eth0) | PERSISTENT | 0 |
| | | 10.253.121.32 (eth0) | | | |
| | | 10.244.1.1 (cni0) | | | |
| | | 10.244.1.0 (flannel.1) | | | |
+———–+———+————————+———————————————–+————+———–+
| kworker02 | RUNNING | 172.17.0.1 (docker0) | fd42:38af:bc0d:704d:216:3eff:fe9f:82c0 (eth0) | PERSISTENT | 0 |
| | | 10.253.121.89 (eth0) | | | |
| | | 10.244.2.1 (cni0) | | | |
| | | 10.244.2.0 (flannel.1) | | | |
+———–+———+————————+———————————————–+————+———–+

So all these containers are running centos. Three of them are being used for kubernetes cluster. One will be using for haproxy which we will be utilizing as a loadbalancer to load balance the request to one of the two kubernetes worker node.

To learn more about lxc containers follow this link.
Steps:

Deploy kubernetes cluster:

Once you deployed three lxc containers configure one of them as kubernetes master and other two as kubernetes worker node. To cut short the configuration journey  you can follow this link.

Deploy ha-proxy container with centos operating system:

We will be deploying one more lxc container with centos and will be configuring haproxy as per below steps:

root@vbhost:~# lxc exec haproxy bash
[root@haproxy ~]#
Now install the haproxy package in the container
# yum install haproxy
Once you have installed haproxy we need change the configuration so that it will load balance the traffic between the kubernetes worker node. Open the /etc/haproxy/haproxy.cfg file and replace it with below contents:
[root@haproxy ~]# cat /etc/haproxy/haproxy.cfg
#———————————————————————
# Example configuration for a possible web application. See the
# full configuration options online.
#
# http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
#
#———————————————————————

#———————————————————————
# Global settings
#———————————————————————
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the ‘-r’ option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2

chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon

# turn on stats unix socket
stats socket /var/lib/haproxy/stats

#———————————————————————
# common defaults that all the ‘listen’ and ‘backend’ sections will
# use if not designated in their block
#———————————————————————
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000

frontend http_front
bind *:80
stats uri /haproxy?stats
default_backend http_back

backend http_back
balance roundrobin
server kube 10.253.121.32:80
server kube 10.253.121.89:80
[root@haproxy ~]#

Make sure you change the bottom two ip address with ip address of the kubernetes worker nodes so that it could be load balanced. Here are the ip adress of my worker node which we have entered in the above haproxy configuration file. Also we are using http port 80 for our configuration.
# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
kmaster Ready master 31d v1.17.1 10.253.121.39 <none> CentOS Linux 7 (Core) 4.15.0-106-generic docker://19.3.5
kworker01 Ready <none> 31d v1.17.1 10.253.121.32 <none> CentOS Linux 7 (Core) 4.15.0-106-generic docker://19.3.5
kworker02 Ready <none> 31d v1.17.1 10.253.121.89 <none> CentOS Linux 7 (Core) 4.15.0-106-generic docker://19.3.5
#

Now restart and enable the haproxy service.
# systemctl enable haproxy
# systemctl restart haproxy
We are done with haproxy configuration. Now logout from it.

Install the Nginx-controller on kubernetes master node:

Clone the git repo  and change directory to “kubernetes-ingress/deployments/”
# git clone https://github.com/nginxinc/kubernetes-ingress.git
# cd kubernetes-ingress/deployments/

Create the namespace and service account.
# kubectl apply -f common/ns-and-sa.yaml
Apply the role and cluster role binding
# kubectl apply -f rbac/rbac.yaml
Make the secret
# kubectl apply -f common/default-server-secret.yaml
apply the configmap required.
# kubectl apply -f common/nginx-config.yaml
Now deploy the Ingress controller as daemon-set
# kubectl apply -f daemon-set/nginx-ingress.yaml
Now if you check the namespace and the resources within “nginx-ingress” namespace you will find similar resources being created.
# kubectl get ns
NAME STATUS AGE
cattle-system Active 29d
default Active 31d
efk Active 29d
kube-node-lease Active 31d
kube-public Active 31d
kube-system Active 31d
nginx-ingress Active 10s

# kubectl get all -n nginx-ingress
NAME READY STATUS RESTARTS AGE
pod/nginx-ingress-2rq6s 0/1 ContainerCreating 0 14s
pod/nginx-ingress-65vnd 0/1 ContainerCreating 0 14s

NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/nginx-ingress 2 2 0 2 0 <none> 14s

Once they are ready we are going to deploy services.

Deploy the Nginx service with NodePort type listening on port 80 which will run sample Nginx web-server with its default index.html file. Here is manifest file I am using for it.

# cat nginx-deploy-main.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: nginx
name: nginx-deploy-main
spec:
replicas: 1
selector:
matchLabels:
run: nginx-main
template:
metadata:
labels:
run: nginx-main
spec:
containers:
– image: nginx
name: nginx



apiVersion: v1
kind: Service
metadata:
name: nginx-deploy-main
spec:
type: NodePort
selector:
run: nginx-main
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
– port: 80

Deploy the Nginx service
# kubectl create -f nginx-deploy-main.yaml
deployment.apps/nginx-deploy-main created
service/nginx-deploy-main created

Now lets deploy the another service which will be of the type NodePort with port 80.  For this service I am using my own created docker image called “manmohanmirkar/mytea_image” which will simply display the message “This is Tea Shop” in the browser. This service will be get called once you  try to access url “tea.myshop.com” . Sample manifest file is as below:
# cat tea.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: tea
name: tea-deploy
spec:
replicas: 2
selector:
matchLabels:
app: tea
template:
metadata:
labels:
app: tea
spec:
containers:
– name: tea
image: manmohanmirkar/mytea_image:latest


apiVersion: v1
kind: Service
metadata:
name: tea-deploy
spec:
type: NodePort
selector:
app: tea
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
– port: 80

Apply the tea service:
# kubectl create -f tea.yml
deployment.apps/tea-deploy created
service/tea-deploy created

Configure the coffee service

Deploy one more service which will be of the type NodePort with port 80.  For this service I am using my own created docker image called “manmohanmirkar/mycoffee_image” which will simply display the message “This is Coffee Shop” in the browser. This service will be get called once you  try to access url “coffee.myshop.com” . Sample manifest file is as below:
# cat coffe.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: coffee
name: coffee-deploy
spec:
replicas: 2
selector:
matchLabels:
app: coffee
template:
metadata:
labels:
app: coffee
spec:
containers:
– name: coffee
image: manmohanmirkar/mycoffee_image:latest

apiVersion: v1
kind: Service
metadata:
name: coffee-deploy
spec:
type: NodePort
selector:
app: coffee
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
– port: 80
Now lets apply the coffee service and deployment.
# kubectl create -f coffe.yml
deployment.apps/coffee-deploy created
service/coffee-deploy created

Deploy the Ingress resource

This is the main configuration in this article which will configure the Ingress resource. This Ingress resource will be performing the task of routing the request to respective service based on the URL. Let have look at the manifest file for the same:
# cat cafe-ingress.yml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: my-ingress-resource
spec:
rules:
– host: nginx.example.com
http:
paths:
– backend:
serviceName: nginx-deploy-main
servicePort: 80
– host: tea.myshop.com
http:
paths:
– backend:
serviceName: tea-deploy
servicePort: 80
– host: coffee.myshop.com
http:
paths:
– backend:
serviceName: coffee-deploy
servicePort: 80

Basically in the above file will deploy the resource type Ingress. It has got three host based rules configured for each service. So if the host url is “nginx.example.com” then it has backend with service Name “nginx-deploy-main”. Basically it means that whenever the request with URL “nginx.example.com” made it will be get forwarded to the service “nginx-deploy-main”.
In the similar way we have two more hosts “tea.myshop.com” and “coffee.myshop.com” with backed configured as “tea-deploy” and “coffee-deploy”. This also means that whenever the request made with URL “tea.myshop.com” to the haproxy serrver it will forwarded to the service “tea-deploy”. Also in the similar way if the request with URL “coffee.myshop.com” it will be automatically get forwarded to the service “coffee-deploy” which we have already deployed.
Now lets deploy the ingress resource:
# kubectl create -f cafe-ingress.yml
ingress.networking.k8s.io/my-ingress-resource created

Crosscheck the ingress resource with following commands:
# kubectl describe ing
Name: my-ingress-resource
Namespace: default
Address:
Default backend: default-http-backend:80 (<error: endpoints “default-http-backend” not found>)
Rules:
Host Path Backends
—- —- ——–
nginx.example.com
nginx-deploy-main:80 (10.244.2.82:80)
tea.myshop.com
tea-deploy:80 (10.244.1.94:80,10.244.2.83:80)
coffee.myshop.com
coffee-deploy:80 (10.244.1.95:80,10.244.2.84:80)
Annotations: <none>
Events:
Type Reason Age From Message
—- —— —- —- ——-
Normal AddedOrUpdated 31s nginx-ingress-controller Configuration for default/my-ingress-resource was added or updated
Normal AddedOrUpdated 31s nginx-ingress-controller Configuration for default/my-ingress-resource was added or updated

You can able to see from the output that, if the host is “nginx.example.com” then service configured is “nginx-deploy-main” and if the host or URL is “tea.myshop.com” then service for the same is “tea-deploy” sample applicable for the coffee service with respective service name.

This is the final step in which we are going to configure the DNS entries for all the three URL we have configured in the ingress resource. Basically we are going make the entries on the host machine with all the urls with ip of out haproxy container.
# lxc list haproxy
+———+———+———————–+———————————————–+————+———–+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+———+———+———————–+———————————————–+————+———–+
| haproxy | RUNNING | 10.253.121.146 (eth0) | fd42:38af:bc0d:704d:216:3eff:fefa:cb4c (eth0) | PERSISTENT | 0 |
+———+———+———————–+———————————————–+————+———–+

So ip address of haproxy is 10.253.121.146. Simply add below entries /etc/hosts of the host machine:
# cat /etc/hosts
127.0.0.1 localhost
192.168.56.5 vbhost

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters



10.253.121.146 nginx.example.com
10.253.121.146 coffee.myshop.com
10.253.121.146 tea.myshop.com

Check the last three entries all url are pointing to haproxy which will in turn forward the request to our kubernetes worker node.

Now lets try to access the all URL’s one by one from the host machine.

So this all about the topic of How to configure ingress controller in kubernetes.

Latest articles

Related articles