Skip to content

Commit

Permalink
LoadBalancer in BackendTrafficPolicy (envoyproxy#2063)
Browse files Browse the repository at this point in the history
* LoadBalancer in BackendTrafficPolicy

Fixes: envoyproxy#1105

Signed-off-by: Arko Dasgupta <arko@tetrate.io>

* tests

Signed-off-by: Arko Dasgupta <arko@tetrate.io>

---------

Signed-off-by: Arko Dasgupta <arko@tetrate.io>
Signed-off-by: zirain <zirain2009@gmail.com>
  • Loading branch information
arkodg authored and zirain committed Oct 26, 2023
1 parent 49e6163 commit 0b67360
Show file tree
Hide file tree
Showing 9 changed files with 615 additions and 6 deletions.
6 changes: 6 additions & 0 deletions api/v1alpha1/backendtrafficpolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@ type BackendTrafficPolicySpec struct {

// RateLimit allows the user to limit the number of incoming requests
// to a predefined value based on attributes within the traffic flow.
// +optional
RateLimit *RateLimitFilterSpec `json:"rateLimit,omitempty"`

// LoadBalancer policy to apply when routing traffic from the gateway to
// the backend endpoints
// +optional
LoadBalancer *LoadBalancer `json:"loadBalancer,omitempty"`
}

// BackendTrafficPolicyStatus defines the state of BackendTrafficPolicy
Expand Down
6 changes: 3 additions & 3 deletions api/v1alpha1/envoygateway_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func DefaultEnvoyGatewayLogging() *EnvoyGatewayLogging {
}
}

// GetEnvoyGatewayAdmin returns the EnvoyGatewayAdmin of EnvoyGateway or a default EnvoyGatewayAdmin if unspecified.
// GetEnvoyGatewayTelemetry returns the EnvoyGatewayTelemetry of EnvoyGateway or a default EnvoyGatewayTelemetry if unspecified.
func (e *EnvoyGateway) GetEnvoyGatewayTelemetry() *EnvoyGatewayTelemetry {
if e.Telemetry != nil {
if e.Telemetry.Metrics.Prometheus == nil {
Expand All @@ -109,8 +109,8 @@ func (e *EnvoyGateway) GetEnvoyGatewayTelemetry() *EnvoyGatewayTelemetry {
return e.Telemetry
}

// IfDisablePrometheus returns if disable prometheus.
func (e *EnvoyGateway) IfDisablePrometheus() bool {
// DisablePrometheus returns if disable prometheus.
func (e *EnvoyGateway) DisablePrometheus() bool {
return e.GetEnvoyGatewayTelemetry().Metrics.Prometheus.Disable
}

Expand Down
55 changes: 55 additions & 0 deletions api/v1alpha1/loadbalancer_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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 v1alpha1

// LoadBalancer defines the load balancer policy to be applied.
// +union
type LoadBalancer struct {
// Type decides the type of Load Balancer policy.
// Valid RateLimitType values are
// "ConsistentHash",
// "LeastRequest",
// "Random",
// "RoundRobin",
//
// +unionDiscriminator
Type LoadBalancerType `json:"type"`
// ConsistentHash defines the configuration when the load balancer type is
// set to ConsistentHash
//
// +optional
ConsistentHash *ConsistentHash `json:"consistentHash,omitempty"`
}

// LoadBalancerType specifies the types of LoadBalancer.
// +kubebuilder:validation:Enum=ConsistentHash;LeastRequest;Random;RoundRobin
type LoadBalancerType string

const (
// ConsistentHashLoadBalancerType load balancer policy.
ConsistentHashLoadBalancerType LoadBalancerType = "ConsistentHash"
// LeastRequestLoadBalancerType load balancer policy.
LeastRequestLoadBalancerType LoadBalancerType = "LeastRequest"
// RandomLoadBalancerType load balancer policy.
RandomLoadBalancerType LoadBalancerType = "Random"
// RoundRobinLoadBalancerType load balancer policy.
RoundRobinLoadBalancerType LoadBalancerType = "RoundRobin"
)

// ConsistentHash defines the configuration related to the consistent hash
// load balancer policy
type ConsistentHash struct {
Type ConsistentHashType `json:"type"`
}

// ConsistentHashType defines the type of input to hash on.
// +kubebuilder:validation:Enum=SourceIP
type ConsistentHashType string

const (
// SourceIPConsistentHashType hashes based on the source IP address.
SourceIPConsistentHashType ConsistentHashType = "SourceIP"
)
40 changes: 40 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 @@ -44,6 +44,36 @@ spec:
spec:
description: spec defines the desired state of BackendTrafficPolicy.
properties:
loadBalancer:
description: LoadBalancer policy to apply when routing traffic from
the gateway to the backend endpoints
properties:
consistentHash:
description: ConsistentHash defines the configuration when the
load balancer type is set to ConsistentHash
properties:
type:
description: ConsistentHashType defines the type of input
to hash on.
enum:
- SourceIP
type: string
required:
- type
type: object
type:
description: Type decides the type of Load Balancer policy. Valid
RateLimitType values are "ConsistentHash", "LeastRequest", "Random",
"RoundRobin",
enum:
- ConsistentHash
- LeastRequest
- Random
- RoundRobin
type: string
required:
- type
type: object
rateLimit:
description: RateLimit allows the user to limit the number of incoming
requests to a predefined value based on attributes within the traffic
Expand Down
51 changes: 48 additions & 3 deletions internal/gatewayapi/backendtrafficpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,18 @@ func resolveBTPolicyRouteTargetRef(policy *egv1a1.BackendTrafficPolicy, routes m
}

func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.BackendTrafficPolicy, route RouteContext, xdsIR XdsIRMap) {
var (
rl *ir.RateLimit
lb *ir.LoadBalancer
)

// Build IR
var rl *ir.RateLimit
if policy.Spec.RateLimit != nil {
rl = t.buildRateLimit(policy)
}
if policy.Spec.LoadBalancer != nil {
lb = t.buildLoadBalancer(policy)
}

// Apply IR to all relevant routes
prefix := irRoutePrefix(route)
Expand All @@ -252,6 +259,7 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
// Apply if there is a match
if strings.HasPrefix(r.Name, prefix) {
r.RateLimit = rl
r.LoadBalancer = lb
}
}
}
Expand All @@ -260,12 +268,18 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
}

func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.BackendTrafficPolicy, gateway *GatewayContext, xdsIR XdsIRMap) {
var (
rl *ir.RateLimit
lb *ir.LoadBalancer
)

// Build IR
var rl *ir.RateLimit
if policy.Spec.RateLimit != nil {
rl = t.buildRateLimit(policy)
}

if policy.Spec.LoadBalancer != nil {
lb = t.buildLoadBalancer(policy)
}
// Apply IR to all the routes within the specific Gateway
// If the feature is already set, then skip it, since it must be have
// set by a policy attaching to the route
Expand All @@ -279,6 +293,9 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
if r.RateLimit == nil {
r.RateLimit = rl
}
if r.LoadBalancer == nil {
r.LoadBalancer = lb
}
}
}

Expand Down Expand Up @@ -392,3 +409,31 @@ func (t *Translator) buildRateLimit(policy *egv1a1.BackendTrafficPolicy) *ir.Rat

return rateLimit
}

func (t *Translator) buildLoadBalancer(policy *egv1a1.BackendTrafficPolicy) *ir.LoadBalancer {
var lb *ir.LoadBalancer
switch policy.Spec.LoadBalancer.Type {
case egv1a1.ConsistentHashLoadBalancerType:
lb = &ir.LoadBalancer{
ConsistentHash: &ir.ConsistentHash{},
}
if policy.Spec.LoadBalancer.ConsistentHash != nil &&
policy.Spec.LoadBalancer.ConsistentHash.Type == egv1a1.SourceIPConsistentHashType {
lb.ConsistentHash.SourceIP = ptr.To(true)
}
case egv1a1.LeastRequestLoadBalancerType:
lb = &ir.LoadBalancer{
LeastRequest: &ir.LeastRequest{},
}
case egv1a1.RandomLoadBalancerType:
lb = &ir.LoadBalancer{
Random: &ir.Random{},
}
case egv1a1.RoundRobinLoadBalancerType:
lb = &ir.LoadBalancer{
RoundRobin: &ir.RoundRobin{},
}
}

return lb
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
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
- apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
namespace: envoy-gateway
name: gateway-2
spec:
gatewayClassName: envoy-gateway-class
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
grpcRoutes:
- apiVersion: gateway.networking.k8s.io/v1alpha2
kind: GRPCRoute
metadata:
namespace: default
name: grpcroute-1
spec:
parentRefs:
- namespace: envoy-gateway
name: gateway-1
sectionName: http
rules:
- backendRefs:
- name: service-1
port: 8080
httpRoutes:
- apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: default
name: httproute-1
spec:
hostnames:
- gateway.envoyproxy.io
parentRefs:
- namespace: envoy-gateway
name: gateway-2
sectionName: http
rules:
- matches:
- path:
value: "/"
backendRefs:
- name: service-1
port: 8080
backendTrafficPolicies:
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: envoy-gateway
name: policy-for-gateway
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: gateway-1
namespace: envoy-gateway
loadBalancer:
type: Random
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: default
name: policy-for-route
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: httproute-1
namespace: default
loadBalancer:
type: ConsistentHash
consistentHash:
type: SourceIP
Loading

0 comments on commit 0b67360

Please sign in to comment.