📝 Kubernetes

Ingress: HTTP Routing in Kubernetes

P
Author
Pyland
📅
Published
30.06.2026
⏱️
Reading time
2 min
👁️
Views
80
🌳
Level
Advanced

You have 5 microservices, each needing external access. Creating 5 LoadBalancers is expensive and unwieldy. Ingress lets you funnel all HTTP/HTTPS traffic through a single load balancer, distributing it to services based on URL rules.

Why Ingress

Without Ingress: every LoadBalancer Service means a separate external IP and a separate load balancer. 5 services = 5 IP addresses = 5 billable LBs at your cloud provider.

With Ingress:

Internet → 1 IP (LoadBalancer) → Ingress Controller
                                    ├── /api     → backend-service:8000
                                    ├── /static  → frontend-service:3000
                                    └── /admin   → admin-service:8080

One IP, one load balancer, routing by URL or hostname.

Ingress Controller

An Ingress is a K8s object containing routing rules. By itself it does nothing.

An Ingress Controller is a Pod (typically nginx, Traefik, or HAProxy) that reads Ingress rules and actually routes traffic.

Installing the nginx Ingress Controller

# Via Helm (recommended)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --create-namespace

# Or via a manifest
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.5/deploy/static/provider/cloud/deploy.yaml

# Verify
kubectl get pods -n ingress-nginx
# NAME                                        READY   STATUS    AGE
# ingress-nginx-controller-7d4db76476-xq2jk   1/1     Running   2m

kubectl get svc -n ingress-nginx
# NAME                       TYPE           EXTERNAL-IP
# ingress-nginx-controller   LoadBalancer   34.123.45.67

For minikube:

minikube addons enable ingress

Path-Based Routing (by URL)

# ingress-path.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: backend-service
                port:
                  number: 8000
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 3000
kubectl apply -f ingress-path.yaml

kubectl get ingress
# NAME          CLASS   HOSTS   ADDRESS         PORTS   AGE
# app-ingress   nginx   *       34.123.45.67    80      2m

Now:
- http://34.123.45.67/api/users → backend-service
- http://34.123.45.67/ → frontend-service

Host-Based Routing (by Domain)

# ingress-host.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-host-ingress
spec:
  ingressClassName: nginx
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 8080
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 3000
    - host: admin.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: admin-service
                port:
                  number: 8081

Requests are routed based on the Host header:
- api.example.com → api-service
- app.example.com → frontend-service
- admin.example.com → admin-service

TLS/SSL Configuration

Step 1: Create a Secret with the Certificate

# Self-signed (for testing)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=example.com/O=example"

kubectl create secret tls example-tls \
  --cert=tls.crt \
  --key=tls.key

Step 2: Ingress with TLS

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - api.example.com
        - app.example.com
      secretName: example-tls
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 8080

Automatic Certificates with cert-manager

# Install cert-manager
helm repo add jetstack https://charts.jetstack.io
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true
# ClusterIssuer for Let's Encrypt
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
# Ingress with automatic certificate
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - api.example.com
      secretName: api-tls   # cert-manager will create this Secret automatically

Useful nginx Ingress Annotations

metadata:
  annotations:
    # Limit request body size
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    # Timeout
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    # Rate limiting
    nginx.ingress.kubernetes.io/limit-rps: "10"
    # Basic Auth
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    # CORS
    nginx.ingress.kubernetes.io/enable-cors: "true"

Your reaction to the article

💬 Comments (0)

🔐 Sign in to leave a comment
🚪 Login
💭

No comments yet

Be the first to share your opinion about this article!

🔗 Similar

Similar articles

Continue learning with these materials

📝

AI Agents: ReAct Loop and Autonomous Actions

A chatbot answers questions. An agent takes action: it calls tools, retrieves real data, and...

📅 30.06.2026 👁️ 101
📝

RAG: Chatting with Documents via Vector Search

RAG (Retrieval-Augmented Generation) is a pattern for working with your own documents. Instead of fine-tuning...

📅 30.06.2026 👁️ 94
📝

Health Checks: Liveness and Readiness in Kubernet…

A container is running — that does not mean the application is working. There might...

📅 30.06.2026 👁️ 93

Did you like the article?

Subscribe to our updates and receive new articles first. Grow with PyLand!