K8s Ingress: Routing, TLS, and Controllers
Configure Kubernetes Ingress for HTTP routing, TLS termination, and path-based routing. Covers NGINX, Traefik, and HAProxy ingress controllers.
π‘ Quick Answer: Configure Kubernetes Ingress for HTTP routing, TLS termination, and path-based routing. Covers NGINX, Traefik, and HAProxy ingress controllers.
The Problem
This is one of the most searched Kubernetes topics. Having a comprehensive, well-structured guide helps both beginners and experienced users quickly find what they need.
The Solution
Install NGINX Ingress Controller
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx --create-namespaceBasic Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- host: other.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: other-app
port:
number: 80TLS with cert-manager
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: secure-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 80
---
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: nginxRate Limiting & Security
metadata:
annotations:
nginx.ingress.kubernetes.io/rate-limit: "10"
nginx.ingress.kubernetes.io/rate-limit-window: "1m"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"graph LR
A[Client] -->|HTTPS| B[Ingress Controller]
B -->|Host: app.example.com| C[app Service]
B -->|Host: api.example.com| D[api Service]
B -->|Path: /docs| E[docs Service]
C --> F[Pod 1]
C --> G[Pod 2]
D --> H[Pod 3]Path Types
pathType controls how the path is matched:
# Exact matching β path must match exactly
- path: /api/v1/users
pathType: Exact
backend:
service:
name: users-v1
port:
number: 80
# Prefix matching β matches the URL path prefix (most common)
- path: /api/v1
pathType: Prefix
backend:
service:
name: api-v1
port:
number: 80URL Rewriting
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rewrite-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
# /api/users -> /users
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-service
port:
number: 80Canary Deployments
Weight-based canary splits traffic between a main and canary Ingress pointing at different Services:
# Main ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-ingress
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service: {name: main-service, port: {number: 80}}
---
# Canary ingress (10% of traffic)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-ingress
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service: {name: canary-service, port: {number: 80}}Header-based canary routes to the canary Service whenever a specific header is present, instead of splitting by weight:
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
nginx.ingress.kubernetes.io/canary-by-header-value: "true"Session Affinity
metadata:
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/affinity-mode: "persistent"
nginx.ingress.kubernetes.io/session-cookie-name: "SERVERID"
nginx.ingress.kubernetes.io/session-cookie-max-age: "3600"Basic Authentication
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auth-ingress
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
spec:
ingressClassName: nginx
rules:
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service: {name: admin-service, port: {number: 80}}htpasswd -c auth admin
kubectl create secret generic basic-auth --from-file=authDefault Backend
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-with-default
spec:
ingressClassName: nginx
defaultBackend:
service: {name: default-service, port: {number: 80}}
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service: {name: api-service, port: {number: 80}}Debug Ingress
kubectl get ingress
kubectl describe ingress my-ingress
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
curl -H "Host: app.example.com" http://<ingress-ip>/
kubectl exec -n ingress-nginx <nginx-pod> -- cat /etc/nginx/nginx.confFrequently Asked Questions
What is the difference between Ingress and Service?
A Service provides internal load balancing and DNS within the cluster. An Ingress provides external HTTP/HTTPS routing with host-based and path-based rules, TLS termination, and virtual hosting.
Ingress vs Gateway API?
Gateway API is the successor to Ingress with more features: cross-namespace routing, traffic splitting, header-based matching. Ingress is simpler and more widely supported today.
Do I need an Ingress Controller?
Yes. The Ingress resource is just configuration β you need a controller (NGINX, Traefik, HAProxy, or cloud-specific) to implement it.
Best Practices
- Start simple β use the basic form first, add complexity as needed
- Be consistent β follow naming conventions across your cluster
- Document your choices β add annotations explaining why, not just what
- Monitor and iterate β review configurations regularly
Key Takeaways
- This is fundamental Kubernetes knowledge every engineer needs
- Start with the simplest approach that solves your problem
- Use
kubectl explainandkubectl describewhen unsure - Practice in a test cluster before applying to production

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
