Production Kubernetes clusters (AWS EKS, Google GKE, and Azure AKS) distribute worker nodes across three Availability Zones (AZs) to survive datacenter power or cooling outages. However, by default, `kube-proxy` and CNI load balancers distribute internal `ClusterIP` service traffic uniformly at random across all healthy pods in the cluster—completely ignoring which Availability Zone the calling pod resides in.
Because AWS and Google Cloud charge an effective $0.02 per GB ($20.00 per TB) for every gigabyte crossing an Availability Zone boundary within the same region ($0.01/GB egress from Zone A + $0.01/GB ingress to Zone B), default Kubernetes service routing silently taxes 66.7% of all internal microservice traffic.
The 3-Zone Probability Math of Default `ClusterIP` Routing
In a balanced Kubernetes deployment spanning $Z$ Availability Zones, the probability that a random `kube-proxy` iptables/IPVS rule routes an internal RPC call to a pod in a different Availability Zone is $(Z - 1) / Z$:
Furthermore, if the response payload is also large (for example, an internal Redis cache cluster, OpenSearch query service, or gRPC feature store returning 500 KB vectors), both the request and the response traverse the inter-zone fiber link—incurring the $0.02/GB charge in both directions.
High-Risk East-West Workloads That Amplify Cross-AZ Billing
| Internal Workload Type | Why Cross-AZ Amplification Occurs | Remediation Architecture |
|---|---|---|
| Microservice gRPC / REST APIs | Random `ClusterIP` selection routes 66.7% of calls across zones. | Enable `trafficDistribution: PreferClose` on Kubernetes `Service`. |
| Apache Kafka / Redpanda | Producers write to leader partitions in remote AZs; consumers fetch from remote brokers. | Configure `broker.rack` and `client.rack` for local-replica follower fetching. |
| Redis / Valkey Read Replicas | Application pods query primary node or random read replicas across AZs. | Route read-only `GET` queries strictly to the local-AZ replica IP. |
| Prometheus / OpenTelemetry | Centralized scraper in `AZ-a` scrapes 500 pods in `AZ-b` and `AZ-c` every 15s. | Deploy zone-local collector DaemonSets/shards that compress before remote-write. |
Implementing Kubernetes Topology-Aware Routing (`PreferClose`)
Modern Kubernetes releases provide two native mechanisms on the `Service` object to instruct the EndpointSlice controller and `kube-proxy` to keep traffic inside the originating Availability Zone:
- `spec.trafficDistribution: PreferClose` (Kubernetes 1.31+ Standard): Directs `kube-proxy` (and eBPF CNIs like Cilium) to route traffic exclusively to healthy endpoints in the same zone (`topology.kubernetes.io/zone`), automatically falling back to cluster-wide endpoints if the local zone has zero healthy pods.
- `service.kubernetes.io/topology-mode: Auto` (Legacy Annotation): Calculates proportional CPU capacity per zone and populates `EndpointSlice` zone hints when each zone has at least 3 endpoints.
apiVersion: v1
kind: Service
metadata:
name: recommendation-engine-grpc
namespace: production
annotations:
# Fallback annotation for Kubernetes 1.27 - 1.30 clusters
service.kubernetes.io/topology-mode: "Auto"
spec:
selector:
app: recommendation-engine
# Native field in Kubernetes 1.31+ to keep traffic inside the calling AZ
trafficDistribution: PreferClose
ports:
- name: grpc
protocol: TCP
port: 9090
targetPort: 9090
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: recommendation-engine
namespace: production
spec:
replicas: 9
selector:
matchLabels:
app: recommendation-engine
template:
metadata:
labels:
app: recommendation-engine
spec:
# Guarantee even 3-3-3 pod distribution across all 3 Availability Zones
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: recommendation-engine
Verifying `forZones` Hints in `EndpointSlice` Objects
Applying `trafficDistribution: PreferClose` or `service.kubernetes.io/topology-mode: Auto` does not guarantee zone-local routing is active—if endpoint counts are skewed across AZs, the EndpointSlice controller silently omits zone hints and reverts to cluster-wide random routing. Verify that `hints.forZones` is populated using `kubectl`:
$ kubectl get endpointslices -n production -l kubernetes.io/service-name=recommendation-engine-grpc -o yaml
endpoints:
- addresses:
- 10.42.18.104
conditions:
ready: true
hints:
forZones:
- name: us-east-1a
nodeName: ip-10-42-18-12.ec2.internal
zone: us-east-1a
- addresses:
- 10.42.84.219
conditions:
ready: true
hints:
forZones:
- name: us-east-1b
nodeName: ip-10-42-84-90.ec2.internal
zone: us-east-1b
Eliminating Kafka Consumer Cross-AZ Egress (Follower Fetching)
In a 3-AZ Apache Kafka or Amazon MSK cluster with `replication.factor=3`, partition replication between brokers across AZs is unavoidable for durability. However, by default, all consumers read exclusively from the **Partition Leader**—meaning 66.7% of consumer read bandwidth crosses AZ boundaries.
By mapping each broker and consumer pod's Kubernetes node label (`topology.kubernetes.io/zone`) to Kafka's rack awareness config, consumers fetch messages from the **in-zone follower replica** for `$0.00/GB`:
# 1. Broker Configuration (server.properties) broker.rack=us-east-1a replica.selector.class=org.apache.kafka.common.replica.RackAwareReplicaSelector # 2. Consumer Client Configuration (Injected via Kubernetes Downward API / Node Zone) client.rack=us-east-1a
Operational Safeguard: Preventing Zone Hotspots Under HPA Scaling
Before enabling `PreferClose` on every service, verify that **both the upstream caller and the downstream target are evenly balanced across all 3 AZs** using `topologySpreadConstraints`. If an Ingress Controller or API Gateway runs 80% of its pods in `us-east-1a`, enabling strict zone-local routing will force 80% of downstream database/microservice load onto the pods in `us-east-1a`, starving pods in `1b` and `1c` while triggering CPU throttling in `1a`.
Master 95th Percentile Enterprise Bandwidth Contracts Next
Learn how 5-minute SNMP sampling windows work and how to convert $/Mbps commit rates into effective $/GB.