Module 4: Networking Ingress And Networkpolicy

3. `Ingress`: a single HTTP door for the cluster

Description

With lesson 2's networking contract confirmed — every Pod, an IP, no NAT, in either direction — this lesson answers a different question: how does traffic get in from outside the cluster? The naive answer would be "a NodePort or LoadBalancer Service for every service you want to expose" — and that answer, at scale, becomes just as unsustainable as the problem you already solved once in another guide in this ecosystem. Ingress is Kubernetes' solution to the same problem, at a different layer.

Connection to the module

This lesson is purely conceptual — you're not going to run any command. It's the foundation lessons 4 and 5 build on, which install and configure a real Ingress. By the end of this lesson you're going to be able to explain why Andes Cargo needs this piece, before seeing how it gets built.


The problem, without Ingress

status-api-service (Module 2) is a ClusterIP-type Service — deliberately, reachable only from inside the cluster. If you wanted to expose it directly outward without Ingress, you'd have two options, neither satisfactory at scale:

  • NodePort: each Service reserves a fixed port (in the 30000-32767 range) on every node in the cluster. It works, but every new service needs its own port, memorized and communicated to each client — no readable domain names, no path-based routing.
  • LoadBalancer: on a real cloud, each Service of this type creates a dedicated load balancer (an ALB or NLB on AWS). It works, but a balancer for every microservice in a system with dozens of them is, literally, dozens of balancers — each with its own cost, its own public IP, its own TLS certificate to renew.

Neither option solves something almost every real system needs: routing andes-cargo.example.com/status to one service and andes-cargo.example.com/manifests to another, with one public address, one TLS certificate, and a single layer where traffic rules get decided. That's exactly the problem Ingress solves.


The explicit parallel: Ingress is a Kubernetes cluster's API Gateway

If you completed aws-serverless-and-containers-guide, you already built the solution to this exact same problem, at a different layer. That guide's Module 5 opened with this description:

"An API Gateway is an office building's front desk. It doesn't do any floor's work — it doesn't bill, doesn't process orders, doesn't query databases — but without it, every visitor would have to know by heart which floor, office, and hours to find who they're looking for."

Ingress is the same idea, at a different layer. The following table makes the parallel explicit, field by field:

CapabilityAPI Gateway (AWS, account layer)Ingress (Kubernetes, cluster layer)
What it solvesOne public URL, many backends (Lambda, containers, other AWS services)One host/port, many of the cluster's internal Services
RoutingBy HTTP method and path (GET /shipments/{id})By host and path (andes-cargo.local/)
Who implements itAmazon API Gateway (AWS managed service)A controller you install inside the cluster (lesson 4: ingress-nginx)
TLS/certificatesManaged by AWS Certificate ManagerManaged by cert-manager (named in lesson 1, not built)
Without this pieceEvery Lambda/container resolves its own public URL, with no shared layerEvery Service needs its own NodePort/LoadBalancer
ScopeAn AWS accountA Kubernetes cluster

The central difference, and the reason both guides need their own lesson for this, isn't conceptual — it's the same idea, "a single front desk instead of one door per company" — it's about who administers the implementation. API Gateway is a managed service: AWS runs the infrastructure, you only declare the rules. Ingress differs on a critical point: the Ingress object itself is only a declaration of rules (which host/path goes to which Service) — it does nothing on its own until you install a controller that implements them. That's, literally, the friction mikeocool's quote (this module's lesson 1) describes: "you're going to be installing additional controllers, starting with ingress."

        THE SAME PROBLEM, TWO DIFFERENT LAYERS

  aws-serverless-and-containers-guide (M5)   kubernetes-and-eks-in-production-guide (M4)
  ┌─────────────────────────────┐            ┌─────────────────────────────┐
  │   External HTTP client        │            │   External HTTP client        │
  └──────────────┬───────────────┘            └──────────────┬───────────────┘
                  ▼                                            ▼
       ┌────────────────────┐                        ┌────────────────────┐
       │   API Gateway        │  managed by AWS       │   Ingress             │  you install
       │   (one public URL)    │                       │   (one rule)          │  the controller
       └──────────┬──────────┘                        └──────────┬──────────┘
                  │                                               │
        ┌─────────┼─────────┐                            ┌────────┼────────┐
        ▼         ▼         ▼                             ▼        ▼        ▼
     Lambda   container  other service                 Service   Service   Service

What an Ingress object technically is

An Ingress is a Kubernetes API object (apiVersion: networking.k8s.io/v1, kind: Ingress) that declares HTTP routing rules: given a host (for example, andes-cargo.local) and a path (for example, /), which Service — and which port on that Service — to forward traffic to. Nothing more. The object itself listens on no port, processes no HTTP request, starts no process — it's, exactly like a Deployment or Service manifest, a declaration of intent, that some other piece has to make real.

That other piece is the Ingress controller — a Pod (or several) running inside the cluster, watching every existing Ingress object, and configuring, underneath, a real HTTP server (typically NGINX, though other implementations exist) to satisfy those rules. Without a controller installed, an Ingress applied with kubectl apply saves perfectly into etcd, with no error whatsoever — and does absolutely nothing, because no one's reading it. This is, in itself, one of the most common traps of learning Ingress for the first time, and this module's lesson 4 resolves it by installing the controller before declaring any rule.

              THE Ingress OBJECT DOES NOTHING ON ITS OWN

  kubectl apply -f ingress.yaml
          │
          ▼
   ┌─────────────┐        with no controller installed:
   │   etcd        │  ──►  the object gets saved, no one reads it,
   │  (Ingress      │       no traffic gets routed, with no visible
   │   saved)       │       error
   └─────────────┘

   ┌─────────────┐        with ingress-nginx running (lesson 4):
   │   etcd        │  ──►  the controller detects the new object,
   │  (Ingress      │       configures NGINX underneath, traffic
   │   saved)       │       starts flowing per the rule
   └─────────────┘
          ▲
          │
   ingress-nginx (constantly watching)

IngressClass: when there's more than one controller

A cluster can have more than one Ingress controller installed at the same time (for example, ingress-nginx for internal traffic and the AWS Load Balancer Controller for traffic that needs a real ALB — Module 7 comes back to this). When that happens, every Ingress object needs to declare, with the ingressClassName field, which controller it belongs to. This guide uses a single controller (ingress-nginx, lesson 4), so the field appears with only one possible value (nginx) — but it's worth knowing the mechanism from now, because Module 7 picks it back up with a second real controller.


Analogy: the building's front desk, again, with the rules written in the visitor log

Picking back up lesson 1's analogy: if Ingress is an office building's single front desk, then the Ingress object itself is only the access rule book someone wrote — "any visitor asking for 'Andes Cargo' goes to the third floor" — not the person who actually stops the visitor at the door and directs them. That book, with no real receptionist working that shift, is paper with no effect: anyone could walk straight to the elevator with no one stopping them to read the book. The Ingress controller is the flesh-and-blood receptionist — ingress-nginx, in this guide's case — who actually reads the book, stops each visitor, and directs them per what's written. Writing the book (applying an Ingress) without having hired the receptionist first (installing the controller) is exactly the mistake the previous section describes.


Common mistakes

Declaring an Ingress before installing any controller, and not understanding why "nothing happens" (the most common mistake when learning this piece for the first time). What happens: someone, following a tutorial other than this guide, applies an Ingress manifest without having installed any controller first, sees kubectl apply respond created with no error, and expects the traffic to already be routed. Why it happens: most Kubernetes objects you already know (Pod, Deployment, Service) do something tangible the moment you apply them — it's intuitive to expect the same from Ingress. How to spot it: kubectl get ingress shows the object, but any curl against the expected address fails, with no error on Kubernetes' side explaining it. How to fix it: this guide avoids the mistake through lesson ordering — lesson 4 installs the controller before lesson 5 declares any rule — but if you ever find yourself in this situation, kubectl get pods -A | grep -i ingress is the first diagnostic command: if no Ingress controller Pod is running in any namespace, that's the cause.

Confusing Ingress with a LoadBalancer-type Service (conceptual). What happens: someone assumes Ingress and Service type: LoadBalancer solve the same problem, interchangeably. How to spot it: if you're unsure which to use to expose status-api-service. How to fix it: a LoadBalancer exposes one Service, with one external IP, with no host/path routing logic whatsoever — it's the right tool when you really only have one service to expose, with no need for rules. Ingress is designed for the case where several Services share a single entry door, with routing rules between them — the case that becomes inevitable in any system with more than one HTTP component, like Andes Cargo will have over time.

Expecting Ingress to replace the need for a Service (already previewed in lesson 1, worth repeating here with the full mechanism in front of you). What happens: someone, understanding that Ingress "exposes traffic outward," assumes they can skip declaring status-api-service (Module 2) and point the Ingress directly at the Pods. How to spot it: if you look, in an Ingress's specification, for some field to declare Pods directly, instead of a Service. How to fix it: Ingress's specification only accepts a Service as a backend (backend.service.name), never a Pod or a direct label selector — lesson 5 confirms it in real YAML.


Exercises

Exercise 1 — Fill in the parallel table from memory. Without going back to this lesson's table, complete: "API Gateway is to an AWS account what Ingress is to ___." Then, name two capabilities both share.

See solution

"API Gateway is to an AWS account what Ingress is to a Kubernetes cluster." Two shared capabilities: routing incoming HTTP traffic to multiple backends based on rules (path/host), and a single shared entry door instead of one per individual backend.

Exercise 2 — Explain to a colleague why a freshly applied Ingress "does nothing." A colleague applied an Ingress manifest on a cluster with no controller installed, and doesn't understand why curl returns nothing. Explain it to them in two or three sentences, using this lesson's analogy.

See solution

A reasonable explanation: "The Ingress object you applied is only the access rule book — it says which visitor goes to which floor, but does nothing on its own. What's missing is hiring the flesh-and-blood receptionist, the Ingress controller, who actually reads that book and directs traffic per what it says. With no controller running, the book exists, perfectly saved, and no one reads it."

Exercise 3 — Decide when Ingress isn't needed. A fictional company has a single internal microservice, with no plan to add more in the near future, and only needs to expose it temporarily for a demo. Using this lesson's criteria (not your intuition), argue whether Ingress is the right tool, or whether something simpler is enough.

See solution

For that specific case, a NodePort-type Service (or LoadBalancer, if on a real cloud) is probably enough: the problem Ingress solves — routing by host/path between multiple backends, with a single shared door — doesn't exist yet when there's only one service. Installing and maintaining a complete Ingress controller for a single temporary service is more infrastructure than the case justifies — the same kind of trade-off you already saw, at another layer, between Lambda and a container in aws-serverless-and-containers-guide M1.


Summary and next step

This lesson explained what an Ingress is with no command run: a declaration of HTTP routing rules (host/pathService) that, on its own, does nothing until an Ingress controller — a real Pod watching those rules and configuring an HTTP server underneath — implements them. The parallel with API Gateway (aws-serverless-and-containers-guide M5) isn't a coincidence: it's the same problem — a single front desk, instead of one door per service — solved at two different layers of the same system.

Before moving on you should be able to: explain the difference between the Ingress object and the Ingress controller; fill in the API Gateway parallel table without looking at it; and decide, for a new case, whether Ingress is the right tool or whether a simpler Service is enough.

Next lesson: hands-on, installing ingress-nginx in kind. There you install, for the first time in this guide, the real receptionist this lesson described in theory — with the exact friction mikeocool's quote anticipated.

Resources

  1. Kubernetes — Ingress — the complete official specification for the Ingress object, including the distinction with the controller.
  2. Kubernetes — Ingress Controllers — the official listing of implementations, and the explanation of why an Ingress with no controller does nothing.
  3. aws-serverless-and-containers-guide (NIEVA), Module 5, lesson 2 — the exact origin of the "office building's front desk" analogy, picked back up here at Kubernetes' layer.
  4. Kubernetes — Service — this guide's Module 2 reference, the piece an Ingress always needs as a backend.