From bd61661622e1b0e90f5aff40d28fac251eb241f1 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Wed, 16 Oct 2024 12:19:45 -0700 Subject: [PATCH] feat: implement fallback for the Backend API Relates to https://github.com/envoyproxy/gateway/issues/3055 Signed-off-by: Arko Dasgupta --- api/v1alpha1/backend_types.go | 1 - internal/gatewayapi/route.go | 12 +- .../testdata/backend-with-fallback.in.yaml | 58 ++++++ .../testdata/backend-with-fallback.out.yaml | 180 ++++++++++++++++++ site/content/en/latest/api/extension_types.md | 1 + site/content/zh/latest/api/extension_types.md | 1 + 6 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 internal/gatewayapi/testdata/backend-with-fallback.in.yaml create mode 100644 internal/gatewayapi/testdata/backend-with-fallback.out.yaml diff --git a/api/v1alpha1/backend_types.go b/api/v1alpha1/backend_types.go index a2022c2c5ef..bb407981af8 100644 --- a/api/v1alpha1/backend_types.go +++ b/api/v1alpha1/backend_types.go @@ -131,7 +131,6 @@ type BackendSpec struct { // the health of the active backends falls below 72%. // // +optional - // +notImplementedHide Fallback *bool `json:"fallback,omitempty"` } diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 1239caadc91..f82158715a5 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -1291,6 +1291,7 @@ func (t *Translator) processDestination(backendRefContext BackendRefContext, resources, envoyProxy, ) + ds.Filters = t.processDestinationFilters(routeType, backendRefContext, parentRef, route, resources) } @@ -1672,9 +1673,18 @@ func (t *Translator) processBackendDestinationSetting(backendRef gwapiv1.Backend } } - return &ir.DestinationSetting{ + ds := &ir.DestinationSetting{ Protocol: dstProtocol, Endpoints: dstEndpoints, AddressType: dstAddrType, } + + if backend.Spec.Fallback != nil { + // set only the secondary priority, the backend defaults to a primary priority if unset. + if ptr.Deref(backend.Spec.Fallback, false) { + ds.Priority = ptr.To(uint32(1)) + } + } + + return ds } diff --git a/internal/gatewayapi/testdata/backend-with-fallback.in.yaml b/internal/gatewayapi/testdata/backend-with-fallback.in.yaml new file mode 100644 index 00000000000..af87ddb8d21 --- /dev/null +++ b/internal/gatewayapi/testdata/backend-with-fallback.in.yaml @@ -0,0 +1,58 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - matches: + - path: + value: "/" + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-1 + - group: gateway.envoyproxy.io + kind: Backend + name: backend-2 +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-1 + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-2 + namespace: default + spec: + fallback: true + endpoints: + - ip: + address: 2.2.2.2 + port: 3001 diff --git a/internal/gatewayapi/testdata/backend-with-fallback.out.yaml b/internal/gatewayapi/testdata/backend-with-fallback.out.yaml new file mode 100644 index 00000000000..74bd61795fe --- /dev/null +++ b/internal/gatewayapi/testdata/backend-with-fallback.out.yaml @@ -0,0 +1,180 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-1 + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-2 + namespace: default + spec: + endpoints: + - ip: + address: 2.2.2.2 + port: 3001 + fallback: true + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Accepted +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-1 + - group: gateway.envoyproxy.io + kind: Backend + name: backend-2 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + weight: 1 + - addressType: IP + endpoints: + - host: 2.2.2.2 + port: 3001 + priority: 1 + weight: 1 + hostname: '*' + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: / diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index ddc32a2021e..8a54fb2d6c6 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -384,6 +384,7 @@ _Appears in:_ | --- | --- | --- | --- | | `endpoints` | _[BackendEndpoint](#backendendpoint) array_ | true | Endpoints defines the endpoints to be used when connecting to the backend. | | `appProtocols` | _[AppProtocolType](#appprotocoltype) array_ | false | AppProtocols defines the application protocols to be supported when connecting to the backend. | +| `fallback` | _boolean_ | false | Fallback indicates whether the backend is designated as a fallback.
It is highly recommended to configure active or passive health checks to ensure that failover can be detected
when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
The overprovisioning factor is set to 1.4, meaning the fallback backends will only start receiving traffic when
the health of the active backends falls below 72%. | #### BackendStatus diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md index ddc32a2021e..8a54fb2d6c6 100644 --- a/site/content/zh/latest/api/extension_types.md +++ b/site/content/zh/latest/api/extension_types.md @@ -384,6 +384,7 @@ _Appears in:_ | --- | --- | --- | --- | | `endpoints` | _[BackendEndpoint](#backendendpoint) array_ | true | Endpoints defines the endpoints to be used when connecting to the backend. | | `appProtocols` | _[AppProtocolType](#appprotocoltype) array_ | false | AppProtocols defines the application protocols to be supported when connecting to the backend. | +| `fallback` | _boolean_ | false | Fallback indicates whether the backend is designated as a fallback.
It is highly recommended to configure active or passive health checks to ensure that failover can be detected
when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
The overprovisioning factor is set to 1.4, meaning the fallback backends will only start receiving traffic when
the health of the active backends falls below 72%. | #### BackendStatus