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 installingkubectl
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:
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.
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
.
!! 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
.
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/
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.