Skip to main content

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 an 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 the kubectl command-line tool is installed on your local machine and configured to connect to your cluster. You can read more about installing kubectl in the Official documentation.

  • Reserve and attach an LB IP through the K8s LB IP section to expose a service externally via ingress. Please find the detailed steps here.

  • 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 for more information.

Architecture Reference:

Ingress Architecture

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.

Ingress Namespace Components

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

Ingress Namespace Components 2

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

To avoid this error response, we can configure a 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 a default backend deployment for handling the 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 that we have completed the required application deployments, before creating the ingress rule to expose the services in a host-based manner, we need to map the ingress-nginx-controller external service IP to your domain name (like example.com) using the DNS Management Portal in the E2E dashboard.

Creating an A record to perform host-based routing for both backend services, nginxhello-red and nginxhello-blue.

DNS Record

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/

Hello Blue

Hello Red

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.

default