Skip to content

Commit

Permalink
implement backend
Browse files Browse the repository at this point in the history
Signed-off-by: Guy Daich <[email protected]>
  • Loading branch information
guydc committed May 28, 2024
1 parent 57a6ea3 commit 67106e1
Show file tree
Hide file tree
Showing 74 changed files with 5,357 additions and 275 deletions.
13 changes: 0 additions & 13 deletions api/v1alpha1/backend_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const (
// AppProtocolType defines various backend applications protocols supported by Envoy Gateway
//
// +kubebuilder:validation:Enum=gateway.envoyproxy.io/h2c;gateway.envoyproxy.io/ws;gateway.envoyproxy.io/wss
// +notImplementedHide
type AppProtocolType string

const (
Expand All @@ -37,7 +36,6 @@ const (
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].reason`
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// +notImplementedHide
type Backend struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand All @@ -54,7 +52,6 @@ type Backend struct {
//
// +kubebuilder:validation:XValidation:rule="(has(self.fqdn) || has(self.ipv4) || has(self.unix))",message="one of fqdn, ipv4 or unix must be specified"
// +kubebuilder:validation:XValidation:rule="((has(self.fqdn) && !(has(self.ipv4) || has(self.unix))) || (has(self.ipv4) && !(has(self.fqdn) || has(self.unix))) || (has(self.unix) && !(has(self.ipv4) || has(self.fqdn))))",message="only one of fqdn, ipv4 or unix can be specified"
// +notImplementedHide
type BackendEndpoint struct {
// FQDN defines a FQDN endpoint
//
Expand All @@ -74,8 +71,6 @@ type BackendEndpoint struct {

// IPv4Endpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-socketaddress
//
// +notImplementedHide
type IPv4Endpoint struct {
// Address defines the IPv4 address of the backend endpoint.
//
Expand All @@ -93,8 +88,6 @@ type IPv4Endpoint struct {

// FQDNEndpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-socketaddress
//
// +notImplementedHide
type FQDNEndpoint struct {
// Hostname defines the FQDN hostname of the backend endpoint.
//
Expand All @@ -112,16 +105,12 @@ type FQDNEndpoint struct {

// UnixSocket describes TCP/UDP unix domain socket address, corresponding to Envoy's Pipe
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-pipe
//
// +notImplementedHide
type UnixSocket struct {
// Path defines the unix domain socket path of the backend endpoint.
Path string `json:"path"`
}

// BackendSpec describes the desired state of BackendSpec.
//
// +notImplementedHide
type BackendSpec struct {
// Endpoints defines the endpoints to be used when connecting to the backend.
//
Expand Down Expand Up @@ -167,7 +156,6 @@ const (
)

// BackendStatus defines the state of Backend
// +notImplementedHide
type BackendStatus struct {
// Conditions describe the current conditions of the Backend.
//
Expand All @@ -181,7 +169,6 @@ type BackendStatus struct {
// BackendList contains a list of Backend resources.
//
// +kubebuilder:object:root=true
// +notImplementedHide
type BackendList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Expand Down
4 changes: 2 additions & 2 deletions api/v1alpha1/ext_proc_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ type ExtProc struct {
//
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=1
// +kubebuilder:validation:XValidation:message="BackendRefs only supports Service kind.",rule="self.all(f, f.kind == 'Service')"
// +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="self.all(f, f.group == '')"
// +kubebuilder:validation:XValidation:message="BackendRefs only supports Service and Backend kind.",rule="self.all(f, f.kind == 'Service' || f.kind == 'Backend')"
// +kubebuilder:validation:XValidation:message="BackendRefs only supports Core and gateway.envoyproxy.io group.",rule="self.all(f, f.group == '' || f.group == 'gateway.envoyproxy.io')"
BackendRefs []BackendRef `json:"backendRefs"`

// MessageTimeout is the timeout for a response to be returned from the external processor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,11 @@ spec:
minItems: 1
type: array
x-kubernetes-validations:
- message: BackendRefs only supports Service kind.
rule: self.all(f, f.kind == 'Service')
- message: BackendRefs only supports Core group.
rule: self.all(f, f.group == '')
- message: BackendRefs only supports Service and Backend kind.
rule: self.all(f, f.kind == 'Service' || f.kind == 'Backend')
- message: BackendRefs only supports Core and gateway.envoyproxy.io
group.
rule: self.all(f, f.group == '' || f.group == 'gateway.envoyproxy.io')
failOpen:
description: |-
FailOpen defines if requests or responses that cannot be processed due to connectivity to the
Expand Down
2 changes: 2 additions & 0 deletions charts/gateway-helm/templates/_rbac.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ resources:
- backendtrafficpolicies
- securitypolicies
- envoyextensionpolicies
- backends
verbs:
- get
- list
Expand All @@ -85,6 +86,7 @@ resources:
- backendtrafficpolicies/status
- securitypolicies/status
- envoyextensionpolicies/status
- backends/status
verbs:
- update
{{- end }}
Expand Down
1 change: 1 addition & 0 deletions examples/redis/redis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ data:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
extensionApis:
enableEnvoyPatchPolicy: true
enableBackend: true
rateLimit:
backend:
type: Redis
Expand Down
3 changes: 3 additions & 0 deletions internal/cmd/egctl/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ func translateGatewayAPIToIR(resources *gatewayapi.Resources) (*gatewayapi.Trans
GlobalRateLimitEnabled: true,
EndpointRoutingDisabled: true,
EnvoyPatchPolicyEnabled: true,
BackendEnabled: true,
}

// Fix the services in the resources section so that they have an IP address - this prevents nasty
Expand Down Expand Up @@ -309,6 +310,7 @@ func translateGatewayAPIToGatewayAPI(resources *gatewayapi.Resources) (gatewayap
GlobalRateLimitEnabled: true,
EndpointRoutingDisabled: true,
EnvoyPatchPolicyEnabled: true,
BackendEnabled: true,
}
gRes := gTranslator.Translate(resources)
// Update the status of the GatewayClass based on EnvoyProxy validation
Expand Down Expand Up @@ -341,6 +343,7 @@ func translateGatewayAPIToXds(dnsDomain string, resourceType string, resources *
GlobalRateLimitEnabled: true,
EndpointRoutingDisabled: true,
EnvoyPatchPolicyEnabled: true,
BackendEnabled: true,
}
gRes := gTranslator.Translate(resources)

Expand Down
29 changes: 29 additions & 0 deletions internal/gatewayapi/backend.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright Envoy Gateway Authors
// SPDX-License-Identifier: Apache-2.0
// The full text of the Apache license is available in the LICENSE file at
// the root of the repo.

package gatewayapi

import (
egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
"github.com/envoyproxy/gateway/internal/gatewayapi/status"
)

func (t *Translator) ProcessBackends(backends []*egv1a1.Backend) []*egv1a1.Backend {
var res []*egv1a1.Backend
for _, backend := range backends {
backend := backend.DeepCopy()

// Ensure Backends are enabled
if !t.BackendEnabled {
status.UpdateBackendStatusAcceptedCondition(backend, false)
} else {
status.UpdateBackendStatusAcceptedCondition(backend, true)
}

res = append(res, backend)
}

return res
}
17 changes: 12 additions & 5 deletions internal/gatewayapi/envoyextensionpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,11 +439,18 @@ func (t *Translator) buildExtProc(
Settings: dsl,
}

authority = fmt.Sprintf(
"%s.%s:%d",
extProc.BackendRefs[0].Name,
NamespaceDerefOr(extProc.BackendRefs[0].Namespace, policyNamespacedName.Namespace),
*extProc.BackendRefs[0].Port)
if extProc.BackendRefs[0].Port != nil {
authority = fmt.Sprintf(
"%s.%s:%d",
extProc.BackendRefs[0].Name,
NamespaceDerefOr(extProc.BackendRefs[0].Namespace, policyNamespacedName.Namespace),
*extProc.BackendRefs[0].Port)
} else {
authority = fmt.Sprintf(
"%s.%s",
extProc.BackendRefs[0].Name,
NamespaceDerefOr(extProc.BackendRefs[0].Namespace, policyNamespacedName.Namespace))

Check warning on line 452 in internal/gatewayapi/envoyextensionpolicy.go

View check run for this annotation

Codecov / codecov/patch

internal/gatewayapi/envoyextensionpolicy.go#L449-L452

Added lines #L449 - L452 were not covered by tests
}

extProcIR := &ir.ExtProc{
Name: name,
Expand Down
64 changes: 25 additions & 39 deletions internal/gatewayapi/ext_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import (
"fmt"
"strings"

v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
egv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
"github.com/envoyproxy/gateway/internal/ir"
Expand All @@ -29,68 +28,55 @@ func (t *Translator) processExtServiceDestination(
resources *Resources,
) (*ir.DestinationSetting, error) {
var (
endpoints []*ir.DestinationEndpoint
addrType *ir.DestinationAddressType
servicePort v1.ServicePort
backendTLS *ir.TLSUpstreamConfig
backendTLS *ir.TLSUpstreamConfig
ds *ir.DestinationSetting
)

serviceNamespace := NamespaceDerefOr(backendRef.Namespace, policyNamespacedName.Namespace)
service := resources.GetService(serviceNamespace, string(backendRef.Name))
for _, port := range service.Spec.Ports {
if port.Port == int32(*backendRef.Port) {
servicePort = port
break
}
}
backendNamespace := NamespaceDerefOr(backendRef.Namespace, policyNamespacedName.Namespace)

if servicePort.AppProtocol != nil &&
*servicePort.AppProtocol == "kubernetes.io/h2c" {
protocol = ir.HTTP2
switch KindDerefOr(backendRef.Kind, KindService) {
case KindService:
ds = t.processServiceDestinationSetting(*backendRef, backendNamespace, protocol, resources)
case egv1a1.KindBackend:
if !t.BackendEnabled {
return nil, fmt.Errorf("resource %s of type Backend cannot be used since Backend is disabled in Envoy Gateway configuration", string(backendRef.Name))
}
ds = t.processBackendDestinationSetting(*backendRef, backendNamespace, resources)
ds.Protocol = protocol
}

// Route to endpoints by default
if !t.EndpointRoutingDisabled {
endpointSlices := resources.GetEndpointSlicesForBackend(
serviceNamespace, string(backendRef.Name), KindService)
endpoints, addrType = getIREndpointsFromEndpointSlices(
endpointSlices, servicePort.Name, servicePort.Protocol)
} else {
// Fall back to Service ClusterIP routing
ep := ir.NewDestEndpoint(
service.Spec.ClusterIP,
uint32(*backendRef.Port))
endpoints = append(endpoints, ep)
if ds == nil {
return nil, errors.New(
"failed to translate external service backendRef")

Check warning on line 50 in internal/gatewayapi/ext_service.go

View check run for this annotation

Codecov / codecov/patch

internal/gatewayapi/ext_service.go#L49-L50

Added lines #L49 - L50 were not covered by tests
}

// TODO: support mixed endpointslice address type for the same backendRef
if !t.EndpointRoutingDisabled && addrType != nil && *addrType == ir.MIXED {
if !t.EndpointRoutingDisabled && ds.AddressType != nil && *ds.AddressType == ir.MIXED {
return nil, errors.New(
"mixed endpointslice address type for the same backendRef is not supported")
}

backendTLS = t.applyBackendTLSSetting(
*backendRef,
serviceNamespace,
backendNamespace,
// Gateway is not the appropriate parent reference here because the owner
// of the BackendRef is the policy, and there is no hierarchy
// relationship between the policy and a gateway.
// The owner policy of the BackendRef is used as the parent reference here.
egv1a2.ParentReference{
gwapiv1a2.ParentReference{
Group: ptr.To(gwapiv1.Group(egv1a1.GroupName)),
Kind: ptr.To(gwapiv1.Kind(policyKind)),
Namespace: ptr.To(gwapiv1.Namespace(policyNamespacedName.Namespace)),
Name: gwapiv1.ObjectName(policyNamespacedName.Name),
},
resources)

return &ir.DestinationSetting{
Weight: ptr.To(uint32(1)),
Protocol: protocol,
Endpoints: endpoints,
AddressType: addrType,
TLS: backendTLS,
}, nil
ds.TLS = backendTLS

// TODO: support weighted non-xRoute backends
ds.Weight = ptr.To(uint32(1))

return ds, nil
}

// TODO: also refer to extension type, as WASM may also introduce destinations
Expand Down
12 changes: 12 additions & 0 deletions internal/gatewayapi/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ type Resources struct {
SecurityPolicies []*egv1a1.SecurityPolicy `json:"securityPolicies,omitempty" yaml:"securityPolicies,omitempty"`
BackendTLSPolicies []*gwapiv1a3.BackendTLSPolicy `json:"backendTLSPolicies,omitempty" yaml:"backendTLSPolicies,omitempty"`
EnvoyExtensionPolicies []*egv1a1.EnvoyExtensionPolicy `json:"envoyExtensionPolicies,omitempty" yaml:"envoyExtensionPolicies,omitempty"`
Backends []*egv1a1.Backend `json:"backends,omitempty" yaml:"backends,omitempty"`
}

func NewResources() *Resources {
Expand All @@ -77,6 +78,7 @@ func NewResources() *Resources {
SecurityPolicies: []*egv1a1.SecurityPolicy{},
BackendTLSPolicies: []*gwapiv1a3.BackendTLSPolicy{},
EnvoyExtensionPolicies: []*egv1a1.EnvoyExtensionPolicy{},
Backends: []*egv1a1.Backend{},

Check warning on line 81 in internal/gatewayapi/resource.go

View check run for this annotation

Codecov / codecov/patch

internal/gatewayapi/resource.go#L81

Added line #L81 was not covered by tests
}
}

Expand Down Expand Up @@ -110,6 +112,16 @@ func (r *Resources) GetServiceImport(namespace, name string) *mcsapi.ServiceImpo
return nil
}

func (r *Resources) GetBackend(namespace, name string) *egv1a1.Backend {
for _, be := range r.Backends {
if be.Namespace == namespace && be.Name == name {
return be
}
}

return nil

Check warning on line 122 in internal/gatewayapi/resource.go

View check run for this annotation

Codecov / codecov/patch

internal/gatewayapi/resource.go#L122

Added line #L122 was not covered by tests
}

func (r *Resources) GetSecret(namespace, name string) *v1.Secret {
for _, secret := range r.Secrets {
if secret.Namespace == namespace && secret.Name == name {
Expand Down
Loading

0 comments on commit 67106e1

Please sign in to comment.