The flat network model

Kubernetes requires: every Pod gets its own cluster-wide IP; any Pod can reach any other Pod's IP directly, with no NAT, even across nodes; and a Pod sees the same IP for itself that everyone else sees for it. Unlike the Docker bridge network you saw on the previous page, where a container's IP is only meaningful inside its own host, a Pod IP is routable cluster-wide from the moment it's created.

Node A
frontend-x7d 10.244.1.5
cache-2ab 10.244.1.6
Node B
backend-q9f 10.244.2.3
db-1kd 10.244.2.4

frontend-x7d on Node A can open a connection straight to 10.244.2.3 on Node B — no port mapping, no translation, exactly like two hosts on the same LAN.

How pods get that flat network: CNI

Kubernetes itself doesn't implement the flat network — it delegates to a CNI plugin. When a Pod is scheduled, kubelet calls the plugin, which creates the Pod's network namespace, wires up a veth pair (the same primitive again), assigns an IP, and configures whatever mechanism makes that IP reachable from every other node.

CNI pluginHow it makes Pod IPs reachable across nodes
FlannelWraps Pod traffic in VXLAN tunnels between nodes — simple to run, with tunneling overhead on every packet.
CalicoUses real routing (often BGP) so Pod IPs are just normal routes — no tunnel encapsulation overhead, but requires routable infrastructure.
CiliumUses eBPF to move packets without iptables at all, adding rich L3-L7 visibility and policy enforcement along the way.

Services: a stable address for a moving target

Pods are disposable — rescheduled, restarted, replaced, each time with a new IP. A Service gives callers one stable thing to talk to, no matter how many times the Pods behind it change.

TypeWhat it addsReachable from
ClusterIPA stable virtual IP, load-balanced across matching Pods (the default type)Inside the cluster only
NodePortClusterIP, plus the same static port (30000-32767) opened on every node's IPAnywhere that can reach any node
LoadBalancerNodePort, plus a real external load balancer provisioned by the cloud provider pointing at itThe public internet (if the LB is public)
Headless (clusterIP: None)No virtual IP at all — DNS returns the individual Pod IPs directlyCallers that specifically want to address Pods themselves, e.g. StatefulSets

Life of a request: Ingress → Service → kube-proxy → Pod

Step through what actually happens when a browser hits a URL that's ultimately served by one Pod out of several.

Cluster DNS naming

Every Service automatically gets a name in cluster DNS, served by CoreDNS. Try it:

Ingress: Layer 7 routing into the cluster

An Ingress is just a set of routing rules — host and path to Service — not a running proxy by itself. It only works because an Ingress Controller is deployed to actually read those rules and act on them, letting one entry point route to many Services instead of paying for a LoadBalancer Service per Service.

HostPathRouted to Service
shop.example.com/apiorders-svc:80
shop.example.com/storefront-svc:80
admin.example.com/admin-svc:80

NetworkPolicy: pod-level firewalling

The flat network model means, by default, any Pod can reach any other Pod — there's no isolation at all until you add one. The moment a NetworkPolicy selects a Pod for ingress, that Pod flips from default-allow to default-deny-except-what's-listed.

Common gotchas