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"
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!