DevOps Peach

Docker & Kubernetes · Kubernetes Architecture · Lesson 5 of 5

The Kubernetes network model

Every pod has its own IP and reaches other pods directly without NAT; a CNI plugin builds the pod network and kube-proxy handles the service network.

Practice interactively →

flowchart LR
  subgraph N1["node worker-1"]
    A["pod web<br/>192.168.1.5"]
  end
  subgraph N2["node worker-2"]
    B["pod api<br/>192.168.2.7"]
  end
  A <-- "pod network (CNI), no NAT" --> B
  S["Service api<br/>ClusterIP 10.96.0.20"] -. "kube-proxy" .-> B

Two networks in a cluster

Four rules

  1. Containers in the same pod talk over localhost.
  2. Every pod reaches every other pod without NAT, even on another node.
  3. Every node reaches every pod without NAT.
  4. The IP a pod sees for itself is the IP other pods see.

Common traps

Command Meaning
kubectl get pods -o wide Pod IPs and the node running each pod
kubectl get networkpolicies -n dev NetworkPolicies in the dev namespace
kubectl apply -f calico.yaml Install a CNI (manifest from the official Calico site)

CNI plugins compared

Plugin Notes
Flannel Simple overlay, easy to start, no NetworkPolicy enforcement
Calico Routing or overlay, full NetworkPolicy support, widely used on-premises
Cilium eBPF-based, NetworkPolicy plus L7 rules and observability, can replace kube-proxy
Cloud CNIs (AWS VPC CNI, Azure CNI) Pods get addresses from the cloud network, integrating with its routing and security

How a Service is reached

kube-proxy watches Services and their EndpointSlices (the list of ready pod IPs) and programs each node. In iptables mode it writes NAT rules; ipvs and the newer nftables modes scale better with thousands of Services. Some CNIs such as Cilium handle Services themselves with eBPF and run without kube-proxy.

DNS inside the cluster

CoreDNS gives every Service a name: api from the same namespace, api.prod from another namespace, and the full form api.prod.svc.cluster.local. A pod's /etc/resolv.conf points to CoreDNS and lists search domains so short names work.

A default-deny NetworkPolicy

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: prod
spec:
  podSelector: {}
  policyTypes: ["Ingress"]

This blocks all incoming traffic to pods in prod; further policies then allow only what is needed, for example from pods labelled app: web to pods labelled app: api on port 8080. Policies are additive: traffic is allowed if any policy allows it.

Traffic from outside

The pod network is internal. Traffic from users enters through a Service of type LoadBalancer or NodePort, an Ingress controller, or the newer Gateway API, covered in the Services module. Service meshes such as Istio or Linkerd add mutual TLS, retries, and traffic splitting between services, at the cost of extra components.

Practice interactively →