Ingress + Gateway API cheatsheet.
Why Ingress
LoadBalancer per service = expensive + scattered. Ingress = one LB + L7 routing.
ingress-nginx
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx --create-namespace
Other options: Traefik, HAProxy, Istio, Contour.
Basic Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port: { number: 80 }
Multiple paths
spec:
rules:
- host: example.com
http:
paths:
- path: /api
pathType: Prefix
backend: { service: { name: api, port: { number: 80 } } }
- path: /
pathType: Prefix
backend: { service: { name: web, port: { number: 80 } } }
TLS
spec:
tls:
- hosts: [example.com]
secretName: web-tls
rules:
- host: example.com
http: ...
Create TLS secret:
kubectl create secret tls web-tls --cert=cert.pem --key=key.pem
cert-manager (auto TLS)
helm install cert-manager jetstack/cert-manager -n cert-manager --create-namespace --set crds.enabled=true
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata: { name: letsencrypt-prod }
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef: { name: letsencrypt-prod }
solvers:
- http01:
ingress: { class: nginx }
Annotate Ingress:
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
Cert-manager auto-creates and renews TLS secret.
Common annotations (ingress-nginx)
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
nginx.ingress.kubernetes.io/limit-rps: "100"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "X-Frame-Options: DENY";
Default backend
For unmatched paths:
spec:
defaultBackend:
service:
name: 404-page
port: { number: 80 }
Wildcard host
rules:
- host: "*.example.com"
http: ...
Path types
Exact: exact match.Prefix: path prefix match.ImplementationSpecific: vendor-specific.
IngressClass
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata: { name: nginx }
spec:
controller: k8s.io/ingress-nginx
Multiple ingress controllers can coexist via different IngressClasses.
Gateway API (modern replacement)
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata: { name: my-gateway }
spec:
gatewayClassName: nginx
listeners:
- name: http
protocol: HTTP
port: 80
- name: https
protocol: HTTPS
port: 443
tls:
certificateRefs:
- { name: web-tls }
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata: { name: web }
spec:
parentRefs: [{ name: my-gateway }]
hostnames: [example.com]
rules:
- matches:
- path: { type: PathPrefix, value: /api }
backendRefs:
- { name: api, port: 80 }
- matches:
- path: { type: PathPrefix, value: / }
backendRefs:
- { name: web, port: 80 }
Gateway API is the modern successor. Supports cross-namespace, traffic splitting, header routing.
Traffic splitting (canary)
backendRefs:
- name: web-stable
port: 80
weight: 90
- name: web-canary
port: 80
weight: 10
10% to canary version.
Header / query routing
matches:
- headers:
- name: X-User-Tier
value: premium
backendRefs: [{ name: web-premium, port: 80 }]
Rate limiting
ingress-nginx:
annotations:
nginx.ingress.kubernetes.io/limit-rps: "10"
nginx.ingress.kubernetes.io/limit-burst-multiplier: "2"
Or via service mesh / dedicated rate-limiting middleware.
CORS
annotations:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://app.example.com"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
external-dns
Auto-creates DNS records pointing to Ingress LB:
helm install external-dns oci://registry-1.docker.io/bitnamicharts/external-dns \
--set provider=cloudflare \
--set cloudflare.apiToken=...
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: example.com
Common mistakes
- Wrong
ingressClassName→ 404. - TLS secret in wrong namespace.
path: /withoutpathType(older API).- Missing rewrite annotations → backend gets wrong path.
- Multiple ingress controllers without class differentiation.
Read this next
If you want my Ingress + cert-manager templates, they’re at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .