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.