Kubernetes Part 5: Install and Configure NGINX Ingress Controller


After we have installed the MetalLB load balancer (click here for the blog post abour MetalLB), the next step is to install an Ingress controller.

What is in Ingress controller ? The kubernetes definition is 

In Kubernetes, an Ingress is an object that allows access to your Kubernetes services from outside the Kubernetes cluster. You configure access by creating a collection of rules that define which inbound connections reach which services. This lets you consolidate your routing rules into a single resource.

Since a kubernetes server can host multiple application/web servers, the ingress controller will (in simple terms)  point you to the correct service where the website/application is hosted

I first tried installing the Traefik ingress, but I just couldn''t get it to work properly in combination with the MetalLB load balancer. I guess I have overlooked a minor configuration detail in Traefik, but when I switched to the NGINX-ingress controller, I had it up and running pretty quickly.. 

The procedure below descibers the installation of the NGINX ingress conteller

- Install NGINX - Ingress Controller

# Create the namespace for ingress-nginx
kubectl create namespace ingress-nginx

# Add nginx repository to helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Install nginx ingress controller

helm install ingress-nginx ingress-nginx/ingress-nginx --version="4.0.17" \
    --set rbac.create=true \
    --set controller.kind=DaemonSet \
    --set controller.service.type=LoadBalancer \
    --set controller.service.externalTrafficPolicy=Local \
    --set controller.publishService.enabled=true \
    --set defaultBackend.enabled=true \
    --set defaultBackend.image.repository="k8s.gcr.io/defaultbackend-arm64" \
    --set enable-prometheus-metrics=true \
    --namespace ingress-nginx    

After the installation you can via services is running with the following command
kubectl get service -n ingress-nginx
You should something similar to this

As you can see the nginx-ingress-controller is installed and the MetalLB load balancer has given it an external IP to expose port 80, and 443 to outside the kubernetes cluster to your local network.

To expose your cluster to the Internet you need to port-forward the ports 80 and 443 to the external IP from the nginx-ingress-controller. This article explains for several home router brands on how-to do this 

To expose a web application via the Ingress controller, you always need to do 3 things:

  1. Create a DNS record on your internal network. If you want expose it to the Internet you need to create also a public DNS record). 
  2. Create a service for webapp. This is required to expose the app (pod) within the kubernetes cluster
  3. Create a ingress rule to expose the app (pod) outside the cluster
If you look a the picture at the top of this article you can see how the network traffic runs via a nginx-ingress.

- Test Ingress-Controller
You can test the nginx-ingress controller by creating a test nginx (webserver) app. To proceed to the following:

- Create DNS entry
Create a DNS entry for the nginx-1.mydomain.com  and use as IP the external ip from the ingress-controller.Change mydomain.com of course into your own domain.

- Create test deployment yaml

nano deploy-nginx-1-k8s.yml

 Copy and past the text below in nano, and save the file
apiVersion: apps/v1
kind: Deployment
  name: nginx-1
    app: nginx-1
  replicas: 1
      app: nginx-1
        app: nginx-1
      - image: nginx
        name: nginx-1
kind: Service
apiVersion: v1
  name: nginx-1-service
    app: nginx-1
    - protocol: TCP
      port: 80
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
  name: nginx-01
    kubernetes.io/ingress.class: "nginx"
  - host: nginx-1.mydomain.com
      - path: /
          serviceName: nginx-1-service
          servicePort: 80
The text in red are example values, change them into your own equivalent.

The yaml script wil do 3 things:
  1. Create an app/pod called nginx-1, which is a web server
  2. It will create a service to open port with the kubernetes cluster
  3. It will create an ingress entry called nginx-1.mydomain.com (mydomain.com should changed to your own domain name)
Apply the script via the following command:
kubectl apply -f deploy-nginx-1-k8s.yml
After running the script you check the ingress entry via the command
kubectl get ingress 
You should see something similar like the text below. If the external ip is empty wait a minute and try again, until you seen an ip address as an external ip.

PS C:\Users\erik> kubectl get ingress
NAME      CLASS    HOSTS                  ADDRESS         PORTS     AGE
nginx-1   <none>   nginx-1.mydomain.com    80        17h
The nginx controller has exposed the nginx-1 app via the hostname nginx-1.mydomain.com on port 80 via the ingress-controller.

The check if its working you should go to your browser and type http://nginx-1.mydomain.com. (mydomain.com should be replaced with your own domain) you should see default nginx html page, like the example below.

So if everything went ok, you now have exposed the nginx webpage via your kubernetes ingress controller to the Internet.

If you have any questions, do not hesitate to leave a comment.

In the next post I will be writing how-to setup cert-manager on a kubernetes cluster, and configure it to generate ssl certificates for your websites automatically.


  1. helm repo add is not working for that url

    1. Anonymous4:38 PM

      Looks like the chart repository has been changed. I haven't tested it yet, but

      helm repo add center https://repo.chartcenter.io

      should be changed to:

      helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

    2. Anonymous9:00 PM

      I have updated the script with the new helm repository. It should be working again.

  2. When I try to access my url for nginx-1 it comes up with a username/password prompt... any idea how to stop this?

    1. Anonymous9:45 PM

      Are you opening your site with http:// of https:// ? It should with http:// .

    2. I'm using http://

    3. Anonymous4:35 PM

      Strange I haven't had this issue. I will see if I can try to reproduce it somewhere next week.


Post a Comment