CKA Day 33: Kubernetes Ingress Tutorial | Ingress Explained

Day 33/40 of the Tech Tutorials with Piyush CKA certification course, featuring guest instructor Abhishek Veeramalla. This session explains Ingress — the Kubernetes API object that provides Layer 7 (HTTP/HTTPS) routing into the cluster — and the Ingress Controller that makes Ingress rules actually work.

Why Ingress Exists: The Limitations of Services

Kubernetes Services expose applications, but they are Layer 4 (TCP/UDP) load balancers. Each Service type has practical limits when running multiple web applications:

  • ClusterIP is internal-only; no external access.
  • NodePort opens one high port (30,000–32,767) per Service. Running 10 apps means 10 different node ports — users must remember NodeIP:30001 for app A, NodeIP:30002 for app B, etc.
  • LoadBalancer creates one cloud load balancer per Service. At scale, this becomes expensive (10 apps = 10 cloud LBs) and every Service gets its own public IP.

Ingress solves this by acting as a single entry point (one IP, one LoadBalancer Service for the Ingress Controller itself) that can route HTTP/HTTPS traffic to many backend Services based on hostnames and URL paths.

Ingress Resource vs Ingress Controller

A critical distinction that trips up beginners: the Ingress resource is just a rule set; the Ingress Controller is the Pod that executes those rules.

ComponentWhat It IsAnalogy
Ingress ResourceA Kubernetes API object (kind: Ingress) defining routing rulesThe traffic rulebook
Ingress ControllerA Pod (usually a Deployment) that reads Ingress resources and programs a reverse proxyThe traffic cop enforcing the rulebook

Without an Ingress Controller installed, creating an Ingress resource has no effect. Kubernetes ships with no default Ingress Controller — you must install one (nginx, Traefik, HAProxy, Istio Gateway, etc.).

Ingress YAML Anatomy

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx          # Which controller should process this
  rules:
    - host: app1.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app1-service
                port:
                  number: 80
    - host: app2.example.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 8080
  tls:
    - hosts:
        - app1.example.com
      secretName: app1-tls-secret

Key Fields

FieldDescriptionRequired
apiVersionnetworking.k8s.io/v1 (since K8s 1.19+)Yes
spec.ingressClassNameReferences an IngressClass object; tells the cluster which controller handles this IngressRecommended
spec.rules[].hostVirtual host to match (e.g., app1.example.com)No (default catch-all)
spec.rules[].http.paths[].pathURL path to match (e.g., /, /api)Yes
spec.rules[].http.paths[].pathTypeExact, Prefix, or ImplementationSpecificYes
spec.rules[].http.paths[].backend.service.nameTarget Service nameYes
spec.rules[].http.paths[].backend.service.port.numberTarget Service portYes
spec.tls[].hostsHostnames for TLS terminationNo
spec.tls[].secretNamekubernetes.io/tls Secret containing cert + keyNo

Path Types

  • Exact: Matches the URL path exactly, case-sensitively (/foo matches /foo, not /foo/ or /foo/bar).
  • Prefix: Matches the beginning of the URL path (/foo matches /foo, /foo/bar, /foo/bar/baz). Splits on //foo does NOT match /foobar.
  • ImplementationSpecific: Interpretation depends on the Ingress Controller (e.g., nginx regex support).

The Default Backend

Every Ingress Controller has a default backend — a catch-all Service that handles requests that match no rules. If a user hits the Ingress IP with a host/path that isn’t configured, traffic goes to the default backend (typically a 404 page).

Ingress Controller Installation: NGINX

The most common Ingress Controller for learning and production is the NGINX Ingress Controller. It runs as a Deployment (usually in a dedicated namespace like ingress-nginx) and requires a Service to expose it externally:

# Official Helm install (production)
helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace
 
# Or apply the official manifest
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml

After installation, the controller creates a LoadBalancer Service (on cloud) or NodePort Service (on bare metal/Kind). All your Ingress resources share this one external IP — the controller reads every Ingress object in the cluster and updates its nginx configuration accordingly.

Traffic Flow: User → Ingress → Service → Pod

User (browser)
    │
    ▼
DNS resolves app1.example.com → Ingress Controller External IP
    │
    ▼
Ingress Controller (nginx Pod)
    │ reads Ingress resource rules
    ▼
app1.example.com / → routes to → Service: app1-service:80
    │                                    │
    ▼                                    ▼
                                   Pod 10.244.1.2:80
                                   Pod 10.244.1.3:80

Annotations: Controller-Specific Configuration

Annotations on Ingress resources pass configuration to the specific Ingress Controller. They are not validated by Kubernetes — a typo is silently ignored.

AnnotationControllerPurpose
nginx.ingress.kubernetes.io/rewrite-target: /nginxStrip the matched path prefix before forwarding
nginx.ingress.kubernetes.io/ssl-redirect: "true"nginxForce HTTP → HTTPS redirect
nginx.ingress.kubernetes.io/rate-limit: "100"nginxRequest rate limiting

TLS Termination at the Ingress Layer

Ingress is the natural place to terminate TLS for multiple applications. Instead of managing certificates inside every Pod or Service, the Ingress Controller holds the certificate and decrypts traffic before forwarding plain HTTP to backend Services:

spec:
  tls:
    - hosts:
        - app1.example.com
      secretName: app1-tls-secret   # kubectl create secret tls app1-tls-secret --cert=cert.pem --key=key.pem
  rules:
    - host: app1.example.com
      http:
        paths:
          - path: /
            backend:
              service:
                name: app1-service
                port:
                  number: 80

Security Note: Traffic from the Ingress Controller to the backend Service is typically unencrypted HTTP inside the cluster. For end-to-end encryption, use a service mesh or re-encrypt at the Service level.

CKA Exam Patterns

  1. Ingress resource creation: Expect to write an Ingress YAML that routes foo.bar.com to a specific Service on a specific path.
  2. Ingress Controller already running: On the CKA exam, the nginx Ingress Controller is usually pre-installed. You only create the Ingress resource.
  3. PathType matters: Know the difference between Exact and Prefix.
  4. ingressClassName field: Modern clusters use spec.ingressClassName instead of the deprecated kubernetes.io/ingress.class annotation.

Troubleshooting Ingress

SymptomLikely CauseFix
Ingress rules ignoredNo Ingress Controller installedInstall nginx/Traefik controller
404 from default backendhost or path mismatchCheck DNS, verify kubectl get ingress rules
TLS not workingSecret missing or wrong typeEnsure Secret is kubernetes.io/tls and referenced correctly
Path not strippedMissing rewrite-target annotationAdd nginx.ingress.kubernetes.io/rewrite-target: /
External IP pendingNo cloud provider / MetalLBUse NodePort or install MetalLB on bare metal

See Also

Wiki Concepts

Creator / Entity


Tags: kubernetes ingress nginx cka networking l7-routing tls devops services