Fatskills
Practice. Master. Repeat.
Study Guide: TECH **Ingress Controllers & Ingress Resources (NGINX, Traefik) – Zero-Fluff Study Guide**
Source: https://www.fatskills.com/kubernetes/chapter/tech-ingress-controllers-ingress-resources-nginx-traefik-zero-fluff-study-guide

TECH **Ingress Controllers & Ingress Resources (NGINX, Traefik) – Zero-Fluff Study Guide**

By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.

⏱️ ~9 min read

Ingress Controllers & Ingress Resources (NGINX, Traefik) – Zero-Fluff Study Guide


1. What This Is & Why It Matters

You’re running a Kubernetes cluster with multiple microservices (e.g., frontend, backend, auth-service). Each service has its own ClusterIP or NodePort, but you need:


  • A single entry point (like a receptionist at a hotel) to route traffic to the right service.
  • HTTPS termination (so users don’t see http:// in their browser).
  • Path-based routing (/apibackend, /loginauth-service).
  • Host-based routing (app.example.comfrontend, api.example.combackend).

Without Ingress, you’d have to: - Expose each service via NodePort (ugly, high port numbers, no HTTPS).
- Use a cloud load balancer per service (expensive, hard to manage).
- Manually configure TLS certificates (error-prone, no automation).

With Ingress, you get: ✅ One load balancer for all services (cost-efficient).
Automatic TLS (via cert-manager + Let’s Encrypt).
Flexible routing rules (path, host, headers).
Production-grade traffic management (rate limiting, rewrites, canary deployments).

Real-world scenario:
You inherit a Kubernetes cluster where every service has its own LoadBalancer. Your cloud bill is $2,000/month just for load balancers. Fix: Replace them with a single Ingress Controller + Ingress Resources.


2. Core Concepts & Components


? Ingress Controller

  • Definition: A Kubernetes-native reverse proxy (like NGINX, Traefik, or AWS ALB) that watches Ingress Resources and configures itself to route traffic.
  • Production insight:
  • If the Ingress Controller crashes, all traffic stops. Run it as a Deployment with multiple replicas.
  • Cloud providers (AWS, GCP, Azure) have managed Ingress Controllers (e.g., AWS ALB Ingress Controller). Use them if you don’t want to manage NGINX/Traefik yourself.

? Ingress Resource

  • Definition: A Kubernetes YAML file that defines routing rules (e.g., "Send /api to backend-service").
  • Production insight:
  • Ingress Resources don’t work without an Ingress Controller. It’s like writing a recipe (Ingress) but having no chef (Controller) to cook it.
  • Common mistake: Forgetting to set kubernetes.io/ingress.class (e.g., nginx or traefik). Without it, the Ingress Controller ignores the rule.

? Service (ClusterIP)

  • Definition: An internal Kubernetes service that exposes a set of Pods on a stable IP.
  • Production insight:
  • Ingress does not replace Services. It routes to them. If your backend-service is misconfigured, Ingress can’t fix it.

? TLS Secret

  • Definition: A Kubernetes Secret containing a TLS certificate (.crt + .key).
  • Production insight:
  • Never commit TLS secrets to Git. Use cert-manager to automate certificate issuance (Let’s Encrypt).
  • If the certificate expires, users see browser warnings. Set up monitoring for kube-secret expiry.

? Annotations

  • Definition: Key-value pairs in Ingress YAML that customize behavior (e.g., nginx.ingress.kubernetes.io/rewrite-target: /).
  • Production insight:
  • Annotations are controller-specific. nginx.ingress.kubernetes.io/... won’t work with Traefik.
  • Common use cases:
    • Rate limiting (nginx.ingress.kubernetes.io/limit-rpm: "100").
    • CORS (nginx.ingress.kubernetes.io/enable-cors: "true").
    • Redirects (nginx.ingress.kubernetes.io/permanent-redirect: https://new.example.com).

? Default Backend

  • Definition: A fallback service that handles unmatched requests (e.g., 404 pages).
  • Production insight:
  • If you don’t set a default backend, users get a generic "404" from the Ingress Controller.
  • Deploy a simple default-backend service (e.g., gcr.io/google_containers/defaultbackend:1.4).

? Path-Based vs. Host-Based Routing

Type Example Use Case
Path-based /api → backend-service Single domain, multiple paths (e.g., example.com/api, example.com/login)
Host-based api.example.com → backend-service Multiple subdomains (e.g., app.example.com, api.example.com)

Production insight:
- Host-based routing is cleaner for microservices (each team owns a subdomain).
- Path-based routing is simpler for monoliths (one domain, many paths).


3. Step-by-Step Hands-On: Deploy NGINX Ingress Controller + Ingress Resource


Prerequisites

✅ A running Kubernetes cluster (Minikube, Kind, EKS, GKE, AKS).
kubectl configured to talk to the cluster.
✅ Helm (for installing NGINX Ingress Controller).

Step 1: Install NGINX Ingress Controller

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

# Install NGINX Ingress Controller (creates a LoadBalancer)
helm install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --create-namespace \
  --set controller.service.type=LoadBalancer

Verify:


kubectl get svc -n ingress-nginx

Expected output:


NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)
ingress-nginx-controller             LoadBalancer   10.96.123.45    123.45.67.89     80:32456/TCP,443:30012/TCP
  • EXTERNAL-IP is your public entry point. If it says <pending>, wait a minute (cloud providers take time to provision a load balancer).

Step 2: Deploy a Sample App (2 Services)

# Deploy "hello-world" service (port 8080)
kubectl create deployment hello-world --image=gcr.io/google-samples/hello-app:1.0
kubectl expose deployment hello-world --port=8080 --name=hello-world

# Deploy "goodbye-world" service (port 8080)
kubectl create deployment goodbye-world --image=gcr.io/google-samples/hello-app:2.0
kubectl expose deployment goodbye-world --port=8080 --name=goodbye-world

Verify:


kubectl get pods,svc

Expected output:


NAME                              READY   STATUS    RESTARTS   AGE
pod/hello-world-xyz123            1/1     Running   0          1m
pod/goodbye-world-abc456          1/1     Running   0          1m

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)
service/hello-world  ClusterIP   10.96.123.100   <none>        8080/TCP
service/goodbye-world ClusterIP  10.96.123.101   <none>        8080/TCP

Step 3: Create an Ingress Resource (Path-Based Routing)

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1 # Removes /hello or /goodbye from the path spec: ingressClassName: nginx # Required for NGINX Ingress Controller rules: - http:
paths:
- path: /hello(/|$)(.*) # Matches /hello, /hello/, /hello/foo
pathType: Prefix
backend:
service:
name: hello-world
port:
number: 8080
- path: /goodbye(/|$)(.*) # Matches /goodbye, /goodbye/, /goodbye/bar
pathType: Prefix
backend:
service:
name: goodbye-world
port:
number: 8080

Apply:


kubectl apply -f ingress.yaml

Verify:


kubectl get ingress

Expected output:


NAME              CLASS   HOSTS   ADDRESS         PORTS   AGE
example-ingress   nginx   *       123.45.67.89    80      1m

Test:


# Get the external IP of the Ingress Controller
INGRESS_IP=$(kubectl get svc -n ingress-nginx ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

# Test /hello
curl http://$INGRESS_IP/hello
# Output: Hello, world! Version: 1.0.0

# Test /goodbye
curl http://$INGRESS_IP/goodbye
# Output: Hello, world! Version: 2.0.0

Step 4: Add TLS (HTTPS)

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

# Create a Kubernetes Secret
kubectl create secret tls example-tls --key tls.key --cert tls.crt

Update ingress.yaml to include TLS:


spec:
  tls:
  - hosts:
- example.com
secretName: example-tls rules: - host: example.com # Now requires a Host header
http:
paths:
- path: /hello
pathType: Prefix
backend:
service:
name: hello-world
port:
number: 8080
- path: /goodbye
pathType: Prefix
backend:
service:
name: goodbye-world
port:
number: 8080

Apply:


kubectl apply -f ingress.yaml

Test with HTTPS:


# Test with curl (ignore self-signed cert warning)
curl -k https://$INGRESS_IP/hello -H "Host: example.com"
# Output: Hello, world! Version: 1.0.0


4. ? Production-Ready Best Practices


Security

  • Use cert-manager (not manual TLS secrets): bash helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set installCRDs=true Then create a ClusterIssuer for Let’s Encrypt: ```yaml 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 ```
  • Restrict Ingress to internal networks (if possible): yaml controller:
    service:
    annotations:
    service.beta.kubernetes.io/aws-load-balancer-internal: "true" # AWS
  • Enable rate limiting to prevent DDoS: yaml annotations:
    nginx.ingress.kubernetes.io/limit-rpm: "100"
    nginx.ingress.kubernetes.io/limit-burst-multiplier: "5"

Cost Optimization

  • Use a single Ingress Controller (not one per namespace).
  • Avoid LoadBalancer for internal services (use ClusterIP + Ingress).
  • Use cloud-managed Ingress Controllers (e.g., AWS ALB Ingress Controller) if you’re already on that cloud.

Reliability & Maintainability

  • Set resource requests/limits for the Ingress Controller: yaml controller:
    resources:
    requests:
    cpu: 100m
    memory: 256Mi
    limits:
    cpu: 1
    memory: 1Gi
  • Use ingressClassName (not deprecated kubernetes.io/ingress.class).
  • Label Ingress Resources for easier filtering: yaml metadata:
    labels:
    app: my-app
    env: prod

Observability

  • Monitor Ingress Controller metrics (Prometheus + Grafana): yaml controller:
    metrics:
    enabled: true
    serviceMonitor:
    enabled: true
  • Log all requests (useful for debugging): yaml controller:
    config:
    access-log-path: "/var/log/nginx/access.log"
    error-log-path: "/var/log/nginx/error.log"
  • Set up alerts for:
  • High 5xx errors (nginx_ingress_controller_requests{status=~"5.."}).
  • High latency (nginx_ingress_controller_request_duration_seconds).


5. ⚠️ Common Mistakes & Traps

Mistake Symptom Fix/Prevention
Forgetting ingressClassName Ingress rules are ignored. Always set spec.ingressClassName: nginx (or traefik).
Using NodePort instead of LoadBalancer for Ingress Controller External traffic can’t reach the cluster. Use LoadBalancer (or ClusterIP + external LB in cloud).
Not setting a default backend Users see a generic 404. Deploy a default-backend service.
Mixing path-based and host-based routing without host Rules conflict. Always specify host if using host-based routing.
Not testing TLS in production Users see "Your connection is not private". Use curl -v to test HTTPS before going live.


6. ? Exam/Certification Focus


Typical Question Patterns

  1. "Which component is responsible for routing traffic to Services?"
  2. ❌ "Ingress Resource" (it’s just a config file).
  3. "Ingress Controller" (it’s the actual proxy).

  4. "How do you expose multiple Services under a single domain?"

  5. ❌ "Use NodePort for each Service."
  6. "Use an Ingress Resource with path-based routing."

  7. "What’s the difference between pathType: Prefix and pathType: Exact?"

  8. Prefix: Matches /foo and /foo/bar.
  9. Exact: Only matches /foo.

  10. "How do you enable HTTPS for an Ingress?"

  11. ❌ "Set spec.tls: true."
  12. "Create a TLS Secret and reference it in spec.tls."

Key ⚠️ Trap Distinctions

Concept NGINX Ingress Traefik Ingress
Annotation prefix nginx.ingress.kubernetes.io/... traefik.ingress.kubernetes.io/...
Default backend Must be manually deployed Built-in (but customizable)
TLS Requires Secret Supports Let’s Encrypt out of the box


7. ? Hands-On Challenge

Challenge:
Deploy a Traefik Ingress Controller and route traffic to two services (app1 and app2) using host-based routing (app1.example.comapp1, app2.example.comapp2).

Solution:


# Install Traefik via Helm
helm repo add traefik https://helm.traefik.io/traefik
helm install traefik traefik/traefik -n traefik --create-namespace

# Deploy two apps
kubectl create deployment app1 --image=gcr.io/google-samples/hello-app:1.0
kubectl expose deployment app1 --port=8080
kubectl create deployment app2 --image=gcr.io/google-samples/hello-app:2.0
kubectl expose deployment app2 --port=8080

# Create Ingress (host-based)
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: traefik-ingress
  annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web spec: rules: - host: app1.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app1
port:
number: 8080 - host: app2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app2
port:
number: 8080 EOF

Why it works:
- Traefik’s Helm chart automatically creates a LoadBalancer.
- Host-based routing ensures app1.example.com and app2.example.com go to different services.


8. ? Rapid-Reference Crib Sheet

Command/Concept Example Notes
Install NGINX Ingress helm install ingress-nginx ingress-nginx/ingress-nginx Use --set controller.service.type=LoadBalancer
Get Ingress IP kubectl get svc -n ingress-nginx Look for EXTERNAL-IP
Path-based routing path: /api Use pathType: Prefix for /api/foo
Host-based routing host: api.example.com Requires DNS pointing to Ingress IP
TLS Secret kubectl create secret tls my-tls --key tls.key --cert tls.crt Use cert-manager for automation
Default backend defaultBackend: { service: { name: default-backend, port: 8080 } } Handles 404s
Rate limiting nginx.ingress.kubernetes.io/limit-rpm: "100" Prevents DDoS
Rewrite target nginx.ingress.kubernetes.io/rewrite-target: /$1 Strips /api from /api/foo
IngressClass ingressClassName: nginx Required for NGINX
Traefik annotations traefik.ingress.kubernetes.io/router.entrypoints: web Tra


ADVERTISEMENT