Kubernetes Ingress — Routing External Traffic

Sanjeev SharmaSanjeev Sharma
4 min read

Advertisement

Kubernetes Ingress — Routing External Traffic

Ingress manages external HTTP/HTTPS access to services. Learn routing rules, SSL termination, and load balancing.

Introduction

Ingress provides HTTP and HTTPS routes to services within a cluster. It's the standard way to expose applications to external users.

Ingress Basics

Simple Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /

spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

Installing Nginx Ingress Controller

# Add Helm repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Install nginx ingress controller
helm install nginx-ingress ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --create-namespace

# Check installation
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx

Routing Rules

Path-Based Routing

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-routing
spec:
  ingressClassName: nginx
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 3000

      - path: /admin
        pathType: Prefix
        backend:
          service:
            name: admin-service
            port:
              number: 8080

Host-Based Routing

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: host-routing
spec:
  ingressClassName: nginx
  rules:
  - host: web.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 3000

  - host: admin.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: admin-service
            port:
              number: 8080

Exact vs Prefix Path Matching

paths:
# Exact match: only /api
- path: /api
  pathType: Exact
  backend:
    service:
      name: api-service
      port:
        number: 3000

# Prefix match: /api, /api/users, /api/posts, etc
- path: /api
  pathType: Prefix
  backend:
    service:
      name: api-service
      port:
        number: 3000

SSL/TLS Termination

TLS with Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - example.com
    secretName: example-tls

  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

Create TLS Secret

# Generate self-signed certificate
openssl req -x509 -newkey rsa:4096 -nodes \
  -out cert.pem -keyout key.pem -days 365 \
  -subj "/CN=example.com"

# Create secret
kubectl create secret tls example-tls \
  --cert=cert.pem \
  --key=key.pem

# Verify
kubectl get secret example-tls

Certificate Management with Cert-Manager

# Install cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml

# Create ClusterIssuer
kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx
EOF

Use cert-manager:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"

spec:
  tls:
  - hosts:
    - example.com
    secretName: example-tls

  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

Advanced Ingress Features

Rewrite Rules

metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2

rules:
- host: example.com
  http:
    paths:
    - path: /api(/|$)(.*)
      pathType: Prefix
      backend:
        service:
          name: api-service
          port:
            number: 3000

Rate Limiting

metadata:
  annotations:
    nginx.ingress.kubernetes.io/limit-rps: "10"
    nginx.ingress.kubernetes.io/limit-connections: "5"

Authentication

metadata:
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required'
# Create basic auth secret
htpasswd -c auth admin
kubectl create secret generic basic-auth --from-file=auth

CORS

metadata:
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE"
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"

Ingress Best Practices

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: production-ingress
  annotations:
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"

spec:
  ingressClassName: nginx

  tls:
  - hosts:
    - api.example.com
    secretName: api-tls

  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 3000

Debugging Ingress

# View Ingress resources
kubectl get ingress

# Describe ingress
kubectl describe ingress simple-ingress

# View ingress details
kubectl get ingress -o yaml

# Check ingress controller logs
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx

# Test ingress routing
curl -H "Host: example.com" http://ingress-ip

FAQ

Q: What's the difference between Service and Ingress? A: Services expose pods within cluster or via NodePort. Ingress is HTTP/HTTPS layer providing domain-based routing and SSL termination.

Q: Do I need an Ingress controller installed? A: Yes. Default is Nginx, but many alternatives exist (HAProxy, Traefik, etc).

Q: Can I use multiple Ingress controllers? A: Yes, using ingressClassName to specify which controller handles each Ingress.

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro