Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions api/v1alpha1/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ type KubernetesDeploymentSpec struct {
// +optional
Replicas *int32 `json:"replicas,omitempty"`

// ReplicasManagedByExternalAutoscaler, when set to true, tells Envoy Gateway not to
// render the replicas field on the generated Deployment, so an external autoscaler
// (an external HorizontalPodAutoscaler, a KEDA ScaledObject, etc.) can own the replica
// count without Envoy Gateway reverting it on the next reconcile. The Replicas field is
// ignored when this is true. This has no additional effect when the built-in EnvoyHpa is
// configured, which already omits the replicas field.
//
// +optional
ReplicasManagedByExternalAutoscaler *bool `json:"replicasManagedByExternalAutoscaler,omitempty"`
Comment thread
guanchzhou marked this conversation as resolved.

// The deployment strategy to use to replace existing pods with new ones.
// +optional
Strategy *appsv1.DeploymentStrategy `json:"strategy,omitempty"`
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 @@ -10350,6 +10350,15 @@ spec:
to 1.
format: int32
type: integer
replicasManagedByExternalAutoscaler:
Comment thread
guanchzhou marked this conversation as resolved.
description: |-
ReplicasManagedByExternalAutoscaler, when set to true, tells Envoy Gateway not to
render the replicas field on the generated Deployment, so an external autoscaler
(an external HorizontalPodAutoscaler, a KEDA ScaledObject, etc.) can own the replica
count without Envoy Gateway reverting it on the next reconcile. The Replicas field is
ignored when this is true. This has no additional effect when the built-in EnvoyHpa is
configured, which already omits the replicas field.
type: boolean
strategy:
description: The deployment strategy to use to replace
existing pods with new ones.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10349,6 +10349,15 @@ spec:
to 1.
format: int32
type: integer
replicasManagedByExternalAutoscaler:
description: |-
ReplicasManagedByExternalAutoscaler, when set to true, tells Envoy Gateway not to
render the replicas field on the generated Deployment, so an external autoscaler
(an external HorizontalPodAutoscaler, a KEDA ScaledObject, etc.) can own the replica
count without Envoy Gateway reverting it on the next reconcile. The Replicas field is
ignored when this is true. This has no additional effect when the built-in EnvoyHpa is
configured, which already omits the replicas field.
type: boolean
strategy:
description: The deployment strategy to use to replace
existing pods with new ones.
Expand Down
12 changes: 7 additions & 5 deletions internal/infrastructure/kubernetes/proxy/resource_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,12 +393,14 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) {
return nil, err
}

// When an HPA is configured, the replica count is owned by the HPA, so the replicas
// field is left unset here. Since the field is omitted from the server-side apply
// patch, Envoy Gateway doesn't take ownership of it and won't revert the replica
// count computed by the HPA on subsequent reconciliations.
// When an autoscaler owns the replica count, the replicas field is left unset here.
// Since the field is omitted from the server-side apply patch, Envoy Gateway doesn't
// take ownership of it and won't revert the count on subsequent reconciliations. This
// applies both to the built-in EnvoyHpa and to an external autoscaler (external HPA,
// KEDA ScaledObject, etc.) opted into via ReplicasManagedByExternalAutoscaler.
replicas := deploymentConfig.Replicas
if provider.GetEnvoyProxyKubeProvider().EnvoyHpa != nil {
if provider.GetEnvoyProxyKubeProvider().EnvoyHpa != nil ||
ptr.Deref(deploymentConfig.ReplicasManagedByExternalAutoscaler, false) {
replicas = nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,18 @@ func TestDeployment(t *testing.T) {
MaxReplicas: new(int32(10)),
},
},
{
// The replicas field must not be rendered when it is managed by an external
// autoscaler (external HPA, KEDA, etc.), even though no built-in EnvoyHpa is set,
// so that Envoy Gateway doesn't own spec.replicas and revert the external count.
caseName: "with-external-autoscaler",
infra: newTestInfra(),
deploy: &egv1a1.KubernetesDeploymentSpec{
Replicas: new(int32(2)),
ReplicasManagedByExternalAutoscaler: new(true),
Strategy: egv1a1.DefaultKubernetesDeploymentStrategy(),
},
},
{
caseName: "gateway-namespace-mode",
infra: newTestInfraWithNamespacedName(types.NamespacedName{Namespace: "ns1", Name: "gateway-1"}),
Expand Down
Loading
Loading