# Keep Service traffic close to the caller with trafficDistribution

> Calls to the inventory Service cross zones. Keep them in the caller's zone, then on its node, with trafficDistribution and Kubernetes 1.35's PreferSameNode.

Level: Intermediate · Topic: Networking · About 12 minutes
Try it in the browser: https://k8wiz.com/playground/keep-service-traffic-local

The playground is a simulated Kubernetes cluster that runs in the browser. kubectl output and errors follow the real ones.

## The situation

inventory runs one replica on each worker. Zone eu-west-1a has two workers, worker-1 and worker-4; eu-west-1b and eu-west-1c have one each. The client Pod on worker-1 calls the inventory Service, and kube-proxy spreads those calls over every replica, so half of them leave the zone.

A Service's `trafficDistribution` asks kube-proxy to prefer close endpoints. In Kubernetes 1.35 it gained `PreferSameNode`, and the older `PreferClose` was renamed `PreferSameZone`. Try both.

## Objectives

1. Measure where client's calls land (`kubectl exec client -- sh -c 'for i in $(seq 1 12); do wget -qO- http://inventory; done' | grep node | sort | uniq -c`)
2. Keep the calls in client's zone with PreferSameZone
3. Keep them on client's node with PreferSameNode
4. Find the hints kube-proxy follows in the EndpointSlice (`kubectl get endpointslices -l kubernetes.io/service-name=inventory -o yaml`)

## Hints

1. The loop prints the node that answered each call. `kubectl get nodes -L topology.kubernetes.io/zone` shows which zone each node is in.
2. `kubectl patch svc inventory -p '{"spec":{"trafficDistribution":"PreferSameZone"}}'`, then run the loop again. worker-1 and worker-4 share eu-west-1a.
3. Switch to `PreferSameNode` and run it once more. The EndpointSlice now carries `hints` on each endpoint: `forZones`, plus `forNodes` for PreferSameNode.

## Solution

```bash
kubectl get nodes -L topology.kubernetes.io/zone
```
```bash
kubectl exec client -- sh -c 'for i in $(seq 1 12); do wget -qO- http://inventory; done' | grep node | sort | uniq -c
```
```bash
kubectl patch svc inventory -p '{"spec":{"trafficDistribution":"PreferSameZone"}}'
```
```bash
sleep 2
```
```bash
kubectl exec client -- sh -c 'for i in $(seq 1 12); do wget -qO- http://inventory; done' | grep node | sort | uniq -c
```
```bash
kubectl patch svc inventory -p '{"spec":{"trafficDistribution":"PreferSameNode"}}'
```
```bash
sleep 2
```
```bash
kubectl exec client -- sh -c 'for i in $(seq 1 12); do wget -qO- http://inventory; done' | grep node | sort | uniq -c
```
```bash
kubectl get endpointslices -l kubernetes.io/service-name=inventory -o yaml | grep -A4 hints | head -5
```

## What it teaches

- By default kube-proxy spreads a Service's traffic over every ready endpoint, wherever it runs.
- `trafficDistribution: PreferSameZone` keeps traffic in the caller's zone, and `PreferSameNode` (new in 1.35) on the caller's node. Both fall back to other endpoints when none are close: they're preferences, not rules.
- The EndpointSlice controller writes the preference as hints on each endpoint, `forZones` and `forNodes`, and kube-proxy on each node follows them.
- `PreferClose` still works as the old name of `PreferSameZone`. Keep enough replicas per zone: preferring close endpoints sends a zone's whole load to its local replicas.
