Skip to content

Commit b01969e

Browse files
authored
Docs: zone aware routing (#4076)
Add documentation for zone aware routing Signed-off-by: greeshma1196 <greeshma.mathew@gmail.com>
1 parent fb3d5f9 commit b01969e

4 files changed

Lines changed: 220 additions & 0 deletions

File tree

docs/kubernetes/ingress-usage.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ zalando.org/skipper-ingress-redirect-code | `301` | change the default HTTPS red
2626
zalando.org/skipper-loadbalancer | `consistentHash` | defaults to `roundRobin`, [see available choices](../reference/backends.md#load-balancer-backend)
2727
zalando.org/skipper-backend-protocol | `fastcgi` | (*experimental*) defaults to `http`, [see available choices](../reference/backends.md#backend-protocols)
2828
zalando.org/skipper-ingress-path-mode | `path-prefix` | (*deprecated*) please use [Ingress version 1 pathType option](https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types), which defaults to ImplementationSpecific and does not change the behavior. Skipper's path-mode defaults to `kubernetes-ingress`, [see available choices](#ingress-path-handling), to change the default use `-kubernetes-path-mode`.
29+
zalando.org/traffic-zone-aware | `"false"` | opt out individual Ingress from zone aware traffic routing
2930

3031
## Supported Service types
3132

@@ -1249,3 +1250,25 @@ spec:
12491250
number: 80
12501251
pathType: ImplementationSpecific
12511252
```
1253+
1254+
## Zone Aware Traffic Routing
1255+
1256+
When zone aware traffic routing is enabled, skipper routes traffic
1257+
preferentially to endpoints in the same availability zone, helping
1258+
reduce cross-zone network costs and latency.
1259+
1260+
Individual Ingress resources can opt out by setting the
1261+
`zalando.org/traffic-zone-aware` annotation to `"false"`.
1262+
1263+
See [Zone Aware Routing](zone-aware-routing.md) for full details on
1264+
enabling, configuring, and opting out of zone aware routing.
1265+
Example:
1266+
1267+
```yaml
1268+
apiVersion: networking.k8s.io/v1
1269+
kind: Ingress
1270+
metadata:
1271+
annotations:
1272+
zalando.org/traffic-zone-aware: "false"
1273+
name: app
1274+
```

docs/kubernetes/routegroups.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,23 @@ Ingress (`pathType: ImplementationSpecific`): | RouteGroup:
649649
`path-prefix` and `/foo` | pathSubtree: `/foo`
650650
`kubernetes-ingress` and /foo$ | path: `/foo`
651651

652+
### zalando.org/traffic-zone-aware
653+
654+
This annotation allows opting out individual RouteGroup resources from
655+
zone aware routing. When set to `"false"`, all endpoints are used
656+
regardless of zone, even if the local zone has enough endpoints.
657+
658+
Example RouteGroup:
659+
660+
```yaml
661+
apiVersion: zalando.org/v1
662+
kind: RouteGroup
663+
metadata:
664+
name: my-route-group
665+
annotations:
666+
zalando.org/traffic-zone-aware: "false"
667+
```
668+
652669
## Multiple skipper deployments
653670

654671
If you want to split for example `internal` and `public` traffic, it
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
# Zone Aware Routing
2+
3+
Zone aware routing directs traffic preferentially to service endpoints
4+
in the same availability zone as the skipper instance handling the
5+
request. This helps in reducing cross-zone network latency and data transfer
6+
costs in multi-AZ Kubernetes clusters.
7+
8+
This page covers both operator setup (enabling and configuring
9+
zone aware routing) and application-level usage (opting out for
10+
individual resources).
11+
12+
## Prerequisites
13+
14+
Zone aware routing requires:
15+
16+
- **Kubernetes EndpointSlices**: Skipper reads the `zone` field from EndpointSlice endpoints,
17+
which Kubernetes populates from the node's
18+
`topology.kubernetes.io/zone` label.
19+
20+
- **Node topology labels**: nodes must have the
21+
`topology.kubernetes.io/zone` label set.
22+
23+
- **Skipper configured with `-kubernetes-topology-zone`**: tells
24+
skipper which zone it is running in. See [Enabling Zone Aware
25+
Routing](#enabling-zone-aware-routing) below.
26+
27+
## Enabling Zone Aware Routing
28+
29+
How zone aware routing is enabled depends on the deployment mode.
30+
31+
### Dataclient mode (standalone skipper)
32+
33+
Set the `-kubernetes-topology-zone` flag to the availability zone of
34+
the skipper instance:
35+
36+
-kubernetes-topology-zone string
37+
sets the topology zone to be used for zone aware routing
38+
(default: empty, zone aware routing disabled)
39+
40+
When this flag is empty (the default), zone aware routing is disabled
41+
and all endpoints are used regardless of zone.
42+
43+
### RouteSRV mode
44+
45+
Configure skipper instances to fetch routes from RouteSRV using the
46+
zone-specific endpoint by setting `-routes-urls` to include the zone
47+
path:
48+
49+
-routes-urls http://<routesrv-host>/routes/<zone>
50+
51+
### Injecting the zone via Kubernetes downward API
52+
53+
In a typical deployment, each skipper pod runs on a different node and
54+
should use that node's zone. Use the Kubernetes downward API to inject
55+
the node's topology zone into the pod:
56+
57+
```yaml
58+
apiVersion: apps/v1
59+
kind: Deployment
60+
metadata:
61+
name: skipper
62+
spec:
63+
template:
64+
spec:
65+
containers:
66+
- name: skipper
67+
args:
68+
- skipper
69+
- -kubernetes
70+
- -kubernetes-topology-zone=$(TOPOLOGY_ZONE)
71+
env:
72+
- name: TOPOLOGY_ZONE
73+
valueFrom:
74+
fieldRef:
75+
fieldPath: metadata.labels['topology.kubernetes.io/zone']
76+
```
77+
78+
## How It Works
79+
80+
Skipper reads zone information from the Kubernetes EndpointSlice API.
81+
Each endpoint in an EndpointSlice has a `zone` field (for example
82+
`eu-central-1a`) that Kubernetes sets based on the node where the
83+
pod runs.
84+
85+
When zone aware routing is enabled, skipper filters endpoints to
86+
prefer those in the same zone as the skipper instance. A minimum
87+
threshold of **3 endpoints** in the local zone is required for zone
88+
filtering to activate. If fewer than 3 local-zone endpoints exist, all
89+
endpoints across all zones are used as a fallback to maintain
90+
availability.
91+
92+
```mermaid
93+
flowchart LR
94+
A[K8s EndpointSlice API] -->|zone per endpoint| B[Skipper Dataclient]
95+
B -->|filter by zone<br/>threshold >= 3| C{Enough local<br/>endpoints?}
96+
C -->|Yes| D[Use local-zone<br/>endpoints only]
97+
C -->|No| E[Use all endpoints<br/>across zones]
98+
D --> F[eskip Route with<br/>LBEndpoints]
99+
E --> F
100+
```
101+
102+
## Architecture: Two Modes of Zone Filtering
103+
104+
Zone aware routing can operate in two distinct modes, depending on
105+
the deployment model. Both modes apply the same threshold of 3
106+
endpoints per zone.
107+
108+
### Mode 1: Dataclient filtering
109+
110+
When skipper runs standalone (without RouteSRV), the Kubernetes
111+
dataclient filters endpoints at route build time. When it resolves
112+
backends for an Ingress or RouteGroup, it returns only same-zone
113+
endpoints if at least 3 exist. Otherwise, all endpoints are returned.
114+
115+
This mode is active whenever `-kubernetes-topology-zone` is set.
116+
117+
### Mode 2: RouteSRV filtering
118+
119+
When using a [RouteSRV](ingress-controller.md#routesrv) deployment, RouteSRV
120+
performs zone filtering when serving routes. RouteSRV polls for
121+
routes every 3 seconds, then creates per-zone route variants
122+
by filtering each route's endpoints to the requesting zone.
123+
124+
Skipper instances fetch zone-filtered routes from RouteSRV by
125+
requesting `/routes/{zone}` instead of `/routes`.
126+
127+
```mermaid
128+
flowchart TB
129+
subgraph routesrv ["RouteSRV"]
130+
A[Poll routes from<br/>K8s dataclient] --> B[Build full<br/>route table]
131+
B --> C[filterRoutesByZone]
132+
C --> D["/routes — all endpoints"]
133+
C --> E["/routes/{zone} — zone-filtered endpoints"]
134+
end
135+
136+
subgraph skipper ["Skipper Instance (zone: eu-central-1a)"]
137+
F["GET /routes/eu-central-1a"] --> E
138+
E --> G[Route table with<br/>local-zone endpoints]
139+
end
140+
```
141+
142+
## RouteSRV Integration
143+
144+
RouteSRV exposes zone-filtered routes at `/routes/{zone}`.
145+
When a skipper instance requests `/routes/eu-central-1a`, RouteSRV
146+
returns routes with `LBEndpoints` filtered to only those in
147+
`eu-central-1a` (when the threshold is met).
148+
149+
Each zone gets independent HTTP caching metadata:
150+
151+
- **ETag**: zone-specific hash, different from the full-routes ETag
152+
- **X-Count**: number of routes in the zone-filtered set
153+
- **Last-Modified**: timestamp of the last update for that zone
154+
155+
If a requested zone has no data or fewer than 3 endpoints in a
156+
route, RouteSRV falls back to serving the full unfiltered
157+
route set.
158+
159+
## Opting Out
160+
161+
Individual Ingress or RouteGroup resources can opt out of zone aware
162+
routing by setting the `zalando.org/traffic-zone-aware` annotation to
163+
`"false"`. When opted out, traffic is routed to all endpoints
164+
regardless of zone, even if there are at least three local-zone endpoints are available.
165+
166+
### How opt-out works
167+
168+
- When the annotation is set while using the DataClient mode, the DataClient skips zone filtering for that resource's endpoints (all endpoints are included in the route).
169+
- When the annotation is set while using the RouteSRV mode, the filter `annotate("zalando.org/traffic-zone-aware", "false")` is added to the route. This filter signals to RouteSRV that the route should not be zone-filtered when serving `/routes/{zone}`.
170+
171+
## Behavior Details
172+
173+
- **Threshold**: zone filtering activates only when there are at least
174+
3 endpoints in the local zone. This prevents routing all traffic to
175+
a very small number of local pods, which could cause overload.
176+
177+
- **Fallback**: when the threshold is not met, all endpoints across
178+
all zones are used. This ensures availability is maintained even
179+
when a zone has few or no endpoints.

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ nav:
2525
- Ingress Controller Deployment: kubernetes/ingress-controller.md
2626
- Ingress Usage: kubernetes/ingress-usage.md
2727
- Ingress Backends: kubernetes/ingress-backends.md
28+
- Zone Aware Routing: kubernetes/zone-aware-routing.md
2829
- RouteGroups: kubernetes/routegroups.md
2930
- RouteGroup CRD Semantics: kubernetes/routegroup-crd.md
3031
- RouteGroup Validation: kubernetes/routegroup-validation.md

0 commit comments

Comments
 (0)