Skip to content

Commit

Permalink
feat(translator): support switching between service/clusterIP routing (
Browse files Browse the repository at this point in the history
…#3543)

* feat(translator): support switching between service/clusterIP routing

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* use enum instead of bool

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* try adding e2e test

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* formatting

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* update-tests

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* incorrect default

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* fix formatting

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* Apply more suggestions

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* formatting

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* formatting

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* formatting

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* fix test

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>

* add translator test case

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
  • Loading branch information
evacchi authored Jun 14, 2024
1 parent 6425d03 commit 59614bd
Show file tree
Hide file tree
Showing 14 changed files with 505 additions and 6 deletions.
15 changes: 15 additions & 0 deletions api/v1alpha1/envoyproxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ type EnvoyProxySpec struct {
// +optional
Concurrency *int32 `json:"concurrency,omitempty"`

// RoutingType can be set to "Service" to use the Service Cluster IP for routing to the backend,
// or it can be set to "Endpoint" to use Endpoint routing. The default is "Endpoint".
// +optional
RoutingType *RoutingType `json:"routingType,omitempty"`

// ExtraArgs defines additional command line options that are provided to Envoy.
// More info: https://www.envoyproxy.io/docs/envoy/latest/operations/cli#command-line-options
// Note: some command line options are used internally(e.g. --log-level) so they cannot be provided here.
Expand Down Expand Up @@ -125,6 +130,16 @@ type EnvoyProxySpec struct {
BackendTLS *BackendTLSConfig `json:"backendTLS,omitempty"`
}

// RoutingType defines the type of routing of this Envoy proxy.
type RoutingType string

const (
// ServiceRoutingType is the RoutingType for Service Cluster IP routing.
ServiceRoutingType RoutingType = "Service"
// EndpointRoutingType is the RoutingType for Endpoint routing.
EndpointRoutingType RoutingType = "Endpoint"
)

// BackendTLSConfig describes the BackendTLS configuration for Envoy Proxy.
type BackendTLSConfig struct {
// ClientCertificateRef defines the reference to a Kubernetes Secret that contains
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -10202,6 +10202,11 @@ spec:
required:
- type
type: object
routingType:
description: |-
RoutingType can be set to "Service" to use the Service Cluster IP for routing to the backend,
or it can be set to "Endpoint" to use Endpoint routing. The default is "Endpoint".
type: string
shutdown:
description: Shutdown defines configuration for graceful envoy shutdown
process.
Expand Down
2 changes: 1 addition & 1 deletion internal/gatewayapi/ext_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (t *Translator) processExtServiceDestination(
}

// TODO: support mixed endpointslice address type for the same backendRef
if !t.EndpointRoutingDisabled && ds.AddressType != nil && *ds.AddressType == ir.MIXED {
if !t.IsEnvoyServiceRouting(resources) && ds.AddressType != nil && *ds.AddressType == ir.MIXED {
return nil, errors.New(
"mixed endpointslice address type for the same backendRef is not supported")
}
Expand Down
10 changes: 5 additions & 5 deletions internal/gatewayapi/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
for _, backendRef := range rule.BackendRefs {
backendRef := backendRef
ds := t.processDestination(backendRef, parentRef, httpRoute, resources)
if !t.EndpointRoutingDisabled && ds != nil && len(ds.Endpoints) > 0 && ds.AddressType != nil {
if !t.IsEnvoyServiceRouting(resources) && ds != nil && len(ds.Endpoints) > 0 && ds.AddressType != nil {
dstAddrTypeMap[*ds.AddressType]++
}
if ds == nil {
Expand All @@ -214,7 +214,7 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
}

// TODO: support mixed endpointslice address type between backendRefs
if !t.EndpointRoutingDisabled && len(dstAddrTypeMap) > 1 {
if !t.IsEnvoyServiceRouting(resources) && len(dstAddrTypeMap) > 1 {
routeStatus := GetRouteStatus(httpRoute)
status.SetRouteStatusCondition(routeStatus,
parentRef.routeParentStatusIdx,
Expand Down Expand Up @@ -1159,7 +1159,7 @@ func (t *Translator) processDestination(backendRefContext BackendRefContext,
}
}

if !t.EndpointRoutingDisabled {
if !t.IsEnvoyServiceRouting(resources) {
endpointSlices := resources.GetEndpointSlicesForBackend(backendNamespace, string(backendRef.Name), KindDerefOr(backendRef.Kind, KindService))
endpoints, addrType = getIREndpointsFromEndpointSlices(endpointSlices, servicePort.Name, servicePort.Protocol)
} else {
Expand Down Expand Up @@ -1210,7 +1210,7 @@ func (t *Translator) processDestination(backendRefContext BackendRefContext,
ds.Filters = t.processDestinationFilters(routeType, backendRefContext, parentRef, route, resources)
}

if err := validateDestinationSettings(ds, t.EndpointRoutingDisabled, backendRef.Kind); err != nil {
if err := validateDestinationSettings(ds, t.IsEnvoyServiceRouting(resources), backendRef.Kind); err != nil {
routeStatus := GetRouteStatus(route)
status.SetRouteStatusCondition(routeStatus,
parentRef.routeParentStatusIdx,
Expand Down Expand Up @@ -1265,7 +1265,7 @@ func (t *Translator) processServiceDestinationSetting(backendRef gwapiv1.Backend
}

// Route to endpoints by default
if !t.EndpointRoutingDisabled {
if !t.IsEnvoyServiceRouting(resources) {
endpointSlices := resources.GetEndpointSlicesForBackend(backendNamespace, string(backendRef.Name), KindDerefOr(backendRef.Kind, KindService))
endpoints, addrType = getIREndpointsFromEndpointSlices(endpointSlices, servicePort.Name, servicePort.Protocol)
} else {
Expand Down
40 changes: 40 additions & 0 deletions internal/gatewayapi/testdata/envoyproxy-endpoint-routing.in.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
envoyproxy:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
namespace: envoy-gateway-system
name: test
spec:
routingType: Endpoint
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:
- name: service-1
port: 8080
135 changes: 135 additions & 0 deletions internal/gatewayapi/testdata/envoyproxy-endpoint-routing.out.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
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:
- name: service-1
port: 8080
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:
config:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
creationTimestamp: null
name: test
namespace: envoy-gateway-system
spec:
logging: {}
routingType: Endpoint
status: {}
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
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: 7.7.7.7
port: 8080
protocol: HTTP
weight: 1
hostname: '*'
isHTTP2: false
name: httproute/default/httproute-1/rule/0/match/0/*
pathMatch:
distinct: false
name: ""
prefix: /
40 changes: 40 additions & 0 deletions internal/gatewayapi/testdata/envoyproxy-service-routing.in.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
envoyproxy:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
namespace: envoy-gateway-system
name: test
spec:
routingType: Service
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:
- name: service-1
port: 8080
Loading

0 comments on commit 59614bd

Please sign in to comment.