← Articulet Kubernetes Zero to Hero Chapter 4.3
Module 4 Networking and Services

Ingress and Traffic Management

In the previous chapter you learned how Services provide stable addresses for Pods. But how do visitors from outside the cluster find their way in? If every service had its own public IP, you'd have tangled infrastructu...

Chapter 10 of 22

In the previous chapter you learned how Services provide stable addresses for Pods. But how do visitors from outside the cluster find their way in? If every service had its own public IP, you'd have tangled infrastructure. You need one controlled entrance. That's Ingress.


4.3.1 Why Ingress Exists

A LoadBalancer Service gives you a public IP for one service. But with a web frontend, API backend, and admin dashboard — each a separate Service — you'd need three public IPs and three cloud load balancers. Your bill grows with every new service.

Ingress provides a single entry point for all HTTP/HTTPS traffic. It sits in front of your Services and uses routing rules to direct each request — like a receptionist who sends visitors to different floors based on what they're looking for.

  • Path-based routing: /api goes to the backend, / goes to the frontend. Multiple applications share one domain.
  • Host-based routing: api.example.com routes to one service, www.example.com to another.

Ingress also handles SSL/TLS termination — decrypting HTTPS at the edge and forwarding plain HTTP internally. Your application code needs no certificate awareness.

Visual Description:

graph LR subgraph "External Users" U1[example.com/] U2[example.com/api] end subgraph "Ingress [Main Gatehouse]" ING[Ingress<br/>34.120.50.10<br/>SSL Termination] end subgraph "Internal Services" SVC1[frontend ClusterIP] SVC2[api ClusterIP] end subgraph "Pods" P1[web Pod] P2[api Pod] end U1 -->|path: /| ING U2 -->|path: /api| ING ING -->|/| SVC1 ING -->|/api| SVC2 SVC1 --> P1 SVC2 --> P2 style ING fill:#ffcc80,stroke:#333,stroke-width:2px style SVC1 fill:#a5d6a7 style SVC2 fill:#a5d6a7

One external IP feeds into the Ingress, routing to multiple ClusterIP Services. Far more cost-efficient than multiple LoadBalancers, with one place to manage routing and SSL.


4.3.2 Ingress Resources: Defining the Rules

An Ingress resource is routing rules in YAML. It does NOT route traffic — think of it as posted directions that someone must read and enforce. That "someone" is the Ingress Controller.

Here's an Ingress resource:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-service
            port:
              number: 80

The three path types behave differently:

  • Prefix: Matches any path starting with the prefix — /api matches /api, /api/v1, /api/users. Most common.
  • Exact: Matches only the exact path — /api matches only /api, not /api/.
  • ImplementationSpecific: Matching depends on your Ingress Controller.

⚠️ Common Misconception: "Creating an Ingress resource automatically routes traffic." It does not. Without an Ingress Controller, the resource does nothing.


4.3.3 Ingress Controllers: The Implementation Engine

If the Ingress resource is posted directions, the Ingress Controller is the guard who enforces them. The controller is a pod that watches Ingress resources and configures a reverse proxy to implement their rules.

Popular controllers:

Controller Best For
NGINX Ingress Controller General-purpose; most popular
Traefik Cloud-native; auto-discovery
HAProxy High-performance
Istio Gateway Service mesh; advanced routing

Multiple controllers can coexist using IngressClass to assign each Ingress:

apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: nginx
spec:
  controller: k8s.io/ingress-nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80
graph TD API[API Server] subgraph "NGINX Ingress Controller" WATCH[Controller] NGINX[NGINX Proxy Pod] end ING1[Ingress: app-a] ING2[Ingress: app-b] SVC1[Service A] SVC2[Service B] EXT[External Traffic] API --> ING1 & ING2 WATCH --> ING1 & ING2 WATCH --> NGINX EXT --> NGINX --> SVC1 & SVC2 style NGINX fill:#ffcc80,stroke:#333,stroke-width:2px

🛑 PAUSE & RECALL — 2 minutes

  1. What is the difference between an Ingress resource and an Ingress Controller?
  2. Name the three path types. When would you use Prefix versus Exact?
  3. Why is Ingress more cost-efficient than multiple LoadBalancer Services?

Rate your confidence (0–4).


4.3.4 GCE Ingress Controller: GKE-Native Load Balancing

GKE Note: The GCE Ingress Controller integrates your Ingress directly with Google's global load balancing infrastructure — a key advantage of running Kubernetes on GKE.

On GKE, the GCE Ingress Controller provisions an actual Google Cloud HTTP(S) Load Balancer — globally distributed and Google-managed — instead of running NGINX inside your cluster.

Container-Native Load Balancing (CNLB) is what makes this special. Most controllers route to a Service's ClusterIP, then kube-proxy forwards to Pods: Load Balancer → Node → kube-proxy → Pod. With CNLB, the Google load balancer knows your individual Pod IPs directly. Traffic goes: Load Balancer → Pod. This is direct-to-pod routing.

Benefits: lower latency (one less hop), better health awareness (per-Pod health checks, not node-level), and more accurate load distribution.

GKE enables CNLB through Network Endpoint Groups (NEGs) — auto-created when you use the GCE Ingress, containing your Pod IPs attached to the load balancer.

Use it with ingressClassName: gce:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: gce-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: my-static-ip
spec:
  ingressClassName: gce
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

GKE Note: The GCE Ingress requires Pods to respond HTTP 200 on / by default. Use a BackendConfig CRD to customize the health check path if your app doesn't serve /.

graph LR subgraph "Google Cloud" GLB[Global HTTP(S) Load Balancer] NEG[NEG<br/>Pod IPs: 10.4.1.5,<br/>10.4.2.8, 10.4.3.1] end subgraph "GKE Cluster" P1[Pod: 10.244.1.5] P2[Pod: 10.244.2.8] P3[Pod: 10.244.3.1] end USER -->|HTTPS| GLB -->|direct-to-pod| NEG --> P1 & P2 & P3 style GLB fill:#4285f4,color:#fff style NEG fill:#a5d6a7

4.3.5 Advanced Ingress Patterns

SSL/TLS with Managed Certificates. On GKE, reference networking.gke.io/managed-certificates: my-cert in your Ingress. GKE handles request, validation, and renewal automatically.

Rate limiting — the NGINX Ingress Controller supports nginx.ingress.kubernetes.io/limit-rps: "10" for per-IP request limits.

Canary deployments route a percentage of traffic to a new version. NGINX Ingress uses nginx.ingress.kubernetes.io/canary: "true" and nginx.ingress.kubernetes.io/canary-weight: "20" for 20% canary traffic.

Rewrite rules transform URLs — e.g., /api/v2/users/users via the rewrite-target annotation.


4.3.6 Service Mesh Introduction: Beyond Ingress

Ingress manages north-south traffic (external to internal). For east-west traffic (service-to-service inside the cluster), use a service mesh.

Istio is the most popular mesh; GKE offers it managed as Anthos Service Mesh. The core pattern is the sidecar proxy: every Pod gets an Envoy proxy alongside its app container. All traffic flows through this proxy, forming a mesh that enforces policies and encrypts traffic without code changes.

graph LR subgraph "Pod A" APP1[App Container] PROXY1[Envoy Sidecar] end subgraph "Pod B" APP2[App Container] PROXY2[Envoy Sidecar] end APP1 <-->|localhost| PROXY1 <-->|mTLS| PROXY2 <-->|localhost| APP2 style PROXY1 fill:#ce93d8 style PROXY2 fill:#ce93d8

A mesh provides: mutual TLS (encrypted service calls), traffic shifting (1% → 100% to v2), observability (distributed tracing), and advanced routing (by headers, retries, circuit breakers).

Remember: Ingress manages external-to-internal; a service mesh manages internal service-to-service. They complement each other — Ingress gets users in; the mesh manages what happens inside.


4.3.7 Analogy: The Main Security Gatehouse

Analogy: The Main Security Gatehouse

Imagine a gated neighborhood with one grand entrance. This is your Ingress.

At the gatehouse, several things happen. There's only one entrance — a single controlled access point (your one external IP). Guards have routing directives: "Community center? Right fork. Admin office? Left fork." This is path-based and host-based routing.

Before entry, guards check visitor certificates. No certificate? Redirected to secure verification (HTTPS). Certificates are verified once at the gate — inside, residents don't check IDs at every building. This is SSL/TLS termination.

On busy days, the gatehouse manages crowd flow — letting visitors through at a controlled rate. This is rate limiting. When testing a new layout, 10% of visitors take the new route while 90% stay on the old path. This is canary traffic splitting.

Deep inside, every building has a trusted courier handling inter-building deliveries through secure tunnels. The gatehouse doesn't know about this internal system. This is your service mesh.

Stretch point: Unlike a real gatehouse, Kubernetes Ingress can inspect request content — URL paths, headers — to route. Real guards can't peek inside sealed envelopes; your Ingress reads every HTTP header.


4.3.8 Visual Description: The Gatehouse Architecture

Visual Description:

Picture the gatehouse as concentric zones:

  1. The Outer Wall (External Internet): Visitors approach. HTTP users are immediately redirected to HTTPS at the gate.
  2. The Gatehouse (Ingress): One public IP. SSL termination happens here — certificates verified, encryption stripped for internal use. A routing board: /api → Building B, / → Building A.
  3. The Internal Streets (Cluster Network): ClusterIP Services carry traffic to destinations.
  4. The Buildings (Pods): Containers doing the actual work.
  5. The Courier Network (Service Mesh): Envoy sidecars in every Pod handle all inter-building communication through secure tunnels.
graph TD subgraph "External Internet" U1[HTTP User] U2[HTTPS User] end subgraph "The Gatehouse [Ingress]" ING[Ingress 34.120.50.10] SSL[SSL Termination] RULES["/ → frontend<br/>/api → backend"] end subgraph "Internal Streets [Services]" SVC1[frontend-service] SVC2[api-service] end subgraph "Buildings [Pods]" P1[web Pod] P2[api Pod] end subgraph "Courier Mesh [Istio/ASM]" PROXY1[Envoy] PROXY2[Envoy] end U1 & U2 --> ING --> SSL --> RULES --> SVC1 & SVC2 SVC1 --> P1 --> PROXY1 SVC2 --> P2 --> PROXY2 PROXY1 <-->|mTLS| PROXY2 style ING fill:#ffcc80,stroke:#333,stroke-width:3px style SSL fill:#ef9a9a style PROXY1 fill:#ce93d8 style PROXY2 fill:#ce93d8

🤔 TRY BEFORE YOU SEE

You need to deploy a web app with three components: React frontend, REST API, and admin dashboard — all accessible from the internet via one domain. Sketch:

  1. How many Services, and what types?
  2. How many Ingress rules?
  3. What path-based routing rules?
  4. Where does SSL termination happen?

Draw traffic flow from user to each component.


Reveal: Three ClusterIP Services. Three path rules: / → frontend, /api → API, /admin → admin. SSL at the Ingress. Flow: User → Ingress → ClusterIP → Pod. One external IP shared.


🛑 PAUSE & RECALL — 3 minutes

  1. What is Container-Native Load Balancing, and why is direct-to-pod routing better?
  2. In the gatehouse analogy, what do SSL termination and rate limiting represent?
  3. What does Ingress manage (north-south) versus a service mesh (east-west)?
  4. Why must you install an Ingress Controller before creating an Ingress resource?

Rate your confidence (0–4).


GKE in Practice

The recommended production pattern on GKE: GCE Ingress Controller + Container-Native Load Balancing + Managed Certificates. Globally distributed load balancing, automatic SSL, and direct-to-pod routing — all Google-managed.

Steps:

  1. Reserve a static IP: gcloud compute addresses create my-static-ip --global
  2. Create a ManagedCertificate for automatic SSL
  3. Create Ingress with GCE class, referencing the static IP and certificate
  4. Use BackendConfig to tune health checks:
   apiVersion: cloud.google.com/v1
   kind: BackendConfig
   metadata:
     name: my-backend-config
   spec:
     healthCheck:
       checkIntervalSec: 10
       port: 8080
       type: HTTP
       requestPath: /healthz
     timeoutSec: 60

GKE Note: The GCE Ingress Controller takes 5–10 minutes to provision the load balancer. Don't panic if kubectl get ingress shows the IP as pending — check the Cloud Console under "Network Services → Load Balancing."

For advanced use cases, consider GKE's Gateway Controller, implementing the Kubernetes Gateway API — the successor to Ingress.


Lab: LAB-4.3 — Ingress and Traffic Management (75 minutes)

Deploy the NGINX Ingress Controller, create path-based routing, configure GCE Ingress with Container-Native LB, and set up a Managed SSL Certificate.

Prerequisites: GKE cluster, 2+ nodes.

Part 1: Deploy Sample Applications (15 min)

kubectl create namespace lab-ingress

kubectl create deployment frontend --image=gcr.io/google-samples/hello-app:1.0 -n lab-ingress
kubectl expose deployment frontend --port=8080 --target-port=8080 --type=ClusterIP -n lab-ingress

kubectl create deployment api --image=gcr.io/google-samples/hello-app:2.0 -n lab-ingress
kubectl expose deployment api --port=8080 --target-port=8080 --type=ClusterIP -n lab-ingress

Verify:

kubectl get services -n lab-ingress
# NAME       TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)
# api        ClusterIP   10.96.5.10    <none>        8080/TCP
# frontend   ClusterIP   10.96.8.20    <none>        8080/TCP

Part 2: Deploy NGINX Ingress Controller (15 min)

helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace

kubectl wait --namespace ingress-nginx \
  --for=condition=ready pod \
  --selector=app.kubernetes.io/component=controller \
  --timeout=90s

Part 3: Create Path-Based Routing (15 min)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-routing
  namespace: lab-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api
            port:
              number: 8080
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              number: 8080
kubectl apply -f ingress-rules.yaml
kubectl get ingress -n lab-ingress
# Get the IP, then test:
curl http://<INGRESS-IP>/
curl http://<INGRESS-IP>/api

Part 4: GCE Ingress with Container-Native LB (15 min)

kubectl apply -f - <<'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: gce-ingress
  namespace: lab-ingress
  annotations:
    cloud.google.com/neg: '{"ingress": true}'
spec:
  ingressClassName: gce
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              number: 8080
EOF

Wait 5–10 minutes for the GCE Ingress IP, then check NEGs:

kubectl get ingress gce-ingress -n lab-ingress -w
# Once IP is assigned:
gcloud compute network-endpoint-groups list \
  --filter="name~frontend" \
  --format="table(name, zone, networkEndpointType)"

Part 5: HTTPS with Managed SSL Certificate (15 min)

GKE Note: You need a domain pointed at your GCE Ingress IP. If you don't have one, observe the provisioning process.

kubectl apply -f - <<'EOF'
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: lab-cert
  namespace: lab-ingress
spec:
  domains:
    - lab.yourdomain.com
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: gce-https
  namespace: lab-ingress
  annotations:
    networking.gke.io/managed-certificates: lab-cert
    kubernetes.io/ingress.global-static-ip-name: lab-static-ip
spec:
  ingressClassName: gce
  rules:
  - host: lab.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              number: 8080
EOF

Check status:

kubectl get managedcertificate lab-cert -n lab-ingress

Cleanup

kubectl delete namespace lab-ingress
kubectl delete namespace ingress-nginx

Chapter Summary

Ingress is your cluster's gatehouse — a single entry point for external HTTP/HTTPS traffic. An Ingress resource defines routing rules; an Ingress Controller implements them. You explored path-based and host-based routing and the resource-controller distinction. On GKE, the GCE Ingress Controller enables Container-Native Load Balancing for direct-to-pod routing. Advanced patterns include managed SSL certificates, rate limiting, canary deployments, and rewrite rules. The service mesh — Istio and Anthos Service Mesh — handles encrypted internal traffic, complementing Ingress.


📇 KEY CONCEPT CARDS

  1. Q: What is the difference between an Ingress resource and an Ingress Controller?
    A: The Ingress resource is a YAML declaration of routing rules. The Ingress Controller is a running component (like NGINX) that watches those rules and implements them. Without a controller, an Ingress resource does nothing.
  1. Q: What are the three Ingress path types, and when would you use each?
    A: Prefix matches any path starting with the prefix — most common. Exact matches only the exact character-for-character path. ImplementationSpecific delegates matching to the specific Ingress Controller.
  1. Q: What is Container-Native Load Balancing on GKE, and why is it better?
    A: CNLB routes directly from the Google Cloud Load Balancer to individual Pods, bypassing nodes. Benefits: lower latency, better per-Pod health awareness, more accurate load distribution.
  1. Q: What traffic does Ingress manage versus what a service mesh manages?
    A: Ingress manages north-south traffic (external users into the cluster). A service mesh like Istio manages east-west traffic (internal service-to-service), adding mTLS, traffic shifting, and observability.

ce mesh like Istio manages east-west traffic (internal