Ingress is one of the important concepts in Kubernetes, which allows external users to access containerized application using FQDN (fully qualified domain name). Though Ingress is not enabled and installed by default in Kubernetes cluster. We must enable to this core concept using third party ingress controllers like Nginx, Traefik, HAProxy and Istio etc.
In this tutorial we will demonstrate how to setup and use NGINX Ingress controller in Kubernetes Cluster.
As above picture, external users are accessing applications using NGINX Ingress Controller via FQDN and internal ingress controller routes the request to service and then service routes the request to backend end points or pods.
Enable NGINX Ingress Controller in Minikube
Minikube is a single node Kubernetes cluster, we can easily enable nginx ingress controller in minikube by running “minikube addons” command.
Run below command to verify the status of ingress controller,
# minikube addons list
Run following minikube command to enable ingress controller,
[[email protected] ~]# minikube addons enable ingress * The 'ingress' addon is enabled [[email protected] ~]#
If we re-run “minikube addons list” command, this time we must see the status of ingress is enabled.
Run following kubectl command to verify whether ingress controller’s pod is running or not.
[[email protected] ~]# kubectl get pods --all-namespaces | grep -i nginx-controller kube-system ingress-nginx-controller-7bb4c67d67-gkjj5 1/1 Running 0 20m [[email protected] ~]#
Above output confirms that nginx-controller has been enabled and started its pod successfully under kube-system namespace.
Setup NGINX Ingress Controller in Kubernetes cluster
Note: I am assuming Kubernetes cluster is up and running.
Go to master node or control plane node and execute following kubectl command,
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/deploy.yaml
We will get the following output,
Run following kubectl command to verify the status of nginx-ingress controller pods,
[email protected]:~$ kubectl get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx NAME READY STATUS RESTARTS AGE ingress-nginx-admission-create-v7ftn 0/1 Completed 0 6m12s ingress-nginx-admission-patch-njdnf 0/1 Completed 0 6m12s ingress-nginx-controller-75f84dfcd7-p5dct 1/1 Running 0 6m23s [email protected]:~$
Perfect, above output confirms that NGINX Ingress Controller has been deployed successfully and it’s pod is currently running.
Test Ingress Controller
To test Ingress controller, we will create two applications based on httpd and nginx container and will expose these applications via their respective services and then will create ingress resource which will allow external users to access these applications using their respective urls.
Deploy httpd based deployment and its service with NodePort type listening on the port 80, Create the following yaml file which includes deployment and service section,
[[email protected] ~]# vi httpd-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: httpd-deployment spec: replicas: 1 selector: matchLabels: run: httpd-deployment template: metadata: labels: run: httpd-deployment spec: containers: - image: httpd name: httpd-webserver --- apiVersion: v1 kind: Service metadata: name: httpd-service spec: type: NodePort selector: run: httpd-deployment ports: - port: 80
Save and close the file.
Run kubectl command to deploy above httpd based deployment and its service,
[[email protected] ~]# kubectl create -f httpd-deployment.yaml deployment.apps/httpd-deployment created service/httpd-service created [[email protected] ~]#
Deploy our next NGINX based deployment and its service with NodePort as its type and port as 80, Content of yaml file listed below,
[[email protected] ~]# vi nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 1 selector: matchLabels: run: nginx-deployment template: metadata: labels: run: nginx-deployment spec: containers: - image: nginx name: nginx-webserver --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: type: NodePort selector: run: nginx-deployment ports: - port: 80
Save and exit the file
Now run following kubectl command to deploy above nginx based deployment and its service,
[[email protected]nuxtechi ~]# kubectl create -f nginx-deployment.yaml deployment.apps/nginx-deployment created service/nginx-service created [[email protected] ~]#
Run below command to verify the status of both deployments and their services
[[email protected] ~]# kubectl get deployments.apps httpd-deployment NAME READY UP-TO-DATE AVAILABLE AGE httpd-deployment 1/1 1 1 19m [[email protected] ~]# [[email protected] ~]# kubectl get deployments.apps nginx-deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 1/1 1 1 24m [[email protected] ~]# [[email protected] ~]# kubectl get service nginx-service httpd-service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-service NodePort 10.103.75.91 <none> 80:30042/TCP 78m httpd-service NodePort 10.98.6.131 <none> 80:31770/TCP 73m [[email protected] ~]#
Create and Deploy Ingress Resource
Create the following ingress resource yaml file which will route the request to the respective service based url or path. In our example we be using url or fqdn.
[[email protected] ~]# vim myweb-ingress.yaml apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: name-based-virtualhost-ingress spec: rules: - host: httpd.example.com http: paths: - backend: serviceName: httpd-service servicePort: 80 - host: nginx.example.com http: paths: - backend: serviceName: nginx-service servicePort: 80
save and close the file.
Execute beneath kubectl command to create above ingress resource,
[[email protected] ~]# kubectl create -f myweb-ingress.yaml ingress.networking.k8s.io/name-based-virtualhost-ingress created [[email protected] ~]#
Run following to verify the status of above created ingress resource
[[email protected] ~]# kubectl get ingress name-based-virtualhost-ingress [[email protected] ~]# kubectl describe ingress name-based-virtualhost-ingress
Perfect, above output confirms that ingress resources have been created successfully.
Before accessing these urls from outside of the cluster please make sure to add the following entries in hosts file of your system from where you intended to access these.
192.168.1.190 httpd.example.com 192.168.1.190 nginx.example.com
Now try to access these URLs from web browser, type
http://httpd.example.com
http://nginx.example.com
Great, above confirms that we have successfully deployed and setup nginx ingress controller in Kubernetes. Please do share your valuable feedback and comments.
Hello, I have tried the procedures above, but finally failed.
When I enter the command curl httpd.example.com:80 / nginx.example.com:80 in k8s master, it returns curl: (7) Failed to connect to httpd.example.com port 80: Connection refused.
Do you have any idea about the error?
Hi David,
If the above procedure does not work for you then I would suggest download ingress deploy yaml file and then edit it and add following in deployment section
spec:
hostNetwork: true
dnsPolicy: ClusterFirst
containers:
Save and exit the file and try to redeploy the ingress with the updated yaml file.
Hi Pradeep,
I have downloaded the ingress deploy yaml file and add the following
spec:
hostNetwork: true
but it seems that it failed as well.
Finally it seems it is ok after I added the following in httpd-deployment.yaml and nginx-deployment.yaml.
externalIPs:
– “192.168.30.5”
I believe above won’t work directly unless you assign an external ip to ingress controller service ( external ip can be assigned automatically using MetalLB )
Please refer below,
‘https://kubernetes.github.io/ingress-nginx/deploy/’
‘https://metallb.universe.tf/’
Hi,
I am performing this on EC2 instance and facing the same connection refused error, Please suggest me anything