Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:support slow start mode #2219

Merged
merged 13 commits into from
Nov 24, 2023
12 changes: 12 additions & 0 deletions api/v1alpha1/loadbalancer_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@

package v1alpha1

import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

// LoadBalancer defines the load balancer policy to be applied.
// +union
//
// +kubebuilder:validation:XValidation:rule="self.type == 'ConsistentHash' ? has(self.consistentHash) : !has(self.consistentHash)",message="If LoadBalancer type is consistentHash, consistentHash field needs to be set."
// +kubebuilder:validation:XValidation:rule="self.type in ['Random', 'ConsistentHash'] ? !has(self.slowStartWindow) : true ",message="Currently SlowStartWindow is only supported for RoundRobin and LeastRequest load balancers."
type LoadBalancer struct {
// Type decides the type of Load Balancer policy.
// Valid LoadBalancerType values are
Expand All @@ -24,6 +27,15 @@ type LoadBalancer struct {
//
// +optional
ConsistentHash *ConsistentHash `json:"consistentHash,omitempty"`

// SlowStartWindow defines the duration of the warm up period for newly added host.
// If set, during slow start window, traffic sent to the newly added hosts will gradually increase in a linear manner.
// Currently this is only supported for RoundRobin and LeastRequest load balancers.
tmsnan marked this conversation as resolved.
Show resolved Hide resolved
// For additional details,
// see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-slowstartconfig
//
// +optional
SlowStartWindow *metav1.Duration `json:"slowStartWindow,omitempty"`
tmsnan marked this conversation as resolved.
Show resolved Hide resolved
tmsnan marked this conversation as resolved.
Show resolved Hide resolved
arkodg marked this conversation as resolved.
Show resolved Hide resolved
}

// LoadBalancerType specifies the types of LoadBalancer.
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 @@ -61,6 +61,14 @@ spec:
required:
- type
type: object
slowStartWindow:
description: SlowStartWindow defines the duration of the warm
up period for newly added host. If set, during slow start window,
traffic sent to the newly added hosts will gradually increase
in a linear manner. Currently this is only supported for RoundRobin
and LeastRequest load balancers. For additional details, see
https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-slowstartconfig
type: string
type:
description: Type decides the type of Load Balancer policy. Valid
LoadBalancerType values are "ConsistentHash", "LeastRequest",
Expand All @@ -79,6 +87,10 @@ spec:
field needs to be set.
rule: 'self.type == ''ConsistentHash'' ? has(self.consistentHash)
: !has(self.consistentHash)'
- message: Currently SlowStartWindow is only supported for RoundRobin
and LeastRequest load balancers.
rule: 'self.type in [''Random'', ''ConsistentHash''] ? !has(self.slowStartWindow)
: true '
proxyProtocol:
description: ProxyProtocol enables the Proxy Protocol when communicating
with the backend.
Expand Down
6 changes: 6 additions & 0 deletions internal/gatewayapi/backendtrafficpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,9 @@ func (t *Translator) buildLoadBalancer(policy *egv1a1.BackendTrafficPolicy) *ir.
lb = &ir.LoadBalancer{
LeastRequest: &ir.LeastRequest{},
}
if policy.Spec.LoadBalancer.SlowStartWindow != nil {
tmsnan marked this conversation as resolved.
Show resolved Hide resolved
lb.LeastRequest.SlowStartWindow = policy.Spec.LoadBalancer.SlowStartWindow.Duration
}
case egv1a1.RandomLoadBalancerType:
lb = &ir.LoadBalancer{
Random: &ir.Random{},
Expand All @@ -433,6 +436,9 @@ func (t *Translator) buildLoadBalancer(policy *egv1a1.BackendTrafficPolicy) *ir.
lb = &ir.LoadBalancer{
RoundRobin: &ir.RoundRobin{},
}
if policy.Spec.LoadBalancer.SlowStartWindow != nil {
lb.RoundRobin.SlowStartWindow = policy.Spec.LoadBalancer.SlowStartWindow.Duration
}
}

return lb
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,25 @@ httpRoutes:
backendRefs:
- name: service-1
port: 8080
- apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: default
name: httproute-2
spec:
hostnames:
- gateway.envoyproxy.io
parentRefs:
- namespace: envoy-gateway
name: gateway-2
sectionName: http
rules:
- matches:
- path:
value: "/test2"
backendRefs:
- name: service-2
port: 8080
backendTrafficPolicies:
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
Expand Down Expand Up @@ -91,3 +110,31 @@ backendTrafficPolicies:
type: ConsistentHash
consistentHash:
type: SourceIP
- apiVersion: gateway.envoyproxy.io/v1alpha1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of creating a new route, can we just add this slowStart config to the existing config ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing route has been used to test ConsistentHash, so a new route needs to be added

kind: BackendTrafficPolicy
metadata:
namespace: envoy-gateway
name: policy-for-gateway2
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: gateway-2
namespace: envoy-gateway
loadBalancer:
type: RoundRobin
slowStartWindow: 300s
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: default
name: policy-for-route2
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: httproute-2
namespace: default
loadBalancer:
type: LeastRequest
slowStartWindow: 300s
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,28 @@ backendTrafficPolicies:
reason: Accepted
status: "True"
type: Accepted
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
creationTimestamp: null
name: policy-for-route2
namespace: default
spec:
loadBalancer:
slowStartWindow: 5m0s
type: LeastRequest
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: httproute-2
namespace: default
status:
conditions:
- lastTransitionTime: null
message: BackendTrafficPolicy has been accepted.
reason: Accepted
status: "True"
type: Accepted
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
Expand All @@ -43,6 +65,28 @@ backendTrafficPolicies:
reason: Accepted
status: "True"
type: Accepted
- apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
creationTimestamp: null
name: policy-for-gateway2
namespace: envoy-gateway
spec:
loadBalancer:
slowStartWindow: 5m0s
type: RoundRobin
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: gateway-2
namespace: envoy-gateway
status:
conditions:
- lastTransitionTime: null
message: BackendTrafficPolicy has been accepted.
reason: Accepted
status: "True"
type: Accepted
gateways:
- apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
Expand Down Expand Up @@ -101,7 +145,7 @@ gateways:
protocol: HTTP
status:
listeners:
- attachedRoutes: 1
- attachedRoutes: 2
conditions:
- lastTransitionTime: null
message: Sending translated listener configuration to the data plane
Expand Down Expand Up @@ -197,6 +241,44 @@ httpRoutes:
name: gateway-2
namespace: envoy-gateway
sectionName: http
- apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
creationTimestamp: null
name: httproute-2
namespace: default
spec:
hostnames:
- gateway.envoyproxy.io
parentRefs:
- name: gateway-2
namespace: envoy-gateway
sectionName: http
rules:
- backendRefs:
- name: service-2
port: 8080
matches:
- path:
value: /test2
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-2
namespace: envoy-gateway
sectionName: http
infraIR:
envoy-gateway/gateway-1:
proxy:
Expand Down Expand Up @@ -266,6 +348,26 @@ xdsIR:
name: envoy-gateway/gateway-2/http
port: 10080
routes:
- backendWeights:
invalid: 0
valid: 0
destination:
name: httproute/default/httproute-2/rule/0
settings:
- endpoints:
- host: 7.7.7.7
port: 8080
protocol: HTTP
weight: 1
hostname: gateway.envoyproxy.io
loadBalancer:
leastRequest:
slowStartWindow: 300000000000
name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io
pathMatch:
distinct: false
name: ""
prefix: /test2
- backendWeights:
invalid: 0
valid: 0
Expand Down
13 changes: 11 additions & 2 deletions internal/ir/xds.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"errors"
"net"
"reflect"
"time"

"github.com/tetratelabs/multierror"
"golang.org/x/exp/slices"
Expand Down Expand Up @@ -1044,11 +1045,19 @@ func (l *LoadBalancer) Validate() error {

// RoundRobin load balancer settings
// +k8s:deepcopy-gen=true
type RoundRobin struct{}
type RoundRobin struct {
// SlowStartWindow defines the duration of the warm up period for newly added host.
// If set, slow start mode is enabled for newly added hosts in the cluster.
SlowStartWindow time.Duration `json:"slowStartWindow,omitempty" yaml:"slowStartWindow,omitempty"`
}

// LeastRequest load balancer settings
// +k8s:deepcopy-gen=true
type LeastRequest struct{}
type LeastRequest struct {
// SlowStartWindow defines the duration of the warm up period for newly added host.
// If set, slow start mode is enabled for newly added hosts in the cluster.
SlowStartWindow time.Duration `json:"slowStartWindow,omitempty" yaml:"slowStartWindow,omitempty"`
}

// Random load balancer settings
// +k8s:deepcopy-gen=true
Expand Down
18 changes: 18 additions & 0 deletions internal/xds/translator/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,26 @@ func buildXdsCluster(args *xdsClusterArgs) *clusterv3.Cluster {
cluster.LbPolicy = clusterv3.Cluster_LEAST_REQUEST
} else if args.loadBalancer.LeastRequest != nil {
cluster.LbPolicy = clusterv3.Cluster_LEAST_REQUEST
if args.loadBalancer.LeastRequest.SlowStartWindow > 0 {
cluster.LbConfig = &clusterv3.Cluster_LeastRequestLbConfig_{
LeastRequestLbConfig: &clusterv3.Cluster_LeastRequestLbConfig{
SlowStartConfig: &clusterv3.Cluster_SlowStartConfig{
SlowStartWindow: durationpb.New(args.loadBalancer.LeastRequest.SlowStartWindow),
},
},
}
}
} else if args.loadBalancer.RoundRobin != nil {
cluster.LbPolicy = clusterv3.Cluster_ROUND_ROBIN
if args.loadBalancer.RoundRobin.SlowStartWindow > 0 {
cluster.LbConfig = &clusterv3.Cluster_RoundRobinLbConfig_{
RoundRobinLbConfig: &clusterv3.Cluster_RoundRobinLbConfig{
SlowStartConfig: &clusterv3.Cluster_SlowStartConfig{
SlowStartWindow: durationpb.New(args.loadBalancer.RoundRobin.SlowStartWindow),
},
},
}
}
} else if args.loadBalancer.Random != nil {
cluster.LbPolicy = clusterv3.Cluster_RANDOM
} else if args.loadBalancer.ConsistentHash != nil {
Expand Down
22 changes: 22 additions & 0 deletions internal/xds/translator/testdata/in/xds-ir/load-balancer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,25 @@ http:
- endpoints:
- host: "1.2.3.4"
port: 50000
- name: "fifth-route"
hostname: "*"
loadBalancer:
leastRequest:
slowStartWindow: 100000000
destination:
name: "fifth-route-dest"
settings:
- endpoints:
- host: "1.2.3.4"
port: 50000
- name: "sixth-route"
hostname: "*"
loadBalancer:
roundRobin:
slowStartWindow: 600000000
destination:
name: "sixth-route-dest"
settings:
- endpoints:
- host: "1.2.3.4"
port: 50000
Loading