Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions examples/kubernetes/zone-aware-routing.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: zone-aware-routing-backend-local
spec:
replicas: 1
selector:
matchLabels:
app: zone-aware-routing-backend
version: v1
template:
metadata:
labels:
app: zone-aware-routing-backend
version: v1
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "gateway.envoyproxy.io/owning-gateway-name"
operator: In
values:
- eg
- key: "app.kubernetes.io/component"
operator: In
values:
- proxy
topologyKey: topology.kubernetes.io/zone
namespaceSelector: {}
containers:
- image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
imagePullPolicy: IfNotPresent
name: backend
ports:
- containerPort: 3000
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: zone-aware-routing-backend-nonlocal
spec:
replicas: 1
selector:
matchLabels:
app: zone-aware-routing-backend
version: v1
template:
metadata:
labels:
app: zone-aware-routing-backend
version: v1
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "gateway.envoyproxy.io/owning-gateway-name"
operator: In
values:
- same-namespace
- key: "app.kubernetes.io/component"
operator: In
values:
- proxy
topologyKey: topology.kubernetes.io/zone
namespaceSelector: {}
containers:
- image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
imagePullPolicy: IfNotPresent
name: backend
ports:
- containerPort: 3000
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: zone-aware-routing
spec:
parentRefs:
- name: eg
hostnames:
- "www.example.com"
rules:
- backendRefs:
- group: ""
kind: Service
name: zone-aware-routing-backend
port: 3000
weight: 1
matches:
- path:
type: PathPrefix
value: /zone-aware-routing
218 changes: 218 additions & 0 deletions site/content/en/latest/tasks/traffic/zone-aware-routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
---
title: "Zone Aware Routing"
---

EnvoyGateway makes use of [Envoy Zone Aware Routing][Envoy Zone Aware Routing] to support Kubernetes [Traffic Distribution][Traffic Distribution]
and [Topology Aware Routing][Topology Aware Routing] which are useful for keeping network traffic in the originating zone.
Preferring same-zone traffic between Pods in your cluster can help with reliability, performance (network latency and throughput), or cost.

{{% alert title="Note" color="primary" %}}
The current implementation for Topology Aware Routing support doesn't respect the minimum of 3 endpoints per zone
requirement and applies the same logic as `spec.TrafficDistribution=PreferClose`. This will be fixed in the next release.
{{% /alert %}}


## Prerequisites
* The Kubernetes cluster's nodes must indicate topology information via the `topology.kubernetes.io/zone` [well-known label][Kubernetes well-known metadata].
* There must be at least two valid topology zones for scheduling.
* {{< boilerplate prerequisites >}}

## Configuration

### Kubernetes Service
Create the example Kubernetes Service with either topology aware routing or traffic distribution enabled.

#### Topology Aware Routing
{{< tabpane text=true >}}
{{% tab header="Apply from stdin" %}}
```shell
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
annotations:
service.kubernetes.io/topology-mode: Auto
name: zone-aware-routing-backend
labels:
app: zone-aware-routing-backend
service: zone-aware-routing-backend
spec:
ports:
- name: http
port: 3000
targetPort: 3000
selector:
app: zone-aware-routing-backend
EOF
```
{{% /tab %}}
{{% tab header="Apply from file" %}}
Save and apply the below service manifest to your cluster:
```yaml
---
apiVersion: v1
kind: Service
metadata:
annotations:
service.kubernetes.io/topology-mode: Auto
name: zone-aware-routing-backend
labels:
app: zone-aware-routing-backend
service: zone-aware-routing-backend
spec:
ports:
- name: http
port: 3000
targetPort: 3000
selector:
app: zone-aware-routing-backend
```
{{% /tab %}}
{{< /tabpane >}}

#### Traffic Distribution
{{< tabpane text=true >}}
{{% tab header="Apply from stdin" %}}
```shell
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: zone-aware-routing-backend
labels:
app: zone-aware-routing-backend
service: zone-aware-routing-backend
spec:
ports:
- name: http
port: 3000
targetPort: 3000
selector:
app: zone-aware-routing-backend
trafficDistribution: PreferClose
EOF
```
{{% /tab %}}
{{% tab header="Apply from file" %}}
Save and apply the below service manifest to your cluster:
```yaml
---
apiVersion: v1
kind: Service
metadata:
name: zone-aware-routing-backend
labels:
app: zone-aware-routing-backend
service: zone-aware-routing-backend
spec:
ports:
- name: http
port: 3000
targetPort: 3000
selector:
app: zone-aware-routing-backend
trafficDistribution: PreferClose
```
{{% /tab %}}
{{< /tabpane >}}


### Example deployments and HTTPRoute
Next apply the example manifests to create two Deployments and an HTTPRoute. For the test configuration one Deployment
(zone-aware-routing-backend-local) includes affinity for EnvoyProxy Pods to ensure its Pods are scheduled in the same
zone and the second Deployment (zone-aware-routing-backend-nonlocal) uses anti-affinity to ensure its Pods _don't_
schedule to the same zone in order to demonstrate functionality.
```shell
kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/zone-aware-routing.yaml -n default
```

Ensure that both example Deployments are marked as ready and produces the following output:
```shell
kubectl get deployment/zone-aware-routing-backend-local deployment/zone-aware-routing-backend-nonlocal -n default
NAME READY UP-TO-DATE AVAILABLE AGE
zone-aware-routing-backend-local 1/1 1 1 9m1s
zone-aware-routing-backend-nonlocal 1/1 1 1 9m1s

```

An HTTPRoute resource is created for the `/zone-aware-routing` path prefix along with two example Deployment resources that
are respectively configured with pod affinity/anti-affinity targeting the Envoy Proxy Pods for testing.

Verify the HTTPRoute configuration and status:

```shell
kubectl get httproute/zone-aware-routing -o yaml
```

## Testing

Ensure the `GATEWAY_HOST` environment variable from the [Quickstart](../../quickstart) is set. If not, follow the
Quickstart instructions to set the variable.

```shell
echo $GATEWAY_HOST
```

### HTTPRoute

We will now send a request and expect to be routed to backend in the same local zone as the Envoy Proxy Pods.

```shell
curl -H "Host: www.example.com" "http://${GATEWAY_HOST}/zone-aware-routing" -XPOST -d '{}'
```

We will see the following output. The `pod` header identifies which backend received the request and should have
a name prefix of `zone-aware-routing-backend-local-`. We should see this behavior every time and the nonlocal backend should
not receive requests.

```
{
"path": "/zone-aware-routing",
"host": "www.example.com",
"method": "GET",
"proto": "HTTP/1.1",
"headers": {
"Accept": [
"*/*"
],
"User-Agent": [
"curl/8.7.1"
],
"X-Envoy-External-Address": [
"127.0.0.1"
],
"X-Forwarded-For": [
"10.244.1.5"
],
"X-Forwarded-Proto": [
"http"
],
"X-Request-Id": [
"0f4c5d28-52d0-4727-881f-abf2ac12b3b7"
]
},
"namespace": "default",
"ingress": "",
"service": "",
"pod": "zone-aware-routing-backend-local-5586cd668d-md8sf"
}
```


## Clean-Up

Follow the steps from the [Quickstart](../../quickstart) to uninstall Envoy Gateway and the example manifest.

Delete the zone-aware-routing example resources and HTTPRoute:

```shell
kubectl delete service/zone-aware-routing-backend
kubectl delete deployment/zone-aware-routing-backend-local
kubectl delete deployment/zone-aware-routing-backend-nonlocal
kubectl delete httproute/zone-aware-routing
```

[Traffic Distribution]: https://kubernetes.io/docs/concepts/services-networking/service/#traffic-distribution
[Topology Aware Routing]: https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/
[Kubernetes well-known metadata]: https://kubernetes.io/docs/reference/labels-annotations-taints/#topologykubernetesiozone
[Envoy Zone Aware Routing]: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/zone_aware
Loading