NGINX Ingress Controller

How to set up an Nginx Ingress on E2E Kubernetes and demonstrate host-based routing protocol

Introduction

Kubernetes Ingress is an API object that provides routing rules to manage access to the services within a Kubernetes cluster. This typically uses HTTPS and HTTP protocols to facilitate the routing.

Ingress is the ideal choice for a production environment. Users can expose services within the Kubernetes cluster without having to create multiple load balancers or manually exposing services.

Moreover, K8s Ingress offers a single entry point for the cluster, allowing administrators to manage the applications easily and diagnose any routing issues. This decreases the attack surface of the cluster, automatically increasing the overall security.

Some use cases of Kubernetes Ingress include:

-Providing externally reachable URLs for services

-Load balancing traffic

-Offering name-based virtual hosting

-Terminating SSL (secure sockets layer) or TLS (transport layer security)

Prerequisites

Before you begin with this guide, you should have the following available to you:

Provision E2E Kubernetes cluster with any available versions this will serve as the platform for deploying your service workloads. Once the cluster is up and running, download the cluster configuration file (kubeconfig.yaml) from the E2E Kubernetes dashboard section and place it in the standard location: ~/.kube/config on your local machine.

Ensure that kubectl command-line tool Installed on your local machine and configured to connect to your cluster. You can read more about installing kubectl in the Official documentation.

Need to reserve and attach an LB IP through k8s LB IP section to expose a service externally via ingress.

Please find the detailed steps over here to provision LB IP.

A domain name and DNS A records which you can point to the E2E K8s LB IP used by the Ingress. If you are using E2E to manage your domain’s DNS records, consult the following article to for more information.

Architecture Reference :

../_images/Ingress-Architecture.png

Step 1 : Installing the Kubernetes Nginx Ingress Controller

Now install the Kubernetes-maintained Nginx Ingress Controller using Helm.

An ingress controller acts as a reverse proxy and load balancer. It implements a Kubernetes Ingress. The ingress controller adds a layer of abstraction to traffic routing, accepting traffic from outside the Kubernetes platform and load balancing it to Pods running inside the platform. It converts configurations from Ingress resources into routing rules that reverse proxies can recognize and implement.

Installing the Nginx Ingress Controller using Helm

Add the ingress-nginx Helm repository

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

Update the Helm repository

helm repo update ingress-nginx

Install the Nginx Ingress Controller with specific settings

helm install --set controller.watchIngressWithoutClass=true --namespace ingress-nginx --create-namespace ingress-nginx ingress-nginx/ingress-nginx

List the Helm releases (deployments) installed in the ingress-nginx namespace

helm list -n ingress-nginx

Once the nginx ingress installation has been done few components like nginx controller pod, nginx controller service is in created by assigning one of the attached LB IP.

../_images/ingress-namespace-components.png

Here one of your available LB IP 116.204.172.97 has been assigned to ingress controller service. Let us try to access the service ip using curl.

../_images/ingress-namespace-components2.png

!! We get 404 error because the ingress controller has no ingress routes configured yet.

To avoid this error response we can configure default backend service.

Example: When a request comes into the cluster that doesn’t match any specified rules in your Ingress resources (e.g., no matching host or path), the Ingress controller doesn’t know where to route that request. Instead of returning an error or leaving the request hanging, it sends the traffic to the default backend service.

Step 2 : Creating default backend and static frontend app deployments for host based routing.

Creating default backend deployment for handling error 404 not found error.

echo "---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: default-backend
 labels:
   app.kubernetes.io/name: default-backend
   app.kubernetes.io/part-of: default-backend
spec:
 replicas: 1
 selector:
   matchLabels:
     app.kubernetes.io/name: default-backend
     app.kubernetes.io/part-of: default-backend
 template:
   metadata:
     labels:
       app.kubernetes.io/name: default-backend
       app.kubernetes.io/part-of: default-backend
   spec:
     containers:
     - name: default-backend
       image: k8s.gcr.io/defaultbackend-amd64:1.5
       ports:
       - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
 name: default-backend
 labels:
   app.kubernetes.io/name: default-backend
   app.kubernetes.io/part-of: default-backend
spec:
 ports:
 - port: 80
   protocol: TCP
   targetPort: 8080
 selector:
   app.kubernetes.io/name: default-backend
   app.kubernetes.io/part-of: default-backend
" | kubectl apply -f -

Creating frontend app deployment called nginxhello-blue

echo "---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginxhello-blue
 labels:
   app.kubernetes.io/name: nginxhello-blue
   app.kubernetes.io/part-of: nginxhello-blue
spec:
 replicas: 1
 selector:
   matchLabels:
     app.kubernetes.io/name: nginxhello-blue
     app.kubernetes.io/part-of: nginxhello-blue
 template:
   metadata:
     labels:
       app.kubernetes.io/name: nginxhello-blue
       app.kubernetes.io/part-of: nginxhello-blue
   spec:
     containers:
     - name: nginxhello-blue
       image: suryaprakash116/blue-container
       ports:
       - containerPort: 80
       env:
       - name: NODE_NAME
         valueFrom:
           fieldRef:
             fieldPath: spec.nodeName
       - name: COLOR
         value: blue
---
apiVersion: v1
kind: Service
metadata:
 name: nginxhello-blue
 labels:
   app.kubernetes.io/name: nginxhello-blue
   app.kubernetes.io/part-of: nginxhello-blue
spec:
 ports:
 - port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app.kubernetes.io/name: nginxhello-blue
   app.kubernetes.io/part-of: nginxhello-blue
" | kubectl apply -f -

Creating frontend app deployment called nginxhello-red

echo "---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginxhello-red
 labels:
   app.kubernetes.io/name: nginxhello-red
   app.kubernetes.io/part-of: nginxhello-red
spec:
 replicas: 1
 selector:
   matchLabels:
     app.kubernetes.io/name: nginxhello-red
     app.kubernetes.io/part-of: nginxhello-red
 template:
   metadata:
     labels:
       app.kubernetes.io/name: nginxhello-red
       app.kubernetes.io/part-of: nginxhello-red
   spec:
     containers:
     - name: nginxhello-red
       image: suryaprakash116/blue-container
       ports:
       - containerPort: 80
       env:
       - name: NODE_NAME
         valueFrom:
           fieldRef:
             fieldPath: spec.nodeName
       - name: COLOR
         value: red
---
apiVersion: v1
kind: Service
metadata:
 name: nginxhello-red
 labels:
   app.kubernetes.io/name: nginxhello-red
   app.kubernetes.io/part-of: nginxhello-red
spec:
 ports:
 - port: 80
   protocol: TCP
   targetPort: 80
 selector:
   app.kubernetes.io/name: nginxhello-red
   app.kubernetes.io/part-of: nginxhello-red
" | kubectl apply -f -

Step 3 : Configuring DNS for Host-Based Routing.

Now we have done the required application deployments. Before creating ingress rule to expose the service in host based path manner here we have to map the following ingress-nginx-controller external service IP your domain name like example.com using DNS Management Portal in E2E dashboard. Creating A record to perform host based routing for both backend service nginxhello-red and nginxhello-blue

../_images/DNS-Record.png

Step 4: Creating ingress rule for host-based routing for both application backend services.

echo "apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: host-rule-ingress
spec:
 defaultBackend:
   service:
     name: default-backend
     port:
       number: 80
 rules:
 - host: blue.dsquarezone.online
   http:
     paths:
     - backend:
         service:
           name: nginxhello-blue
           port:
             number: 80
       pathType: ImplementationSpecific
 - host: red.dsquarezone.online
   http:
     paths:
     - backend:
         service:
           name: nginxhello-red
           port:
             number: 80
       pathType: ImplementationSpecific
" | kubectl apply -f -

Now we can access our application named nginxhello-blue on this url http://blue.dsquarezone.online/ and nginxhello-red on this url http://red.dsquarezone.online/

../_images/Helloblue.png ../_images/Hellored.png

Step 5: Create an ingress rule for the default backend service to handle invalid url requests.

echo "apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: single-default-backend-ingress
spec:
 defaultBackend:
   service:
     name: default-backend
     port:
       number: 80" | kubectl apply -f -

Check that our ingress controller handles the invalid request to the default backend service using url.

../_images/default.png