Yayyy!! Mindbrews First Edition is now live on Magzter!

Developers & Open Source

How to deploy Nginx Ingress Controller in Kubernetes

An Ingress Controller in Kubernetes is responsible for reading the ingress resource and processing the data accordingly, in case of Nginx Ingress Controller, whenever an Ingress Resource is defined, the Nginx Ingress Controller reads the hostname from the resource and ensures that whenever any request is received on the Load Balancer on specified hostname, it’s routed to the service specified in the Ingress Resource.

Step 1: Deploy the essentials

We’ll be using the deployment provided by the Kubernetes Team rather than the one provided by the Nginx Team. To start quickly, deploy the latest deployment file from their instructions, at the time of writing of this article the latest one was:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.44.0/deploy/static/provider/baremetal/deploy.yaml

I’ve used the bare metal deployment, because we’ll be creating load balancer in next steps. Once you run the above command you should see the output similar to,

namespace/ingress-nginx created
serviceaccount/ingress-nginx created
configmap/ingress-nginx-controller created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
service/ingress-nginx-controller-admission created
service/ingress-nginx-controller created
deployment.apps/ingress-nginx-controller created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
serviceaccount/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created

Step 2: Deploy the Load Balancer Services

Once everything above is done, you should run kubectl get pods -n ingress-nginx to see the status, if all pods are ready, and once everything’s set, we’ll move to next step.

Suggested:  Deno: The Replacement for Node.js ?

You should see the output as below for the above command,

$> kubectl get pods --namespace=ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-2x9xh        0/1     Completed   0          2m2s
ingress-nginx-admission-patch-wcf45         0/1     Completed   0          2m2s
ingress-nginx-controller-67897c9494-ztfc7   1/1     Running     0          2m3s

Now let’s deploy the load balancer service, each cloud provider provides you with their own Load Balancer service, documentation for the same can be found in their official documentations, I’m however attaching the answers for two cases, AWS (Network Load Balancer, NLB), and MetalLB (for Bare Metal Deployments)

2.1 On AWS using NLB

To deploy a NLB on AWS EKS and expose our ingress controller to the world, create a controller-service.yaml file with the following content

# Source: ingress-nginx/templates/controller-service.yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: 'true'
    service.beta.kubernetes.io/aws-load-balancer-type: nlb
  labels:
    helm.sh/chart: ingress-nginx-3.23.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.44.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
    - name: https
      port: 443
      protocol: TCP
      targetPort: https
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/component: controller

and now deploy the file using kubectl apply -f controller-service.yaml, once done you can see a new Network Load Balancer being provisioned in your EC2 Load Balancers Dashboard,

If you click on the name of the Load Balancer, you can see the DNS Name of the Load Balancer, now all left to do is to map your domain to this address and create a Ingress Resource on your cluster with that domain

2.2 On Bare Metal using MetalLB

Assuming you already have MetalLB up and running, you can easily expose your controller to public IP, using the YAML File below,

kind: Service
apiVersion: v1
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/version: 0.43.0
    helm.sh/chart: ingress-nginx-3.19.0
spec:
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: http
    - name: https
      protocol: TCP
      port: 443
      targetPort: https
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  type: LoadBalancer

and apply the file using kubectl apply -f controller-service.yaml, once done MetalLB will assign an address to your Load Balancer Service, and you can use this IP to access the cluster and expose other services to domains using ingress resource.

Suggested:  Facebook bans extremist conspiracy group QAnon

Tip

On bare metal configurations where you don’t have a cloud load balancer, you can create multiple load balancer services with different names. Each of these services will have a different IP from your IP Pool on Metal LB, and then you can create a simple Load Balancer using HA Proxy or something similar.

Example Nginx Ingress Resource

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: backend-ingress
  namespace: letstream-app
spec:
  tls:
  - hosts:
    - portal.theletstream.com # Replace it with the deployment domain
    secretName: ssl-certificate
  rules:
    - host: portal.theletstream.com # Replace it with the deployment domain
      http:
        paths:
          - backend:
              serviceName: backend-service
              servicePort: 8055

you should remove the tls directive if you don’t need SSL, otherwise you should replace the secretName with your own ssl-secret, to create a SSL Secret, put your Certificate File (cert.crt) and Private Key (key.pem) in certs folder and run the command below,

kubectl create secret tls ssl-certificate --key certs/key.pem --cert certs/cert.crt --namespace letstream-app

replace serviceName with the name of the service you want to redirect the traffic to in same namespace, and servicePort with the port number of the service.

Suggested:  Superpower your Static HTML with Static Jinja!

That’s all folks. If you’ve any doubts, comments, and/or suggestions, feel free to leave them in comments below!

Related posts
Developers & Open Source

How to deploy Kubernetes Dashboard?