Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Setup and deploy Ingress controller for Kubernetes on Bare Metal servers

After install, setup and configuration of Kubernetes Cluster in my bare metal servers, I wanted to do the POC (proof of concept) of Ingress resource for one of the production environment. 

Kubernetes Ingress is an API entity that lets entry to your Kubernetes services from outside network. It provides routing table rules to administer access to the services within a Kubernetes cluster. This normally utilizes HTTPS and HTTP protocols to enable the routing. Ingress is the ideal choice for a production environment (Ingress is also called overlay network which is virtual network that operates on top of different networks and spans across all the nodes in the cluster).

Below is the Kubernetes cluster configuration setup in my lab: 
Configure Nginx Load Balancer for the Kubernetes API Server - Part 1
Install and configure Kubernetes cluster master nodes using kubeadm - Part 2
Install and configure Kubernetes cluster worker nodes using kubeadm - Part 3

Before starting configuration of ingress, I will do the health checkup of my Kubernetes Cluster in the Lab by getting the list of  nodes and status with Kubectl command. I also need IP addresses list of nodes. All looks good.

In this POC I have a website domain name web.example.com hosted on the K8s deployment pods, which I will try to access it this from outside network. As I don't have domain name registered in domain registrar, I will simulate it using DNS record entries in my local /etc/hosts files. Check curl request (text based and API browser) for domain name but connection is refused and not working.

root@k8smaster01:~#
root@k8smaster01:~# kubectl get node -o wide
NAME          STATUS   ROLES           AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
k8smaster01   Ready    control-plane   14d   v1.25.2   192.168.34.61           Ubuntu 20.04.5 LTS   5.15.0-52-generic   containerd://1.6.8
k8smaster02   Ready    control-plane   14d   v1.25.2   192.168.34.62           Ubuntu 20.04.5 LTS   5.15.0-50-generic   containerd://1.6.8
k8smaster03   Ready    control-plane   14d   v1.25.2   192.168.34.63           Ubuntu 20.04.5 LTS   5.15.0-50-generic   containerd://1.6.8
k8sworker01   Ready                    13d   v1.25.2   192.168.34.66           Ubuntu 20.04.5 LTS   5.15.0-50-generic   containerd://1.6.8
k8sworker02   Ready                    13d   v1.25.2   192.168.34.67           Ubuntu 20.04.5 LTS   5.15.0-50-generic   containerd://1.6.8
k8sworker03   Ready                    13d   v1.25.2   192.168.34.68           Ubuntu 20.04.5 LTS   5.15.0-50-generic   containerd://1.6.8
root@k8smaster01:~#
root@k8smaster01:~# vim /etc/hosts
root@k8smaster01:~#
root@k8smaster01:~# cat /etc/hosts
127.0.0.1       localhost
127.0.1.1       k8smaster01.vcloud-lab.com k8smaster01

# 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

192.168.34.61   k8smaster01.vcloud-lab.com k8smaster01

192.168.34.66   web.example.com
192.168.34.67   web.example.com
192.168.34.68   web.example.com
root@k8smaster01:~#
root@k8smaster01:~# curl web.example.com
curl: (7) Failed to connect to web.example.com port 80: Connection refused
root@k8smaster01:~#

Verify the component status of Kubernetes Cluster control-plane, No error here. Git clone the Kubernetes ingress project from github/nginxinc.

root@k8smaster01:~#
root@k8smaster01:~# kubectl get cs -o wide
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS    MESSAGE                         ERROR
controller-manager   Healthy   ok
scheduler            Healthy   ok
etcd-0               Healthy   {"health":"true","reason":""}
root@k8smaster01:~#
root@k8smaster01:~# git clone https://github.com/nginxinc/kubernetes-ingress.git
Cloning into 'kubernetes-ingress'...
remote: Enumerating objects: 45922, done.
remote: Counting objects: 100% (59/59), done.
remote: Compressing objects: 100% (46/46), done.
remote: Total 45922 (delta 26), reused 32 (delta 13), pack-reused 45863
Receiving objects: 100% (45922/45922), 60.82 MiB | 16.68 MiB/s, done.
Resolving deltas: 100% (27340/27340), done.
root@k8smaster01:~#

Reference to official document to deploy Nginx Ingress controller:- https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/

Once folder is downloaded from github, Change the directory kubernetes-ingress/deployments and deploy/create below resources from K8S yaml manifests as shown below in the screenshot. 

common/ns-and-sa.yaml: Creates two resources, namespace and service account for the Kubernetes cluster ingress controller
rbac/rbac.yaml: In the Kubernetes cluster create rbac with cluster role resource and cluster role binding resource for service account.
common/default-server-secret.yaml: This is a part of creating common resources, it creates secret resource with a TLS certificate and key for the default server in NGINX.
common/nginx-config.yaml: This creates a configmap resource for customizing NGINX configuration.
common/ingress-class.yaml: It creates an IngressClass resource. If you would wish to configure the Ingress Controller as the default one, uncomment the annotation ingressclass.kubernetes.io/is-default-class. With this annotation set to true all the new Ingresses without an ingressClassName field specified will be assigned this IngressClass.

By default, it is needed to apply custom resource definitions (CRDS) for VirtualServer, VirtualServerRoute, TransportServer and Policy. If you don't, the Ingress Controller pods will not become Ready
common/crds/k8s.nginx.org_virtualservers.yaml
common/crds/k8s.nginx.org_virtualserverroutes.yaml
common/crds/k8s.nginx.org_transportservers.yaml
common/crds/k8s.nginx.org_policies.yaml


common/crds/k8s.nginx.org_globalconfigurations.yaml: To utilize the TCP and UDP load balancing aspects of the Ingress Controller, create the this object.
daemon-set/nginx-ingress.yaml: This will deploy and run ingress controller in kubernetes cluster. I am creating it as daemon-set so every worker node in the cluster will have one ingress controller pod deployed. My lab size is small, but in bigger environment use the deployment/nginx-ingress.yaml, It will only deploy one pod, you can adjust the replicas number in the yaml file by editing it.

root@k8smaster01:~#
root@k8smaster01:~# cd kubernetes-ingress/deployments
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl apply -f common/ns-and-sa.yaml
namespace/nginx-ingress created
serviceaccount/nginx-ingress created
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl apply -f rbac/rbac.yaml
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress created
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl apply -f common/default-server-secret.yaml
secret/default-server-secret created
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl apply -f common/nginx-config.yaml
configmap/nginx-config created
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# #edit file to uncomment annotations
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl apply -f common/ingress-class.yaml
ingressclass.networking.k8s.io/nginx unchanged
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl apply -f common/crds/k8s.nginx.org_virtualservers.yaml
customresourcedefinition.apiextensions.k8s.io/virtualservers.k8s.nginx.org created
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl apply -f common/crds/k8s.nginx.org_virtualserverroutes.yaml
customresourcedefinition.apiextensions.k8s.io/virtualserverroutes.k8s.nginx.org created
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl apply -f common/crds/k8s.nginx.org_transportservers.yaml
customresourcedefinition.apiextensions.k8s.io/transportservers.k8s.nginx.org created
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl apply -f common/crds/k8s.nginx.org_policies.yaml
customresourcedefinition.apiextensions.k8s.io/policies.k8s.nginx.org created
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl apply -f common/crds/k8s.nginx.org_globalconfigurations.yaml
customresourcedefinition.apiextensions.k8s.io/globalconfigurations.k8s.nginx.org created
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# #kubectl apply -f deployment/nginx-ingress.yaml
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl apply -f daemon-set/nginx-ingress.yaml
daemonset.apps/nginx-ingress created
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl create -f service/nodeport.yaml
service/nginx-ingress created

After deploying various yamls configuration in K8S cluster, verify the status of Ingress controller pods are running and there are no errors. If all looks good curl to the worker node IPs, now I am getting some response 404 Not found instead of connection refused.

root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl get ns
NAME               STATUS   AGE
calico-apiserver   Active   14d
calico-system      Active   14d
default            Active   15d
kube-node-lease    Active   15d
kube-public        Active   15d
kube-system        Active   15d
nginx-ingress      Active   51m
tigera-operator    Active   14d
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl get all --namespace=nginx-ingress
NAME                      READY   STATUS    RESTARTS   AGE
pod/nginx-ingress-cdxh2   1/1     Running   0          4m31s
pod/nginx-ingress-j2t6d   1/1     Running   0          4m31s
pod/nginx-ingress-v7jbb   1/1     Running   0          4m31s

NAME                    TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
service/nginx-ingress   NodePort   10.111.41.11           80:31102/TCP,443:30748/TCP   4m28s

NAME                           DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/nginx-ingress   3         3         3       3            3                     4m31s
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# curl 192.168.34.66

<span style="background-color:#D3D3D3">404 Not Found</span>

404 Not Found


nginx/1.23.1
root@k8smaster01:~/kubernetes-ingress/deployments# root@k8smaster01:~/kubernetes-ingress/deployments# curl 192.168.34.67 <span style="background-color:#D3D3D3">404 Not Found</span>

404 Not Found


nginx/1.23.1
root@k8smaster01:~/kubernetes-ingress/deployments#

Verify web.example.com dns name using curl, I am getting 404 Not Found response.

root@k8smaster01:~/kubernetes-ingress/deployments# curl web.example.com

<span style="background-color:#D3D3D3">404 Not Found</span>

404 Not Found


nginx/1.23.1
root@k8smaster01:~/kubernetes-ingress/deployments#

Ingress controller is setup well till this point, I will now deploy my applications in the cluster and test ingress now. Create a new namespace and deployment with 3 replicas with NGINX image under it.  Under the same namespace, create new ClusterIP service by exposing the deployment. Use port and target ports parameter, use selector label of deployment (start with app=deployment_name). In the last verify the status of all the resources deployed in the project namespace.

root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl create namespace project
namespace/project created
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl get ns project
NAME      STATUS   AGE
project   Active   15s
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl create deployment nginx-deploy --image=nginx --port=80 --replicas=3 -n project
deployment.apps/nginx-deploy created
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl get all -n project
NAME                               READY   STATUS    RESTARTS   AGE
pod/nginx-deploy-968984648-df4vp   1/1     Running   0          10s
pod/nginx-deploy-968984648-fsrxm   1/1     Running   0          10s
pod/nginx-deploy-968984648-lmdhm   1/1     Running   0          10s

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deploy   3/3     3            3           10s

NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deploy-968984648   3         3         3       10s
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl expose deployment nginx-deploy --name=nginx-svc --port=80 --target-port=80 --selector=app=nginx-deploy -n project
service/nginx-svc exposed
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# kubectl get all -n project
NAME                               READY   STATUS    RESTARTS   AGE
pod/nginx-deploy-968984648-df4vp   1/1     Running   0          10s
pod/nginx-deploy-968984648-fsrxm   1/1     Running   0          10s
pod/nginx-deploy-968984648-lmdhm   1/1     Running   0          10s

NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/nginx-svc   ClusterIP   10.101.250.212           80/TCP    12s

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deploy   3/3     3            3           2m1s

NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deploy-968984648   3         3         3       2m1s
root@k8smaster01:~/kubernetes-ingress/deployments#
root@k8smaster01:~/kubernetes-ingress/deployments# cd ~/

Go to home directory. Create a new Ingress resource in the yaml file with the below content. I have provided an annotations to instruct this ingress resource to use IngressClass named nginx (This is NGINX ingress controller name). Mention the DNS name details in yaml. Apply the configuration. Describe the resource and verify details.

root@k8smaster01:~/kubernetes-ingress/deployments# cd ~/
root@k8smaster01:~#
root@k8smaster01:~# vim ingress-resource.yaml
root@k8smaster01:~#
root@k8smaster01:~# cat ingress-resource.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
  namespace: project
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: web.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80
root@k8smaster01:~#
root@k8smaster01:~# kubectl apply -f ingress-resource.yaml
ingress.networking.k8s.io/nginx created
root@k8smaster01:~#
root@k8smaster01:~# kubectl describe ingress nginx -n project
Name:             nginx
Labels:           
Namespace:        project
Address:
Ingress Class:    
Default backend:  
Rules:
  Host             Path  Backends
  ----             ----  --------
  web.example.com
                   /   nginx-svc:80 (10.244.145.22:80,10.244.218.29:80,10.244.53.158:80)
Annotations:       kubernetes.io/ingress.class: nginx
Events:
  Type    Reason          Age   From                      Message
  ----    ------          ----  ----                      -------
  Normal  AddedOrUpdated  19s   nginx-ingress-controller  Configuration for project/nginx was added or updated
  Normal  AddedOrUpdated  19s   nginx-ingress-controller  Configuration for project/nginx was added or updated
  Normal  AddedOrUpdated  19s   nginx-ingress-controller  Configuration for project/nginx was added or updated
root@k8smaster01:~#

Everything is setup correctly now. Curl web.example.com website, I am getting successful result welcome to nginx!. Ingress is working fine. Test the worker nodes IP in curl, It is still showing 404 Not Found.

root@k8smaster01:~#
root@k8smaster01:~# curl web.example.com



<span style="background-color:#F0FFF0">><strong>Welcome to nginx!</strong></span>

Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.

Thank you for using nginx.

root@k8smaster01:~# root@k8smaster01:~# curl 192.168.34.66 <span style="background-color:#D3D3D3">404 Not Found</span>

404 Not Found


nginx/1.23.1
root@k8smaster01:~# curl 192.168.34.67 <span style="background-color:#D3D3D3">404 Not Found</span>

404 Not Found


nginx/1.23.1
root@k8smaster01:~#

This is a trick, as I have setup the Ingress Controller in the bare metal kubernetes setup with NodePort service. I can access it using the node ip and service nodeport port number mentioning Host as DNS.

root@k8smaster01:~# kubectl get services -n nginx-ingress
NAME            TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
nginx-ingress   NodePort   10.111.104.325           80:31313/TCP,443:30203/TCP   5h52m
root@k8smaster01:~#
root@k8smaster01:~# curl http://192.168.34.66:31313 -H 'Host:web.example.com'



<strong><span style="color:#2F4F4F"><span style="background-color:#F0FFF0">Welcome to nginx!</span></span></strong>

Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.

Thank you for using nginx.

root@k8smaster01:~#

This is a last part Incase if you want to delete the ingress controller setup use below commands.

kubectl delete namespace nginx-ingress
kubectl delete clusterrole nginx-ingress
kubectl delete clusterrolebinding nginx-ingress
cd kubernetes-ingress/deployments
kubectl delete -f common/crds/
cd ~/
rm -rf ~/kubernetes-ingress

Useful Articles
Kubernetes kubeadm join could not find a jws signature in the cluster-info ConfigMap for token ID
Kubernetes kubeadm join couldn't validate the identity of the API server connection refused
How to install kubernetes master control-plane on ubuntu Part 1
How to install kubernetes worker node on ubuntu Part 2
ansible create an array with set_fact
Ansible get information from esxi advanced settings nested dictionary with unique keynames
Install Ansible AWX Tower on Ubuntu Linux
Ansible AWX installation error Cannot have both the docker-py and docker python modules
Ansible AWX installation error docker-compose run --rm --service-ports task awx-manage migrate --no-input



This post first appeared on Tales From Real IT System Administrators World And Non-production Environment, please read the originial post: here

Share the post

Setup and deploy Ingress controller for Kubernetes on Bare Metal servers

×

Subscribe to Tales From Real It System Administrators World And Non-production Environment

Get updates delivered right to your inbox!

Thank you for your subscription

×