Deploying and Configuring ingress-nginx for Kubernetes Ingress Management

Traditional NodePort services in Kubernetes face critical limitations: each service requires a dedicated port, leading to port exhaustion, and they operate only at Layer 4 (TCP/UDP), lacking HTTP-aware routing capabilities. Ingress addresses these gaps by providing a Layer 7 HTTP(S) routing layer that abstracts external access through domain-based rules and centralized control.

Ingress resources themself are declarative configurations—they define routing rules but require an Ingress Controller to enforce them. The controller acts as a reverse proxy and load balancer, typically based on NGINX, Traefik, or Istio. For this guide, we use the official Kubernetes-maintained NGINX Ingress Controller.

To deploy the controller:

  • Use a container image hosted in a domestic registry (e.g., lizhenliang/nginx-ingress-controller:0.20.0) to avoid pull failures.
  • Enable hostNetwork: true so the controller binds directly to the host’s network interfaces on ports 80 and 443.
kubectl apply -f ingress-controller.yaml
kubectl get pods -n ingress-nginx

After deployment, verify the controller is listening:

netstat -natp | grep -E ":80|:443"
# Output shows nginx listening on 0.0.0.0:80 and 0.0.0.0:443

These ports now serve as the entry point for all HTTP/HTTPS traffic destined for cluster services.

Configuring Ingress Rules

An Ingress resource maps hostnames and paths to backend services. Core components include:

  • host: The domain name used to access the service
  • serviceName: The Kubernetes Service name
  • servicePort: The port exposed by the Service

HTTP Routing

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: http-ingress
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web-app
          servicePort: 80

In production, point the domain’s A record to a Node with the Ingress Controller. For testing, override DNS locally via /etc/hosts:

192.168.31.62 app.example.com

HTTPS with TLS Termination

First, generate a certificate using CFSSL:

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
chmod +x cfssl* && mv cfssl* /usr/bin/

cat > ca-config.json <<eof auth="" cat="" encipherment="" eof=""> ca-csr.json <<eof ca="" ca-csr.json="" cat="" cfssl="" cfssljson="" eof="" gencert=""> app.example.com-csr.json <<eof app-tls="" app.example.com="" app.example.com-csr.json="" cfssl="" cfssljson="" create="" eof="" gencert="" kubectl="" secret="" tls=""></eof></eof></eof>

Then reference the secret in the Ingress:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: tls-ingress
spec:
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web-app
          servicePort: 80

Path-Based Routing

Route different URL paths to seperate services:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: path-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /v1
        backend:
          serviceName: service-v1
          servicePort: 80
      - path: /v2
        backend:
          serviceName: service-v2
          servicePort: 80

Name-Based Virtual Hosts

Host multiple domains on the same IP:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: vhost-ingress
spec:
  rules:
  - host: site1.example.com
    http:
      paths:
      - backend:
          serviceName: service-a
          servicePort: 80
  - host: site2.example.com
    http:
      paths:
      - backend:
          serviceName: service-b
          servicePort: 80

Customizing Behavior with Annotations

NGINX Ingress supports fine-grained tuning via annotations:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: tuned-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"  # Disable HTTP→HTTPS redirect
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web-app
          servicePort: 80

High Availability Strategies

Runing a single Ingress Controller creates a single point of failure. Two common solutions:

  1. Active-Passive with Keepalived: Deploy two controllers on dedicated nodes, assign a Virtual IP (VIP) that floats between them.
  2. Load-Balanced Cluster (Recommended): Place a cloud or hardware load balancer (e.g., HAProxy, MetalLB) in front of multiple Ingress Controller replicas. This scales horizontally and eliminates single-node dependencies.

For production environments, always deploy at least two replicas of the Ingress Controller across separate nodes and configure external load balancing to distribute traffic.

Tags: Ingress-Nginx kubernetes ingress nginx TLS

Posted on Mon, 21 Sep 2026 16:17:37 +0000 by Nimbuz