Introduction to NGINX
What is ingress?
Ingress is like the main door in the building with signs that tells you which room to go to.
This is more clear in the context of the cluster. Lets say in our kubernetes cluster, we have many applications hosted, like a blog, a ecommerce store and a portfolio site. Any incoming request needs to be redirected to the right application. Ingress is what performs this task.
NGINX is the application that enforces the ingress. In the building analogy, NGINX is the security guard in the building that looks at the incoming request and directs them to the right room based on the ingress rules.
Usage
Following use cases:
- to expose multiple applications hosted in a cluster;
- route traffic based on different URLs or domains that have same base URL.
- add TLS/SSL to your application
- manage load balancing to your services
Hands On: Kubernetes Cluster
Install Minikube
Let us first set up a simple kubernetes cluster to demonstrate the use of nginx ingress controller.
In a linux machine, run the following commands to install minikube:
-
First download:
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
-
Then, install
sudo install minikube-linux-amd64 /usr/local/bin/minikube
Create a kube cluster
Let us create a simple kube cluster. Since we do not want to create any VMs, let us use --driver=none option to start minikube.
minikube start --driver=none --container-runtime=containerd
-
The above command might be greeted with the following error.
Exiting due to GUEST_MISSING_CONNTRACK: Sorry, Kubernetes 1.32.0 requires conntrack to be installed in root's path
This can be mitigated by installing conntrack using following command:sudo apt install conntrack -y
-
Please also check for the containerd toml file. If it does not exist, we can create one manually as follows
mkdir -p /etc/containerd sudo containerd config default | sudo tee /etc/containerd/config.toml
If the minikube command runs correctly, it will install kubectl and point the config to the local cluster so that we can use kubectl command.
minikube kubectl -- get nodes -A -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME vmname Ready control-plane 5m35s v1.32.0 <ip> Ubuntu 22.04.4 LTS 5.15.0-1058-ibm containerd://1.7.24
At this point, basic kube control plane pods are running in the cluster.
Deploy NGINX
Let us deploy NGINX ingress controller in our cluster. We will use help for this purpose, which is a package manager for kubernetes.
Let us first download helm:
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
The above command will add help into the binary location, so helm should be readily usable now.Then, let us download and install nginx ingress in our cluster.
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update helm install nginx-ingress ingress-nginx/ingress-nginx
If we check the current running pods, we should see following:# minikube kubectl -- get po -A NAMESPACE NAME READY STATUS RESTARTS AGE default nginx-ingress-ingress-nginx-controller-78d94b756c-r4gzt 1/1 Running 0 59s
Running Our Apps with Exposed Ports
Here, we will run two applications each of which will have port 80 exposed. For the sake of ease, we will run a simple nginx container and expose their port 80.
To expose the port, we will create a SERVICE type object along with the deployment of the application.
Our first application definition and service definition in file app1.yaml.
# cat app1.yaml apiVersion: apps/v1 kind: Deployment metadata: name: app1 spec: replicas: 1 selector: matchLabels: app: app1 template: metadata: labels: app: app1 spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: app1-service spec: selector: app: app1 ports: - protocol: TCP port: 80 targetPort: 80 type: ClusterIP
Our second application, which is basically the copy of the first application but with a different name.apiVersion: apps/v1 kind: Deployment metadata: name: app2 spec: replicas: 1 selector: matchLabels: app: app2 template: metadata: labels: app: app2 spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: app2-service spec: selector: app: app2 ports: - protocol: TCP port: 80 targetPort: 80 type: ClusterIP
Let us apply the yaml files so that apps are created.# minikube kubectl -- apply -f app1.yaml deployment.apps/app1 created service/app1-service created # minikube kubectl -- apply -f app2.yaml deployment.apps/app2 created service/app2-service created
Create INGRESS object to direct request
At this point, we have created applications with exposed ports. But if any external requests are to access the applications, we need to define some rules so that the requests are properly routed. Going back to the building analogy, we need to create the sign at the door to tell which room to go to.
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: multi-app-ingress spec: rules: - host: app1.local http: paths: - path: / pathType: Prefix backend: service: name: app1-service port: number: 80 - host: app2.local http: paths: - path: / pathType: Prefix backend: service: name: app2-service port: number: 80
The above ingress object routes any requests coming to app1.local to app1-service port number 80, which in turn routes it to our application 1. Similar is the case for app2.
Apply the yaml file for ingress object above similar to how we applied for deployment creation in earlier section.
Update /etc/hosts
Just so that our requests are properly decoded by our local DNS server, we should add following entries into our /etc/hosts file.
127.0.0.1 app1.local 127.0.0.1 app2.local