Skip to content
CAMPUX Cloud Bootcamp Phase Four · Class Twenty-Seven
Phase Four — Operate, Secure & AI
Reading 20 min · Drills 4 · Part C of VII
AKS: Zero to Production
Class Twenty-Seven · Part C

AKS networking

Every request into and across a cluster travels a fixed set of hops, and the day something is unreachable you will save yourself an hour by knowing which hop to look at first.

§1

CoreDNS — how one Service finds another by name

In §27a you learned never to talk to a pod, because pod addresses change; you talk to a Service, which holds a stable ClusterIP. But your code does not carry that IP either — it carries a name. Inside the cluster a pod that wants the payments service opens a connection to payments, or payments.shop.svc.cluster.local, and something has to turn that name into the Service's ClusterIP. That something is CoreDNS, a DNS server AKS runs for you as pods in kube-system. It watches the API server, and for every Service it publishes a name that resolves to that Service's ClusterIP.

The shape of the name is worth holding: service.namespace.svc.cluster.local. Within one namespace the bare name is enough — payments resolves — because CoreDNS appends the caller's namespace by default. Across namespaces you spell it out: payments.billing. That is the whole mechanism behind "services find each other by name," and it is why a typo in a namespace, not a broken app, is the usual reason one service cannot reach another. When you next debug a connection that hangs, resolving the name by hand from inside a pod tells you in one command whether DNS or the network is the problem.

CoreDNS
The in-cluster DNS server, run as pods in kube-system, that resolves a Service name to its ClusterIP. Names take the form service.namespace.svc.cluster.local; the bare name works within a namespace because CoreDNS appends the caller's own.
§2

Ingress — one front door for many Services

A ClusterIP is invisible from outside the cluster, and a LoadBalancer Service per app means one Azure load balancer and one public IP per app — the honest but expensive way to expose things, as §27a warned. The way real clusters expose many apps is a single ingress controller: one pod (or set of pods) that holds one public entry point and routes each incoming HTTP or HTTPS request to the right Service by hostname and path. Requests for shop.example.com go to the shop Service; requests for api.example.com/partner go to the gateway Service. One IP, one certificate store, many backends.

On AKS you do not have to install and babysit that controller yourself. The application routing add-on gives you a managed NGINX ingress controller that AKS keeps patched and running; you write Ingress objects and it does the rest. For teams already standardised on Azure's layer-7 load balancer there is Application Gateway for Containers — the successor to the older Application Gateway Ingress Controller (AGIC) — which pushes routing out to a managed Azure resource in front of the cluster. Either way the mental model is the same: the ingress controller is the reverse proxy at the edge, and the Ingress object is the routing table you hand it.

One door. The proxy decides who goes where.

Fig. 1 · The path in — one ingress controller fans out to Services, each fronting its pods
An external request enters one ingress controller, which routes by host and path to Services, each fronting its pods. Request HTTPS · external Ingress controller Service · shop ClusterIP Service · partner-gw ClusterIP pod pod pod pod one public IP, not one per app
Read it left to right: one request, one controller at the edge, then a fan-out by host and path to Services, each of which load-balances across its own pods. The single entry point is the saving — one IP, one certificate to renew, one place to reason about who may enter — instead of a LoadBalancer, and a bill, per app.
§3

The data plane — where pods get their addresses

Under the names and the proxy sits a plainer question: where does a pod's IP address come from? The answer is the cluster's network model, chosen when the cluster is created, and the current recommended default on AKS is Azure CNI Overlay. Pods receive addresses from a private overlay range that is separate from the virtual network's own address space; the node translates between the two. The reason this is the default is unglamorous and important: it solves IP exhaustion. Under the flat models, every pod consumed a real VNet address, and a busy cluster could drain a subnet — the kind of ceiling you hit at 2am during a scale-out, not in planning.

You will still meet the older names, and it is worth being precise about them so an interview does not catch you. Legacy kubenet is on a deprecation path — do not describe it as "the default." Flat Azure CNI, where pods sit directly in the VNet, is still available and correct when a pod genuinely needs a routable VNet address, but it trades away the address-space savings. For a new, deliberately ordinary cluster, Overlay is the choice that will not surprise you later. The distinction that matters is the one you can state in a sentence: Overlay hands pods overlay IPs and spares your subnet; the flat models spend a real VNet address on every pod.

§4

Network policies — pods talk to everyone until you say otherwise

Here is the fact that surprises people, and the one an auditor will ask about: by default, every pod in the cluster can open a connection to every other pod. There is no wall between namespaces at the network layer until you build one. A network policy is that wall — a rule that says which pods may send traffic to which, selected by label. Apply a policy that admits only the partner's source to the gateway pods, and everything else is denied; write no policy, and the gateway is reachable from any compromised pod in the cluster.

To enforce those rules the cluster needs a policy engine, chosen at creation: Azure Network Policy Manager, or a Cilium- or Calico-based option. The pattern to internalise is default-deny: start by denying ingress to a set of pods, then add back only the sources that must reach them. That is the opposite of the cluster's out-of-the-box posture, and closing the gap is deliberate work, not a setting that is on. When someone signs a contract with an "audited network policy" clause, this is the object that satisfies it — and a cluster with no policies is a finding waiting to be written.

Network policy
A label-selected rule governing which pods may send traffic to which. The default posture is all-to-all; a policy narrows it. Enforcement needs a policy engine (Azure Network Policy Manager, or Cilium/Calico) chosen when the cluster is created.
§5

Private clusters — taking the API server off the internet

One address is left to account for: the API server, the endpoint kubectl talks to. By default it has a public IP, reachable from anywhere and guarded by authentication. A private cluster replaces that with a private endpoint — the API server is reachable only over the virtual network, with no public IP at all. Administrators reach it from inside the VNet, over a peering, or through a VPN or bastion, and a scanner on the open internet cannot even see that it exists.

This is defence in depth, not a substitute for the authentication and RBAC of §27e; a private endpoint narrows who can reach the door, while RBAC decides what they may do once they knock. The cost is operational — your pipelines and your engineers now need a network path in, which is real work to arrange and a real thing to get wrong. Whether that trade is worth it is exactly the judgement call a regulated tenant faces, and the three networking concerns below are the ones you weigh together when you design a cluster's edge.

Reach in — the API server
Public endpoint by default; a private cluster gives it a private endpoint on the VNet. Authentication and RBAC still gate what a caller may do (§27e); the private endpoint only narrows who can reach it.
Reach in — application traffic
One ingress controller as the single front door, routing external HTTP or HTTPS by host and path to many ClusterIP Services. On AKS, the managed application routing add-on or Application Gateway for Containers.
Reach across — pod to pod
All-to-all by default; a network policy narrows it to only the sources that must connect. Requires a policy engine chosen at cluster creation. This is the clause an auditor checks.
Case File · Campux Retail

The partner gateway gets its front door — and only the partner's key

one ingress route in, one network policy across, and the audit clause is satisfied

In §27a the partner gateway landed as one Deployment behind a ClusterIP Service — reachable inside the cluster, invisible outside. The contract needs it reachable by the wholesale partner and no one else, so two objects finish the job. An Ingress on the application routing add-on gives the gateway a single public hostname on the managed NGINX controller, terminating HTTPS at the edge; that is the front door. The storefront stays on App Service and the pos-batch job stays on Container Apps — nothing new is dragged onto the cluster to earn this.

The second object is the one the auditor will read. A network policy admits traffic to the partner-gw pods only from the partner's declared source, and denies everything else — which, given the cluster's all-to-all default, is a wall that did not exist an hour ago. That single policy is the "audited network policy" clause of the wholesale contract, written as a Kubernetes object rather than a paragraph of intent. The cluster is still exactly the size of the contract: one route in, one rule across, and a clause that a reviewer can verify by reading the manifest.

On the job

"The service is up but I can't reach it"

You · Cloud Engineer · a colleague pages you at the end of the day

Nothing focuses the mind like an unreachable app that every dashboard swears is healthy, and the fix is a walk down the hops, not a guess. From a pod, resolve the target name — if DNS returns nothing, it is CoreDNS or a namespace typo, and you stop there. If the name resolves but the connection hangs, ask whether a network policy is denying it, because a new default-deny rule silently drops exactly the traffic that used to flow. If the caller is external, the question moves up to the ingress route and its host and path. Naming the layers — DNS, policy, ingress — is what turns a two-hour flail into a ten-minute check.

Class Twenty-Seven · Part C

Examination

Four drills, then two situations. The situations have no marking scheme — write your answer before you reveal the reasoning, or the exercise is worthless. Nothing is stored.

Drill 01Recall
A pod opens a connection to the name payments. What turns that name into an address it can actually reach?
Marked

B. CoreDNS is the in-cluster resolver that watches the API server and publishes a name for every Service, resolving payments to that Service's stable ClusterIP. A confuses layers: the ingress controller is the edge proxy for traffic arriving from outside, not the resolver for internal names. C reaches for the wrong resolver — cluster-internal names like payments.billing.svc.cluster.local mean nothing to public Azure DNS. D is the pod-IP sin the whole Service model exists to prevent; wire to a pod address and it goes stale the first time that pod is replaced. The name-to-ClusterIP hop is CoreDNS, and it is the first thing to check when one service cannot find another.

Drill 02Recall
You must expose five internal apps to the internet on one public IP, routed by hostname. What do you reach for on AKS?
Marked

B. One ingress controller holds a single public entry point and routes by host and path to many Services, which is exactly the shape of the requirement — and on AKS the application routing add-on gives you a managed NGINX controller you do not have to patch. A works but wastes an Azure load balancer and a public IP on every app, five bills where one would do. C exposes raw node ports, a blunt instrument that leaks your node topology and burdens callers with port numbers. D is impossible for pods behind ClusterIP and reckless even where it is not — public IPs belong at the edge, not on the workload. When the words are "many apps, one IP, route by host," the answer is an ingress controller.

Drill 03Select three
Which three statements about AKS networking are true?
Marked

The all-to-all default, Azure CNI Overlay, and the private endpoint. The two rejects are the traps interviewers set. Kubenet is not the default — it is on a deprecation path, and calling it the default is the tell of someone reading an old guide; Azure CNI Overlay is the current recommendation. And CoreDNS is exactly the resolver for in-cluster Service names, the reverse of the false option — it turns payments into a ClusterIP, and it is public Azure DNS that handles internet names. The all-to-all default is the one to carry into any security conversation: the network wall between pods does not exist until you build it with a policy.

Drill 04Spot the error
A junior writes up the plan for exposing the partner gateway. One line is wrong in a way that leaves an audit finding. Which?
# plan: exposing partner-gw to the wholesale partner
1.  An Ingress on the app-routing add-on gives it one
    public hostname over managed NGINX.
2.  CoreDNS resolves partner-gw to its ClusterIP for
    internal callers.
3.  Pods are all-to-all by default, so no network policy
    is needed to restrict who reaches the gateway.
4.  A private cluster would take the API server off the
    public internet.
Marked

Line three. It reads the default backwards. All-to-all means every pod in the cluster can already reach the gateway, so a compromised pod anywhere is a path to the partner integration — which is precisely why a network policy is required, not a reason it is optional. Ship this plan and the gateway is exposed to the whole cluster, and the contract's audited-network-policy clause is unmet: an auditor reads the manifests, finds no policy, and writes the finding. The fix is one object — a policy admitting only the partner's source and denying the rest.

The other lines are sound. The application routing add-on does provide a managed NGINX ingress controller (A is wrong). CoreDNS resolves Service names to ClusterIPs for internal callers, exactly as line two says (B is wrong). And a private cluster does replace the API server's public endpoint with a private one (D is wrong). The lesson generalises: a permissive default is not a decision someone made for your safety — it is a gap you are expected to close, and mistaking openness for a considered choice is how audits fail.

Situation 01Write before you reveal
A teammate proposes giving each of the cluster's public apps its own LoadBalancer Service "so they're independent." You think one ingress controller is right. Make the case — in a way that teaches the model, not just the verdict.
Independence sounds like a virtue. Ask what each LoadBalancer actually costs, and what the ingress buys that the split-up version cannot.
Reasoning

Concede the instinct before you correct it. Wanting each app independent is a reasonable reflex — blast radius, clean separation. But a LoadBalancer Service per app buys a specific, billed thing: one Azure load balancer and one public IP each, plus a certificate to terminate and renew per address. Five apps become five edges to secure, five IPs to allowlist, five renewals to forget. The "independence" is mostly duplicated edge, not real isolation.

Then name what the ingress centralises on purpose. One ingress controller gives you a single front door: one IP, one place to terminate HTTPS, one routing table read by host and path. That is not less independent — the apps are still separate Services behind it — it is the routing and the certificate handling pulled into one auditable spot. Fewer edges is fewer things to misconfigure, and on AKS the application routing add-on runs and patches that controller for you.

Close on when the split is actually right. Be honest about the limit so you are not dogmatic: a workload that is not HTTP, or one that genuinely needs its own IP for allowlisting by a partner, is a fair reason to break out a dedicated Service. The rule is HTTP and HTTPS through one ingress by default, a dedicated address only when a real requirement forces it — the same "soft by default, hard when required" shape as the rest of the track.

Situation 02Write before you reveal
During a review, someone says: "The partner gateway is behind a ClusterIP and an ingress, so it's locked down — external traffic only reaches it through the front door." Is the cluster's internal exposure handled? Reason it out.
The claim is about the edge. The audit clause is about the inside.
Reasoning

The claim is true about the wrong boundary. Yes, the ingress is the only path in from outside, and that part is handled. But "locked down" quietly assumes the inside of the cluster is safe, and it is not. By default every pod in the cluster can open a connection straight to the gateway pods, bypassing the ingress entirely — the front door governs outsiders, not the neighbours already in the building.

Name what is actually missing. Without a network policy the gateway is reachable by any pod in any namespace, so a single compromised workload anywhere becomes a route to the partner integration. That is exactly the exposure the contract's audited-network-policy clause exists to close, and an ingress does nothing for it. The two objects solve two different problems: the ingress admits external traffic through one door; the policy restricts internal pod-to-pod traffic to the partner's declared source.

Close on how you would verify it, not assert it. Do not take "locked down" on trust — read the manifests. If there is no NetworkPolicy selecting the partner-gw pods, the all-to-all default stands and the clause is unmet, whatever the ingress does. The habit worth showing is checking the actual object rather than the intent in the sentence, because the auditor will check the object too.

Examination record · first attempt
0/4
Class 27c · Complete
Retain this much

Five things worth carrying out of Part C

  1. CoreDNS is the in-cluster resolver: it turns a Service name into that Service's ClusterIP. The name is service.namespace.svc.cluster.local; the bare name works within a namespace.
  2. An ingress controller is one public front door that routes external HTTP and HTTPS by host and path to many Services. On AKS use the application routing add-on's managed NGINX, or Application Gateway for Containers.
  3. Azure CNI Overlay is the current recommended network model — pods get overlay IPs, sparing the VNet subnet from exhaustion. Legacy kubenet is deprecating; do not call it the default.
  4. Pods are all-to-all by default. A network policy is the wall that narrows pod-to-pod traffic to only the sources that must connect; it needs a policy engine chosen at cluster creation.
  5. A private cluster gives the API server a private endpoint with no public IP. It narrows who can reach the door; RBAC still decides what they may do once they knock.
Notes
  1. The precise DNS suffix and search behaviour has edge cases worth knowing before they bite: a pod's resolver is configured to append a search list, which is why payments resolves within a namespace but a partially-qualified name like payments.billing is needed across one. It is also why the occasional slow DNS lookup traced to unnecessary search-domain expansion is a real, if niche, performance story on busy clusters — not something to tune on day one, but the kind of detail that separates "DNS works" from "I know why it sometimes doesn't."
  2. Treat the specifics of which network model is "default" as a moving target, and the direction as settled. Azure has shifted its recommendation over time as Overlay matured, and the exact wording in the docs may read differently by the time you provision a cluster; what is stable is the reasoning — overlay addressing exists to spare the VNet, and reaching for a model that spends a real subnet address on every pod should be a deliberate choice with a reason behind it, not the path of least resistance.