Asterrr's Handbook

Kubernetes networking

The Kubernetes networking model, CNI plugins, Service types and kube-proxy, cluster DNS names, Ingress vs Gateway API, and NetworkPolicies for KCNA.

Exam tasks: 2.1 (networking)

The decision: for a given traffic path (container to container, Pod to Pod, client to app, app to the internet), which Kubernetes object or plug-in is responsible, and what name or address does the caller use?

The networking model

Kubernetes sets the rules and leaves the plumbing to plug-ins:

  • Every Pod gets its own IP address. Containers in the same Pod share it and reach each other on localhost.
  • Every Pod can reach every other Pod on any node without NAT. The cluster network is flat.
  • Agents on a node (the kubelet, for example) can reach all Pods on that node.
  • Pod IPs are ephemeral. When a Pod is replaced, its IP changes. That's why Services exist.
  • Dual-stack (IPv4 and IPv6 at once) is stable and supported if the CNI plugin supports it.

CNI: who builds the Pod network

The Container Network Interface is a CNCF spec for plug-ins that the container runtime calls when a Pod sandbox is created. The plug-in creates the Pod's network interface, assigns an IP (IPAM) and sets up routes.

PluginApproachNotes
CalicoRouted (BGP) or overlay, eBPF optionFull NetworkPolicy support, plus its own richer policies
CiliumeBPF in the kernelCan replace kube-proxy, L7-aware policy, CNCF graduated
FlannelSimple VXLAN overlayNo NetworkPolicy enforcement on its own
Cloud CNIs (AWS VPC CNI, Azure CNI)Pods get IPs from the cloud networkPods are directly routable in the VPC
  • An overlay (VXLAN, Geneve) wraps Pod packets inside node-to-node packets. Easy to set up, small overhead.
  • A routed network advertises Pod CIDRs to the underlay (often BGP). No encapsulation, needs network support.
  • A cluster has no working Pod network until a CNI plugin is installed. Nodes stay NotReady without one.

NetworkPolicy with Flannel

Creating a NetworkPolicy always succeeds, because the API server just stores it. If the CNI plugin doesn't enforce policies, nothing is blocked. "The policy exists but traffic still flows" points to the CNI plugin, not to a typo in the policy.

Services: stable names for moving Pods

A Service selects Pods by label and gives them one stable virtual IP and DNS name. The control plane tracks the matching Pod IPs in EndpointSlices.

TypeReachable fromTypical use
ClusterIP (default)Inside the cluster onlyBackend APIs, databases
NodePortEvery node's IP on a port in 30000–32767Simple external access, building block for load balancers
LoadBalancerAn external load balancer from the cloud provider (or MetalLB on bare metal)Exposing one service publicly
ExternalNameInside the cluster, as a DNS CNAMEGiving an external host (a managed database) an in-cluster name
Headless (clusterIP: None)DNS returns Pod IPs directlyStatefulSets, client-side load balancing
  • kube-proxy runs on every node and programs the dataplane that turns a Service IP into a Pod IP. Its modes are iptables (default), nftables (GA since v1.33, recommended on newer kernels) and ipvs.
  • eBPF CNIs such as Cilium can replace kube-proxy entirely.

Legacy: use nftables (or iptables) mode instead

kube-proxy's ipvs mode is deprecated as of v1.35. Older material recommends IPVS for large clusters; nftables now covers that performance case.

Exam signal

"Pods are recreated with new IPs, but clients need a fixed address" is a Service. "Each replica needs its own stable DNS name" is a headless Service with a StatefulSet. "Map an outside hostname into the cluster" is ExternalName.

DNS and service discovery

CoreDNS (CNCF graduated) runs as a Deployment in kube-system and serves names for Services and Pods.

  • A Service gets <service>.<namespace>.svc.cluster.local. From the same namespace, the short name works.
  • A Pod behind a headless Service in a StatefulSet gets <pod-name>.<service>.<namespace>.svc.cluster.local.
  • Named ports get SRV records, so clients can look up port numbers too.
  • The kubelet writes each Pod's /etc/resolv.conf to point at the cluster DNS Service, with search domains.
  • Kubernetes also injects environment variables for Services that existed when a Pod started. DNS is preferred, because it sees Services created later.
  • ExternalDNS (a separate project) publishes Service and Ingress hostnames to public DNS providers.

For example, a quotes Service in namespace bookshelf is quotes.bookshelf.svc.cluster.local, and Pods in bookshelf can call http://quotes.

Getting traffic in: Ingress and Gateway API

Both APIs describe HTTP routing (hostnames, paths, TLS) to Services. Neither does anything without a controller that reads them.

IngressGateway API
StatusStable, frozen (no new features)GA since v1.0, actively developed
ObjectsIngress, IngressClassGatewayClass, Gateway, HTTPRoute, GRPCRoute and more
RolesOne object mixes infra and app settingsSplit: infra provider, cluster operator, app developer
FeaturesHost and path routing, TLS; the rest via controller-specific annotationsHeader matching, traffic splitting by weight, cross-namespace routes, built in
ProtocolsHTTP and HTTPSHTTP, gRPC, TLS, TCP and UDP routes
  • Gateway API is the recommended direction for new work. It also covers service-to-service traffic through the GAMMA initiative, see Service mesh.

Legacy: use Gateway API or another maintained controller instead

The community ingress-nginx controller (kubernetes/ingress-nginx) was retired in March 2026 and gets no more releases or security fixes. The Ingress API itself is still stable and supported by other controllers.

NetworkPolicies

By default, every Pod accepts traffic from anywhere. A NetworkPolicy changes that for the Pods it selects:

  • Policies are namespaced and select Pods by label (podSelector).
  • Once any policy selects a Pod for a direction (ingress or egress), that direction becomes deny by default, and only what some policy allows gets through. Policies are additive: there are no "deny" rules.
  • Rules allow traffic from or to Pods (podSelector), namespaces (namespaceSelector) or IP ranges (ipBlock), on given ports.
  • They work at L3/L4 (IPs, ports). Path- or method-based rules need a CNI extension or a service mesh.
  • An egress default-deny also blocks DNS, so you usually allow UDP and TCP port 53 to CoreDNS.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ledger-from-api-only
  namespace: payments
spec:
  podSelector:
    matchLabels:
      app: ledger
  policyTypes: ["Ingress"]
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: payments-api
      ports:
        - protocol: TCP
          port: 7070
1 IP per Pod
Shared by all containers in the Pod.
30000–32767
Default NodePort range.
svc.cluster.local
Default cluster DNS suffix for Services.
Allow all
Default Pod traffic behaviour until a NetworkPolicy selects the Pod.

For hands-on depth, see the CKA pages on Services, Gateway API and network policies.

Scenarios

Scenario
A team deploys a Deployment named inventory in namespace warehouse. Its Pods are replaced often and their IP addresses change each time. What should other workloads in the cluster use to reach inventory reliably?
Scenario
An engineer applies a NetworkPolicy that should only allow traffic to a database from the backend Pods. The policy is created without errors, but every Pod can still connect to the database. What is the MOST likely cause?
Scenario
A platform team wants to route HTTP traffic by header and send 10% of requests to a new version, and wants app teams to manage their own routes while the platform team owns the shared entry point. Which option fits BEST?

Further reading

On this page