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
6 changes: 6 additions & 0 deletions .chloggen/bugfix-autoscaler-replicas-respect-spec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
change_type: bug_fix
component: collector
note: "Fix autoscaler not scaling above minReplicas; replicas now respect the scale subresource and never fall below autoscaler.minReplicas."
issues: [4400]
subtext: |
Also rename helper `GetInitialReplicas` to `GetDesiredReplicas` to reflect reconcile-time behavior.
2 changes: 1 addition & 1 deletion internal/manifests/collector/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func Deployment(params manifests.Params) (*appsv1.Deployment, error) {
Annotations: annotations,
},
Spec: appsv1.DeploymentSpec{
Replicas: manifestutils.GetInitialReplicas(params.OtelCol),
Replicas: manifestutils.GetDesiredReplicas(params.OtelCol),
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe if GetDesiredReplicas will produce the same effect as described on #2585

Copy link
Contributor

Choose a reason for hiding this comment

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

One idea would be adding a condition about the HPA here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you so much for your comment! I tried reproducing the behavior described in the original issue, but from what I can see, even when we change minReplicas, the Operator doesn’t seem to create a new ReplicaSet, and the Pods aren’t restarted. Could you let me know if I’m missing something here?

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
  name: simplest
spec:
  autoscaler:
    minReplicas: 2
    maxReplicas: 4
  config:
    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    processors:
      memory_limiter:
        check_interval: 1s
        limit_percentage: 75
        spike_limit_percentage: 15
      batch:
        send_batch_size: 10000
        timeout: 10s

    exporters:
      debug: {}

    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [memory_limiter, batch]
          exporters: [debug]

NAME                                 READY   STATUS    RESTARTS   AGE
simplest-collector-c9fb74dcd-njqd8   1/1     Running   0          28s
simplest-collector-c9fb74dcd-plvd8   1/1     Running   0          28s

Update the minReplicas from 2 to 3.

spec:
  autoscaler:
    minReplicas: 3
    maxReplicas: 4

Add one Pod without restarting the others.

NAME                                 READY   STATUS    RESTARTS   AGE
simplest-collector-c9fb74dcd-6rt44   1/1     Running   0          6s
simplest-collector-c9fb74dcd-njqd8   1/1     Running   0          52s
simplest-collector-c9fb74dcd-plvd8   1/1     Running   0          52s

Selector: &metav1.LabelSelector{
MatchLabels: manifestutils.SelectorLabels(params.OtelCol.ObjectMeta, ComponentOpenTelemetryCollector),
},
Expand Down
19 changes: 17 additions & 2 deletions internal/manifests/collector/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ func TestDeploymentDNSConfig(t *testing.T) {
assert.Equal(t, d.Spec.Template.Spec.DNSConfig.Nameservers, []string{"8.8.8.8"})
}

func TestGetInitialReplicas(t *testing.T) {
func TestGetDesiredReplicas(t *testing.T) {
tests := []struct {
name string
otelCol v1beta1.OpenTelemetryCollector
Expand Down Expand Up @@ -790,11 +790,26 @@ func TestGetInitialReplicas(t *testing.T) {
},
expected: int32Ptr(6),
},
{
name: "autoscaler-with-minReplicas-spec-replicas-greater",
otelCol: v1beta1.OpenTelemetryCollector{
Spec: v1beta1.OpenTelemetryCollectorSpec{
OpenTelemetryCommonFields: v1beta1.OpenTelemetryCommonFields{
Replicas: int32Ptr(5),
},
Autoscaler: &v1beta1.AutoscalerSpec{
MinReplicas: int32Ptr(3),
MaxReplicas: int32Ptr(10),
},
},
},
expected: int32Ptr(5),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := manifestutils.GetInitialReplicas(tt.otelCol)
result := manifestutils.GetDesiredReplicas(tt.otelCol)
if tt.expected == nil {
assert.Nil(t, result)
} else {
Expand Down
2 changes: 1 addition & 1 deletion internal/manifests/collector/statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func StatefulSet(params manifests.Params) (*appsv1.StatefulSet, error) {
TerminationGracePeriodSeconds: params.OtelCol.Spec.TerminationGracePeriodSeconds,
},
},
Replicas: manifestutils.GetInitialReplicas(params.OtelCol),
Replicas: manifestutils.GetDesiredReplicas(params.OtelCol),
PodManagementPolicy: "Parallel",
VolumeClaimTemplates: VolumeClaimTemplates(params.OtelCol),
PersistentVolumeClaimRetentionPolicy: params.OtelCol.Spec.PersistentVolumeClaimRetentionPolicy,
Expand Down
8 changes: 7 additions & 1 deletion internal/manifests/manifestutils/replicas.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ import (
"github.com/open-telemetry/opentelemetry-operator/apis/v1beta1"
)

func GetInitialReplicas(otelCol v1beta1.OpenTelemetryCollector) *int32 {
func GetDesiredReplicas(otelCol v1beta1.OpenTelemetryCollector) *int32 {
// If autoscaling is configured, ensure we never set replicas below MinReplicas,
// but still respect Spec.Replicas which may be updated via the scale subresource (e.g., by HPA).
if otelCol.Spec.Autoscaler != nil && otelCol.Spec.Autoscaler.MinReplicas != nil {
if otelCol.Spec.Replicas != nil {
replicas := max(*otelCol.Spec.Autoscaler.MinReplicas, *otelCol.Spec.Replicas)
return &replicas
}
return otelCol.Spec.Autoscaler.MinReplicas
}
return otelCol.Spec.Replicas
Expand Down
Loading