# Ingress and NetworkPolicy: What They Architecturally Do ## Ingress: routing external HTTP(S) traffic by host/path You already know a LoadBalancer Service can expose something to the public internet. But a real application usually needs more than "one raw IP to one Service" — you might want `api.example.com` and `app.example.com` to route to different backend Services, all through one entry point, with TLS termination handled in one place instead of per-Service. **Ingress** is the Kubernetes object for exactly this: a set of HTTP routing rules (by hostname and/or URL path) that an Ingress controller reads and turns into actual load-balancer/proxy configuration. ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app-ingress spec: rules: - host: app.example.com http: paths: - path: / pathType: Prefix backend: service: name: frontend-svc port: { number: 80 } ``` An important distinction: Ingress is a set of ROUTING RULES, not a load balancer itself — an Ingress controller (a separate piece of software running in the cluster) is what actually reads these rules and does the routing. Without a controller installed, an Ingress object exists in the API but nothing acts on it. ## NetworkPolicy: traffic reachability as something you declare, not assume By default, every Pod in a Kubernetes cluster can reach every other Pod — there is no built-in network isolation between them at all. This surprises people coming from a "obviously the network is locked down unless configured otherwise" assumption. It is exactly backwards from that assumption: **everything is reachable until you say otherwise.** A NetworkPolicy changes this for the Pods it selects, by declaring which traffic IS allowed — everything not explicitly allowed to a Pod covered by at least one NetworkPolicy is then denied. ```yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-frontend-to-backend spec: podSelector: matchLabels: { app: backend } ingress: - from: - podSelector: matchLabels: { app: frontend } ``` This example allows traffic to `backend` Pods only from `frontend` Pods — once this policy exists and selects `backend`, every OTHER Pod trying to reach `backend` is now blocked, even though nothing was true about that before the policy existed. ## Why this matters architecturally, before it matters as a security control Right now, think of NetworkPolicy purely as "declaring intended reachability, not assuming it." ROOT 09 comes back to NetworkPolicy specifically as a SECURITY control (default-deny postures, least-privilege network access) — this module is deliberately just the architectural mental model: Kubernetes doesn't isolate network traffic for you by default, and NetworkPolicy is the mechanism for declaring the reachability you actually intend. ## Instructor Notes **Approximate timing:** 15 minutes read; 10 minutes live. **Likely misconceptions to watch for:** - Students often assume Ingress by itself "does" the routing. Emphasize the controller requirement — an Ingress object with no controller installed does nothing. - The "everything reachable by default" fact genuinely surprises most students the first time they hear it — it's worth stating plainly and letting it land rather than rushing past it. **Discussion question:** "If NO NetworkPolicy exists anywhere in a Namespace, what's the actual reachability between Pods in that Namespace?" (Answer: completely open — every Pod can reach every other Pod, matching the "everything reachable by default" rule.) **Optional extension:** ask what would happen if you created a NetworkPolicy that selects `frontend` Pods but declares no `ingress` rules at all (answer: `frontend` Pods would become completely unreachable by anything — an empty ingress list inside a NetworkPolicy that HAS an ingress policyType means "deny all incoming," not "no policy applies").