Skip to content

Commit 4c36666

Browse files
authored
feat: Support configuring maxConnectionAge in xDSServer (#7374)
Fixes: #7007 Signed-off-by: Arko Dasgupta <[email protected]>
1 parent d4e44fd commit 4c36666

File tree

7 files changed

+173
-4
lines changed

7 files changed

+173
-4
lines changed

api/v1alpha1/envoygateway_helpers.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func DefaultEnvoyGateway() *EnvoyGateway {
2727
Logging: DefaultEnvoyGatewayLogging(),
2828
Admin: DefaultEnvoyGatewayAdmin(),
2929
Telemetry: DefaultEnvoyGatewayTelemetry(),
30+
XDSServer: DefaultXDSServer(),
3031
},
3132
}
3233
}
@@ -67,6 +68,9 @@ func (e *EnvoyGateway) SetEnvoyGatewayDefaults() {
6768
if e.Telemetry == nil {
6869
e.Telemetry = DefaultEnvoyGatewayTelemetry()
6970
}
71+
if e.XDSServer == nil {
72+
e.XDSServer = DefaultXDSServer()
73+
}
7074
}
7175

7276
// GetEnvoyGatewayAdmin returns the EnvoyGatewayAdmin of EnvoyGateway or a default EnvoyGatewayAdmin if unspecified.
@@ -172,6 +176,11 @@ func DefaultGateway() *Gateway {
172176
}
173177
}
174178

179+
// DefaultXDSServer returns a new XDSServer with default configuration parameters.
180+
func DefaultXDSServer() *XDSServer {
181+
return &XDSServer{}
182+
}
183+
175184
// DefaultEnvoyGatewayLogging returns a new EnvoyGatewayLogging with default configuration parameters.
176185
func DefaultEnvoyGatewayLogging() *EnvoyGatewayLogging {
177186
return &EnvoyGatewayLogging{

api/v1alpha1/envoygateway_types.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ type EnvoyGatewaySpec struct {
7474
// +optional
7575
Telemetry *EnvoyGatewayTelemetry `json:"telemetry,omitempty"`
7676

77+
// XDSServer defines the configuration for the Envoy Gateway xDS gRPC server.
78+
// If unspecified, default connection keepalive settings will be used.
79+
//
80+
// +optional
81+
XDSServer *XDSServer `json:"xdsServer,omitempty"`
82+
7783
// RateLimit defines the configuration associated with the Rate Limit service
7884
// deployed by Envoy Gateway required to implement the Global Rate limiting
7985
// functionality. The specific rate limit service used here is the reference
@@ -140,6 +146,21 @@ type KubernetesClientRateLimit struct {
140146
Burst *int32 `json:"burst,omitempty"`
141147
}
142148

149+
// XDSServer defines configuration values for the xDS gRPC server.
150+
type XDSServer struct {
151+
// MaxConnectionAge is the maximum age of an active connection before Envoy Gateway will initiate a graceful close.
152+
// If unspecified, Envoy Gateway randomly selects a value between 10h and 12h to stagger reconnects across replicas.
153+
//
154+
// +optional
155+
MaxConnectionAge *gwapiv1.Duration `json:"maxConnectionAge,omitempty"`
156+
157+
// MaxConnectionAgeGrace is the grace period granted after reaching MaxConnectionAge before the connection is forcibly closed.
158+
// The default grace period is 2m.
159+
//
160+
// +optional
161+
MaxConnectionAgeGrace *gwapiv1.Duration `json:"maxConnectionAgeGrace,omitempty"`
162+
}
163+
143164
// LeaderElection defines the desired leader election settings.
144165
type LeaderElection struct {
145166
// LeaseDuration defines the time non-leader contenders will wait before attempting to claim leadership.

api/v1alpha1/validation/envoygateway_validate.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"fmt"
1010
"net/url"
1111
"strings"
12+
"time"
1213

1314
corev1 "k8s.io/api/core/v1"
1415

@@ -62,6 +63,10 @@ func ValidateEnvoyGateway(eg *egv1a1.EnvoyGateway) error {
6263
return err
6364
}
6465

66+
if err := validateEnvoyGatewayXDSServer(eg.XDSServer); err != nil {
67+
return err
68+
}
69+
6570
return nil
6671
}
6772

@@ -225,6 +230,34 @@ func validateEnvoyGatewayExtensionManager(extensionManager *egv1a1.ExtensionMana
225230
return nil
226231
}
227232

233+
func validateEnvoyGatewayXDSServer(xdsServer *egv1a1.XDSServer) error {
234+
if xdsServer == nil {
235+
return nil
236+
}
237+
238+
if xdsServer.MaxConnectionAge != nil {
239+
d, err := time.ParseDuration(string(*xdsServer.MaxConnectionAge))
240+
if err != nil {
241+
return fmt.Errorf("invalid xdsServer.maxConnectionAge: %w", err)
242+
}
243+
if d <= 0 {
244+
return fmt.Errorf("xdsServer.maxConnectionAge must be greater than zero")
245+
}
246+
}
247+
248+
if xdsServer.MaxConnectionAgeGrace != nil {
249+
d, err := time.ParseDuration(string(*xdsServer.MaxConnectionAgeGrace))
250+
if err != nil {
251+
return fmt.Errorf("invalid xdsServer.maxConnectionAgeGrace: %w", err)
252+
}
253+
if d <= 0 {
254+
return fmt.Errorf("xdsServer.maxConnectionAgeGrace must be greater than zero")
255+
}
256+
}
257+
258+
return nil
259+
}
260+
228261
func validateEnvoyGatewayTelemetry(telemetry *egv1a1.EnvoyGatewayTelemetry) error {
229262
if telemetry == nil {
230263
return nil

api/v1alpha1/validation/envoygateway_validate_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,31 @@ func TestEnvoyGateway(t *testing.T) {
903903
assert.Equal(t, egv1a1.LogLevelInfo, gatewayLogging.Level[egv1a1.LogComponentGatewayDefault])
904904
}
905905

906+
func TestValidateEnvoyGatewayXDSServer(t *testing.T) {
907+
t.Run("valid no overrides", func(t *testing.T) {
908+
require.NoError(t, validateEnvoyGatewayXDSServer(nil))
909+
})
910+
911+
t.Run("valid overrides", func(t *testing.T) {
912+
age := gwapiv1.Duration("30m")
913+
grace := gwapiv1.Duration("1m")
914+
x := &egv1a1.XDSServer{MaxConnectionAge: &age, MaxConnectionAgeGrace: &grace}
915+
require.NoError(t, validateEnvoyGatewayXDSServer(x))
916+
})
917+
918+
t.Run("invalid duration", func(t *testing.T) {
919+
age := gwapiv1.Duration("bad")
920+
x := &egv1a1.XDSServer{MaxConnectionAge: &age}
921+
require.Error(t, validateEnvoyGatewayXDSServer(x))
922+
})
923+
924+
t.Run("non positive", func(t *testing.T) {
925+
age := gwapiv1.Duration("0s")
926+
x := &egv1a1.XDSServer{MaxConnectionAgeGrace: &age}
927+
require.Error(t, validateEnvoyGatewayXDSServer(x))
928+
})
929+
}
930+
906931
func TestDefaultEnvoyGatewayLoggingLevel(t *testing.T) {
907932
type args struct {
908933
component string

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/xds/runner/runner.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,41 @@ func (r *Runner) Name() string {
9696
return string(egv1a1.LogComponentXdsRunner)
9797
}
9898

99-
func defaultServerKeepaliveParams() keepalive.ServerParameters {
100-
return keepalive.ServerParameters{
99+
func (r *Runner) serverKeepaliveParams() (keepalive.ServerParameters, error) {
100+
params := keepalive.ServerParameters{
101101
MaxConnectionAge: getRandomMaxConnectionAge(),
102102
MaxConnectionAgeGrace: defaultMaxConnectionAgeGrace,
103103
}
104+
105+
if r.EnvoyGateway == nil || r.EnvoyGateway.XDSServer == nil {
106+
return params, nil
107+
}
108+
109+
cfg := r.EnvoyGateway.XDSServer
110+
111+
if cfg.MaxConnectionAge != nil {
112+
d, err := time.ParseDuration(string(*cfg.MaxConnectionAge))
113+
if err != nil {
114+
return keepalive.ServerParameters{}, fmt.Errorf("invalid xdsServer.maxConnectionAge: %w", err)
115+
}
116+
if d <= 0 {
117+
return keepalive.ServerParameters{}, fmt.Errorf("xdsServer.maxConnectionAge must be greater than zero")
118+
}
119+
params.MaxConnectionAge = d
120+
}
121+
122+
if cfg.MaxConnectionAgeGrace != nil {
123+
d, err := time.ParseDuration(string(*cfg.MaxConnectionAgeGrace))
124+
if err != nil {
125+
return keepalive.ServerParameters{}, fmt.Errorf("invalid xdsServer.maxConnectionAgeGrace: %w", err)
126+
}
127+
if d <= 0 {
128+
return keepalive.ServerParameters{}, fmt.Errorf("xdsServer.maxConnectionAgeGrace must be greater than zero")
129+
}
130+
params.MaxConnectionAgeGrace = d
131+
}
132+
133+
return params, nil
104134
}
105135

106136
// getRandomMaxConnectionAge picks a random maxConnectionAge value
@@ -127,8 +157,11 @@ func (r *Runner) Start(ctx context.Context) (err error) {
127157
}
128158
r.Logger.Info("loaded TLS certificate and key")
129159

130-
keepaliveParams := defaultServerKeepaliveParams()
131-
r.Logger.Info("configured gRPC keepalive defaults", "maxConnectionAge", keepaliveParams.MaxConnectionAge, "maxConnectionAgeGrace", keepaliveParams.MaxConnectionAgeGrace)
160+
keepaliveParams, err := r.serverKeepaliveParams()
161+
if err != nil {
162+
return err
163+
}
164+
r.Logger.Info("configured gRPC keepalive", "maxConnectionAge", keepaliveParams.MaxConnectionAge, "maxConnectionAgeGrace", keepaliveParams.MaxConnectionAgeGrace)
132165

133166
enforcementPolicy := keepalive.EnforcementPolicy{
134167
MinTime: 15 * time.Second,

site/content/en/latest/api/extension_types.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,7 @@ EnvoyGateway is the schema for the envoygateways API.
12791279
| `logging` | _[EnvoyGatewayLogging](#envoygatewaylogging)_ | false | \{ default:info \} | Logging defines logging parameters for Envoy Gateway. |
12801280
| `admin` | _[EnvoyGatewayAdmin](#envoygatewayadmin)_ | false | | Admin defines the desired admin related abilities.<br />If unspecified, the Admin is used with default configuration<br />parameters. |
12811281
| `telemetry` | _[EnvoyGatewayTelemetry](#envoygatewaytelemetry)_ | false | | Telemetry defines the desired control plane telemetry related abilities.<br />If unspecified, the telemetry is used with default configuration. |
1282+
| `xdsServer` | _[XDSServer](#xdsserver)_ | false | | XDSServer defines the configuration for the Envoy Gateway xDS gRPC server.<br />If unspecified, default connection keepalive settings will be used. |
12821283
| `rateLimit` | _[RateLimit](#ratelimit)_ | false | | RateLimit defines the configuration associated with the Rate Limit service<br />deployed by Envoy Gateway required to implement the Global Rate limiting<br />functionality. The specific rate limit service used here is the reference<br />implementation in Envoy. For more details visit https://github.com/envoyproxy/ratelimit.<br />This configuration is unneeded for "Local" rate limiting. |
12831284
| `extensionManager` | _[ExtensionManager](#extensionmanager)_ | false | | ExtensionManager defines an extension manager to register for the Envoy Gateway Control Plane. |
12841285
| `extensionApis` | _[ExtensionAPISettings](#extensionapisettings)_ | false | | ExtensionAPIs defines the settings related to specific Gateway API Extensions<br />implemented by Envoy Gateway |
@@ -1547,6 +1548,7 @@ _Appears in:_
15471548
| `logging` | _[EnvoyGatewayLogging](#envoygatewaylogging)_ | false | \{ default:info \} | Logging defines logging parameters for Envoy Gateway. |
15481549
| `admin` | _[EnvoyGatewayAdmin](#envoygatewayadmin)_ | false | | Admin defines the desired admin related abilities.<br />If unspecified, the Admin is used with default configuration<br />parameters. |
15491550
| `telemetry` | _[EnvoyGatewayTelemetry](#envoygatewaytelemetry)_ | false | | Telemetry defines the desired control plane telemetry related abilities.<br />If unspecified, the telemetry is used with default configuration. |
1551+
| `xdsServer` | _[XDSServer](#xdsserver)_ | false | | XDSServer defines the configuration for the Envoy Gateway xDS gRPC server.<br />If unspecified, default connection keepalive settings will be used. |
15501552
| `rateLimit` | _[RateLimit](#ratelimit)_ | false | | RateLimit defines the configuration associated with the Rate Limit service<br />deployed by Envoy Gateway required to implement the Global Rate limiting<br />functionality. The specific rate limit service used here is the reference<br />implementation in Envoy. For more details visit https://github.com/envoyproxy/ratelimit.<br />This configuration is unneeded for "Local" rate limiting. |
15511553
| `extensionManager` | _[ExtensionManager](#extensionmanager)_ | false | | ExtensionManager defines an extension manager to register for the Envoy Gateway Control Plane. |
15521554
| `extensionApis` | _[ExtensionAPISettings](#extensionapisettings)_ | false | | ExtensionAPIs defines the settings related to specific Gateway API Extensions<br />implemented by Envoy Gateway |
@@ -5356,6 +5358,22 @@ _Appears in:_
53565358
| `DropHeader` | WithUnderscoresActionDropHeader drops the client header with name containing underscores. The header<br />is dropped before the filter chain is invoked and as such filters will not see<br />dropped headers.<br /> |
53575359

53585360

5361+
#### XDSServer
5362+
5363+
5364+
5365+
XDSServer defines configuration values for the xDS gRPC server.
5366+
5367+
_Appears in:_
5368+
- [EnvoyGateway](#envoygateway)
5369+
- [EnvoyGatewaySpec](#envoygatewayspec)
5370+
5371+
| Field | Type | Required | Default | Description |
5372+
| --- | --- | --- | --- | --- |
5373+
| `maxConnectionAge` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#duration)_ | false | | MaxConnectionAge is the maximum age of an active connection before Envoy Gateway will initiate a graceful close.<br />If unspecified, Envoy Gateway randomly selects a value between 10h and 12h to stagger reconnects across replicas. |
5374+
| `maxConnectionAgeGrace` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#duration)_ | false | | MaxConnectionAgeGrace is the grace period granted after reaching MaxConnectionAge before the connection is forcibly closed.<br />The default grace period is 2m. |
5375+
5376+
53595377
#### XDSTranslatorHook
53605378

53615379
_Underlying type:_ _string_

0 commit comments

Comments
 (0)