Back to Kubernetes Course

Kubernetes Course

Kubernetes Networking Model

screenshot of the app

Kubernetes imposes a few fundamental networking rules that every conformant cluster must satisfy:

  • Every Pod gets its own unique IP address, cluster-wide — no NAT is needed for Pod-to-Pod communication.
  • Pods on any node can communicate with Pods on any other node without NAT, as if all Pods were on one flat network.
  • Nodes can communicate with all Pods, and vice versa, without NAT.
  • A container's view of its own IP is the same IP other Pods see it by — no address translation happens within a Pod.

Kubernetes doesn't implement this networking itself — it delegates to a CNI (Container Network Interface) plugin. Common choices: Calico, Cilium, Flannel, and cloud-specific implementations (AWS VPC CNI, Azure CNI). The CNI plugin is what actually assigns Pod IPs and routes traffic to satisfy the rules above.


Why Ingress? — The Limits of Services

A LoadBalancer Service works well for exposing one application externally, but provisions a separate cloud load balancer per Service — expensive and unwieldy once you have many HTTP services to expose. An Ingress solves this by providing a single entry point that routes external HTTP(S) traffic to many internal Services based on hostname and path.


Ingress Resource

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules: - host: shop.example.com http: paths: - path: /api pathType: Prefix backend: service: name: backend-service port: number: 80 - path: / pathType: Prefix backend: service: name: frontend-service port: number: 80 tls: - hosts: - shop.example.com secretName: shop-tls-secret
  • rules.host routes based on the incoming Host header — allowing multiple domains to share one Ingress and one external IP.
  • paths routes based on URL path — /api traffic goes to the backend Service, everything else goes to the frontend.
  • tls terminates HTTPS at the Ingress, referencing a kubernetes.io/tls Secret containing the certificate and key.

Ingress Controllers

An Ingress resource on its own does nothing — it's just a routing specification. An Ingress Controller must be running in the cluster to actually watch Ingress objects and configure a real proxy/load balancer to implement them. Popular choices:

  • ingress-nginx: The most widely used, based on NGINX.
  • Traefik: Popular for its native support for automatic certificate management and dynamic configuration.
  • AWS/GCP/Azure native controllers: Translate Ingress rules directly into the cloud provider's own load balancer.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml kubectl get pods -n ingress-nginx kubectl get ingress

If a cluster has multiple Ingress controllers installed, ingressClassName specifies which one should handle a given Ingress resource.


Network Policies

By default, Kubernetes networking is fully open — any Pod can reach any other Pod, across any namespace, with no restrictions. A NetworkPolicy lets you restrict traffic, implementing a "default deny, then allow specific paths" model similar to a firewall.

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: backend-allow-frontend namespace: production spec: podSelector: matchLabels: app: backend policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: frontend ports: - protocol: TCP port: 8080
  • podSelector chooses which Pods this policy applies to (here, all Pods labeled app: backend).
  • ingress.from whitelists traffic sources — here, only Pods labeled app: frontend may connect, on port 8080. All other inbound traffic to backend Pods is denied.
  • NetworkPolicies are enforced by the CNI plugin, not the Kubernetes control plane itself — Flannel, for instance, doesn't support NetworkPolicy enforcement at all, while Calico and Cilium do. Check your CNI's capabilities before relying on NetworkPolicies.

A common production pattern is a default-deny policy per namespace, with explicit allow rules layered on top:

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-all namespace: production spec: podSelector: {} policyTypes: - Ingress - Egress