Setting Up an Ingress Controller with Advanced Routing in Kubernetes

Introduction

In a Kubernetes environment, managing external access to multiple services efficiently is crucial. This post walks through setting up the NGINX Ingress Controller in minikube with advanced routing rules, including authentication and rate limiting. By the end of this guide, you’ll have a working setup where different services are exposed through a single Ingress with sophisticated HTTP routing.

Step 1: Deploying the NGINX Ingress Controller

Minikube does not include an Ingress controller by default, so we need to enable it:

minikube addons enable ingress

Verify the Ingress controller is running:

kubectl get pods -n kube-system | grep ingress

Expected output:

NAME                           READY   STATUS    RESTARTS   AGE
ingress-nginx-controller-xx     1/1     Running   0          2m

Step 2: Deploying Sample Applications

We’ll create two sample deployments with simple HTTP responses.

app-one.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-one
  labels:
    app: app-one
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-one
  template:
    metadata:
      labels:
        app: app-one
    spec:
      containers:
      - name: app-one
        image: hashicorp/http-echo
        args:
        - "-text=Hello from App One"
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: app-one
spec:
  selector:
    app: app-one
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
Click Here to Copy YAML

app-two.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-two
  labels:
    app: app-two
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app-two
  template:
    metadata:
      labels:
        app: app-two
    spec:
      containers:
      - name: app-two
        image: hashicorp/http-echo
        args:
        - "-text=Hello from App Two"
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: app-two
spec:
  selector:
    app: app-two
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
Click Here to Copy YAML

Apply these configurations:

kubectl apply -f app-one.yaml
kubectl apply -f app-two.yaml

Step 3: Creating the Advanced Ingress

Now, we’ll create an Ingress resource to route traffic based on the request path.

advanced-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: advanced-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/limit-rps: "5"  # Rate limiting: max 5 requests per second
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.local
    http:
      paths:
      - path: /app-one
        pathType: Prefix
        backend:
          service:
            name: app-one
            port:
              number: 80
      - path: /app-two
        pathType: Prefix
        backend:
          service:
            name: app-two
            port:
              number: 80
Click Here to Copy YAML

Apply the Ingress:

kubectl apply -f advanced-ingress.yaml

Check if the Ingress is created:

kubectl get ingress

Expected output:

NAME            CLASS   HOSTS         ADDRESS        PORTS   AGE
advanced-ingress nginx   myapp.local   192.168.49.2   80      5s

Step 4: Testing the Ingress

First, update your /etc/hosts file to map myapp.local to Minikube’s IP:

echo "$(minikube ip) myapp.local" | sudo tee -a /etc/hosts

Test the routes:

curl -H "Host: myapp.local" http://myapp.local/app-one
curl -H "Host: myapp.local" http://myapp.local/app-two

Expected responses:

Hello from App One
Hello from App Two

Step 5: Enforcing Basic Authentication

To secure access, we add Basic Authentication for app-one.

First, create a username-password pair:

echo "admin:$(openssl passwd -stdin -apr1)" | kubectl create secret generic my-auth-secret --from-file=auth -n default

Modify advanced-ingress.yaml to enforce authentication:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: advanced-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/limit-rps: "5"
    nginx.ingress.kubernetes.io/auth-type: "basic"
    nginx.ingress.kubernetes.io/auth-secret: "my-auth-secret"
    nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.local
    http:
      paths:
      - path: /app-one
        pathType: Prefix
        backend:
          service:
            name: app-one
            port:
              number: 80
      - path: /app-two
        pathType: Prefix
        backend:
          service:
            name: app-two
            port:
              number: 80
Click Here to Copy YAML

Reapply the Ingress:

kubectl apply -f advanced-ingress.yaml

Test authentication:

curl -u admin:your-password -H "Host: myapp.local" http://myapp.local/app-one

If correct, it will return:

Hello from App One

Without credentials, it returns:

401 Unauthorized

Conclusion

By following this guide, we have:

✅ Deployed an NGINX Ingress Controller in Minikube.
✅ Configured multiple applications behind a single Ingress resource.
✅ Implemented rate limiting to control excessive requests.
✅ Secured an endpoint using Basic Authentication.

These techniques are essential when deploying microservices in production environments. You can further extend this setup with TLS termination, JWT authentication, or OAuth integration.

Let me know in the comments if you have any questions!👇

Leave a comment