Skip to content

v0.27.6

Choose a tag to compare

@zalando-robot zalando-robot released this 18 Jun 12:26
9b35db1

Changes

feature: Add support to opt-out from zone aware routing via Ingress/RouteGroup (#4049)

Introduce the annotation zalando.org/traffic-zone-aware: "false" on
Ingress and RouteGroup resources. When set, the resource receives all
endpoints across all zones, bypassing zone filtering both at the
dataclient layer (endpoint fetch) and at the routesrv layer (per-zone
route serving).

Usage:

metadata:
  annotations:
    zalando.org/traffic-zone-aware: "false"

Tasks

  1. Define zalando.org/traffic-zone-aware annotation constant in the
    kubernetes package
  2. Modify GetEndpointSlicesByService and GetEndpointSlicesByTarget
    in clusterstate.go to accept ing and rg context param respectively and
    skip zone filtering when value
    ing.disableZoneAwareness/rg.disableZoneAwareness is true
  3. Add zoneAwarenessAnnotationFilter() helper that returns an annotate()
    filter when the zone-aware opt-out annotation is present
  4. Modify Ingress v1 path rule conversion (convertPathRuleV1) and
    default backend conversion (convertDefaultBackendV1) to read the
    annotation, pass it to endpoint fetch and prepend the annotate() filter
    when annotation is set
  5. Modify RouteGroup backend application (applyServiceBackend) to read
    the annotation, pass it to endpoint fetch and prepend the annotate()
    filter when annotation is set
  6. Add isZoneAwarenessDisabled() in routesrv/polling.go to detect the
    opt-out by inspecting the route filter chain
  7. Wire isZoneAwarenessDisabled() into getRouteForZone() to skip zone
    filtering for opted-out routes
  8. Update makeRoute test helper to inject the annotate() filter when the
    opt-out flag is passed
  9. Add integration test with two Ingresses in zone eu-central-1a: one
    opted out (expects all endpoints across zones), one default (expects
    only zone-local endpoints)
  10. Add unit tests for filterRoutesByZone covering opt-out scenarios:
    both routes opted out, opt-out mixed with normal route, and opt-out with
    a below-threshold zone

Tested the changes:
The skipper-ingress with zone aware routing enabled was in Zone-A

  1. Deployed ingress with 10 replicas, which means 10 endpoints are
    available
zkubectl -n gmapp1 get pods -L topology.kubernetes.io/zone
NAME                       READY   STATUS    RESTARTS   AGE   ZONE
app1-v8-5c5965f6d4-7h6zr   1/1     Running   0          69s   eu-central-1a
app1-v8-5c5965f6d4-7tnq4   1/1     Running   0          68s   eu-central-1a
app1-v8-5c5965f6d4-98mz7   1/1     Running   0          68s   eu-central-1c
app1-v8-5c5965f6d4-99n9p   1/1     Running   0          69s   eu-central-1c
app1-v8-5c5965f6d4-bvdst   1/1     Running   0          69s   eu-central-1a
app1-v8-5c5965f6d4-htn78   1/1     Running   0          68s   eu-central-1b
app1-v8-5c5965f6d4-q75b9   1/1     Running   0          69s   eu-central-1b
app1-v8-5c5965f6d4-wtgm5   1/1     Running   0          69s   eu-central-1a
app1-v8-5c5965f6d4-xhv9q   1/1     Running   0          69s   eu-central-1c
app1-v8-5c5965f6d4-zlz9x   1/1     Running   0          69s   eu-central-1b

This meets the threshold to serve same zone endpoints, but since the
ingress has the opt-out annotation, the route contains all the endpoints
and not just zone filtered

kube_gmapp1__app1_v8_traffic_segment__gmapp1_pg9_test_zalan_do____app1_v8: Host(/^(gmapp1[.]pg9-test[.]zalan[.]do[.]?(:[0-9]+)?)$/) && TrafficSegment(0, 1)
  -> disableAccessLog(2, 3, 404, 429)
  -> fifo(2000, 20, "1s")
  -> annotate("zalando.org/traffic-zone-aware", "false")
  -> oauthTokeninfoValidate("{optOutAnnotations: [iam.zalando.org/public], optOutHosts: [\"^.*[.]ingress[.]cluster[.]local\"], unauthorizedResponse: \"Authentication required, see https://cloud.docs.zalando.net/howtos/authenticate-requests/#default-authentication\\n\"}")
  -> stateBagToTag("auth-user", "client.uid")
  -> <powerOfRandomNChoices, "http://[2a05:d024:90:1103:3e99::6]:8080", "http://[2a05:d024:90:1103:3e99::7]:8080", "http://[2a05:d024:90:1103:3e99::8]:8080", "http://[2a05:d024:90:1103:3e99::9]:8080", "http://[2a05:d024:90:1104:2396::a]:8080", "http://[2a05:d024:90:1104:2396::b]:8080", "http://[2a05:d024:90:1104:2396::c]:8080", "http://[2a05:d024:90:1105:4749::4]:8080", "http://[2a05:d024:90:1105:4749::6]:8080", "http://[2a05:d024:90:1105:4749::7]:8080">;
  1. Deployed a routegroup with 15 replicas, which means 15 endpoints are
    available
zkubectl -n gmapp2 get pods -L topology.kubernetes.io/zone
NAME                     READY   STATUS    RESTARTS   AGE    ZONE
app2-v2-c9694944-598mc   1/1     Running   0          7m6s   eu-central-1c
app2-v2-c9694944-6bcpm   1/1     Running   0          7m6s   eu-central-1c
app2-v2-c9694944-7jgpp   1/1     Running   0          7m7s   eu-central-1b
app2-v2-c9694944-88xzb   1/1     Running   0          7m7s   eu-central-1a
app2-v2-c9694944-8kl6q   1/1     Running   0          7m6s   eu-central-1c
app2-v2-c9694944-8wc97   1/1     Running   0          7m7s   eu-central-1c
app2-v2-c9694944-cv9g8   1/1     Running   0          7m7s   eu-central-1c
app2-v2-c9694944-dkh2h   1/1     Running   0          7m6s   eu-central-1a
app2-v2-c9694944-flnx9   1/1     Running   0          7m6s   eu-central-1a
app2-v2-c9694944-klk6r   1/1     Running   0          7m7s   eu-central-1a
app2-v2-c9694944-kwddv   1/1     Running   0          7m6s   eu-central-1b
app2-v2-c9694944-pjbtz   1/1     Running   0          7m6s   eu-central-1a
app2-v2-c9694944-q5xrh   1/1     Running   0          7m7s   eu-central-1b
app2-v2-c9694944-rs8hk   1/1     Running   0          7m7s   eu-central-1a
app2-v2-c9694944-t6crt   1/1     Running   0          7m6s   eu-central-1b

This meets the threshold to serve same zone endpoints, but since the
routegroup has the opt-out annotation, the route contains all the
endpoints and not just zone filtered

kube_rg__gmapp2__app2_v2_traffic_segment__get__0_0: Path("/test") && Host(/^(app2[.]teapot[.]zalan[.]do[.]?(:[0-9]+)?)$/) && Method("GET") && TrafficSegment(0, 1)
  -> disableAccessLog(2, 3, 404, 429)
  -> fifo(2000, 20, "1s")
  -> annotate("zalando.org/traffic-zone-aware", "false")
  -> annotate("iam.zalando.org/public", "The application uses its own authentication logic, similar to using Partner IAM.")
  -> status(200)
  -> inlineContent("Hello from second backend!")
  -> oauthTokeninfoValidate("{optOutAnnotations: [iam.zalando.org/public], optOutHosts: [\"^.*[.]ingress[.]cluster[.]local\"], unauthorizedResponse: \"Authentication required, see https://cloud.docs.zalando.net/howtos/authenticate-requests/#default-authentication\\n\"}")
  -> stateBagToTag("auth-user", "client.uid")
  -> <powerOfRandomNChoices, "http://[2a05:d024:90:1103:3e99::10]:8080", "http://[2a05:d024:90:1103:3e99::11]:8080", "http://[2a05:d024:90:1103:3e99::12]:8080", "http://[2a05:d024:90:1103:3e99::13]:8080", "http://[2a05:d024:90:1103:3e99::14]:8080", "http://[2a05:d024:90:1103:3e99::f]:8080", "http://[2a05:d024:90:1104:2396::10]:8080", "http://[2a05:d024:90:1104:2396::d]:8080", "http://[2a05:d024:90:1104:2396::e]:8080", "http://[2a05:d024:90:1104:2396::f]:8080", "http://[2a05:d024:90:1105:4749::8]:8080", "http://[2a05:d024:90:1105:4749::9]:8080", "http://[2a05:d024:90:1105:4749::a]:8080", "http://[2a05:d024:90:1105:4749::b]:8080", "http://[2a05:d024:90:1105:4749::c]:8080">;

ref: #3971


Multiarch Docker image

Multiarch Docker image is available in GitHub's docker registry:

docker run -it ghcr.io/zalando/skipper:v0.27.6 skipper --help