✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Kubernetes Network Traffic Policy

Kubernetes Network Traffic Policy defines how containers communicate within and outside the cluster, ensuring secure and efficient network flow management.

Kubernetes Network Traffic Policy is a collective term for the set of fields and controller behaviors that determine how a request directed at a Service, Gateway, or Ingress is load balanced, restricted to specific topology zones, or preserved with its original client address as it moves across nodes toward a backend Pod. It spans Service-level fields such as internalTrafficPolicy and externalTrafficPolicy, topology-aware routing hints, and the NetworkPolicy object used to allow or deny traffic between workloads, all of which shape the actual path and fairness of traffic distribution inside a cluster.


Service Traffic Policy Fields

externalTrafficPolicy

externalTrafficPolicy controls how traffic entering through a NodePort or LoadBalancer Service is routed once it reaches a node. With the value Cluster (the default), kube-proxy forwards the request to any ready Pod backing the Service cluster-wide, potentially adding an extra network hop and masking the original client source IP. With the value Local, kube-proxy forwards only to Pods running on the node that received the packet, preserving the client source IP and avoiding the extra hop, at the cost of uneven load distribution if Pods are not spread evenly across nodes.

apiVersion: v1
kind: Service
metadata:
  name: edge-svc
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  selector:
    app: edge
  ports:
    - port: 80
      targetPort: 8080

internalTrafficPolicy

internalTrafficPolicy applies the same Cluster/Local distinction to traffic originating from inside the cluster (Pod-to-Service calls) rather than from external clients. Setting it to Local restricts a Pod's requests to a Service so that they only reach backend Pods co-located on the same node, which is useful for node-local caching sidecars or DaemonSet-backed Services.

apiVersion: v1
kind: Service
metadata:
  name: node-cache
spec:
  internalTrafficPolicy: Local
  selector:
    app: node-cache
  ports:
    - port: 6379

healthCheckNodePort

When externalTrafficPolicy: Local is set on a LoadBalancer Service, Kubernetes allocates a healthCheckNodePort that cloud load balancers poll to determine which nodes actually have ready backend Pods, so that traffic is only sent to nodes capable of serving it locally.


Topology-Aware Traffic Distribution

Topology Aware Hints

Topology Aware Hints allow EndpointSlice controllers to annotate endpoints with a hints.forZones field, biasing kube-proxy to prefer routing traffic to Pods within the same zone as the originating node. This reduces cross-zone data transfer costs and latency in multi-zone clusters, and is enabled by setting the service.kubernetes.io/topology-mode annotation to Auto.

apiVersion: v1
kind: Service
metadata:
  name: zonal-svc
  annotations:
    service.kubernetes.io/topology-mode: Auto
spec:
  selector:
    app: zonal
  ports:
    - port: 443

Traffic Distribution Field

The newer trafficDistribution field on a Service (PreferClose) offers a more explicit successor to legacy topology keys, instructing kube-proxy implementations to prefer endpoints topologically closer to the client, falling back to any available endpoint when no close one exists, avoiding the strict fallback gaps that affected earlier zone-aware routing implementations.

Interaction with Autoscaling and Rebalancing

Topology-aware routing must be reconciled continuously as Pods are rescheduled by the Horizontal Pod Autoscaler or during node drains; EndpointSlice hints are recalculated whenever the ratio of endpoints to CPU/zone capacity shifts, and heavily skewed zones may see hints disabled automatically to prevent overload of a single zone's Pods.


NetworkPolicy as Traffic Policy Enforcement

Ingress and Egress Rules

A NetworkPolicy resource defines allowed ingress and/or egress traffic for a set of Pods selected by podSelector, based on peer selectors (podSelector, namespaceSelector, ipBlock) and port/protocol combinations. Because NetworkPolicies are additive and default-deny once any policy selects a Pod for a given direction, they act as the primary in-cluster traffic policy enforcement mechanism, independent of Service-level routing fields.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: shop
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080

Default Deny Baselines

Many platform teams establish a namespace-wide default-deny-all NetworkPolicy as a baseline traffic policy, then layer explicit allow rules on top, ensuring that any Service-level or Gateway-level routing decision is still subject to an independent, auditable network-layer gate.

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

CNI-Dependent Extensions

Some CNI plugins extend the base NetworkPolicy API with additional traffic policy primitives — Cilium's CiliumNetworkPolicy supports L7-aware rules (HTTP method/path matching), and Calico's GlobalNetworkPolicy supports cluster-wide scope and explicit rule ordering — both layering on top of, rather than replacing, the standard NetworkPolicy object.


Session Affinity and Load Balancing Algorithm

ClientIP Session Affinity

The sessionAffinity: ClientIP field on a Service instructs kube-proxy to pin a given client IP to the same backend Pod for the duration of sessionAffinityConfig.clientIP.timeoutSeconds, which is a traffic policy concern distinct from topology or external/internal routing, useful for stateful protocols that assume a sticky backend.

IPVS and Load Balancing Modes

When kube-proxy runs in IPVS mode, the traffic policy also includes a choice of load balancing algorithm (round robin, least connection, destination hashing, and others), configurable via the --ipvs-scheduler flag, giving finer control over how traffic is distributed across matched backend Pods than the random selection used by iptables mode.

Interaction with Service Mesh Traffic Shifting

When a service mesh is present, mesh-level traffic policies (weighted routing, circuit breaking, retries) operate at a layer above Kubernetes-native traffic policy fields; both layers apply concurrently, so a canary traffic split configured in the mesh's routing resource still passes through whatever externalTrafficPolicy or NetworkPolicy constraints are configured at the Kubernetes Service level.


Observability and Troubleshooting

Verifying Effective Endpoints

Because traffic policy fields change which endpoints are eligible for a given request, kubectl get endpointslices reveals the actual candidate set, including any zone hints, letting operators confirm that Local policies or topology hints are producing the expected endpoint subset.

kubectl get endpointslices -l kubernetes.io/service-name=edge-svc -o yaml

Common Symptoms of Misconfigured Policy

Setting externalTrafficPolicy: Local without evenly distributed Pods across nodes causes uneven load and, in extreme cases, connection failures on nodes with zero local Pods; overly strict NetworkPolicy default-deny rules without matching allow rules silently drop traffic that otherwise appears correctly routed at the Service level, making traffic policy debugging a matter of checking both routing fields and policy objects together.