Skip to content

[FEATURE] Make the agent Deployment rollout strategy configurable in SharedDeploymentSpec #2253

Description

@paurosello

Problem

The agent Deployment's update strategy is hardcoded and cannot be overridden from the Agent CR. In go/core/internal/controller/translator/agent/manifest_builder.go:599-604 every agent Deployment is rendered with:

Strategy: appsv1.DeploymentStrategy{
    Type: appsv1.RollingUpdateDeploymentStrategyType,
    RollingUpdate: &appsv1.RollingUpdateDeployment{
        MaxUnavailable: &intstr.IntOrString{Type: intstr.Int, IntVal: 0},
        MaxSurge:       &intstr.IntOrString{Type: intstr.Int, IntVal: 1},
    },
},

SharedDeploymentSpec (go/api/v1alpha2/agent_types.go:433) already exposes many pod/deployment knobs — Replicas, Volumes, VolumeMounts, Affinity, Tolerations, NodeSelector, SecurityContext, PodSecurityContext, ExtraContainers — but there is no field for the rollout strategy, so operators cannot change it.

Why this matters

RollingUpdate{maxUnavailable: 0, maxSurge: 1} is a reasonable default for a stateless agent, but it wedges any agent that mounts a ReadWriteOnce volume. On upgrade the surge pod is created before the old pod terminates; if it schedules to a different node than the one holding the RWO volume, the new pod stays Pending on Multi-Attach/FailedAttachVolume and the rollout stalls indefinitely.

Any operator attaching persistent, node-bound storage to an agent (via the existing volumes/volumeMounts fields) hits this. The generic k8s answer — strategy.type: Recreate, which terminates the old pod before starting the new one so the volume detaches cleanly — is exactly what cannot be expressed today.

RWO storage is the common default on many clusters (RWX requires EFS/NFS/CephFS or similar), so "just use RWX" is not always available, and maxUnavailable: 0 is precisely the setting that makes RWO unusable across a rollout.

Proposal

Add an optional rollout-strategy field to SharedDeploymentSpec and use it in manifest_builder.go instead of the hardcoded literal, falling back to the current RollingUpdate{0,1} when unset (fully backward compatible). For example:

// Strategy overrides the agent Deployment update strategy.
// Defaults to RollingUpdate{maxUnavailable: 0, maxSurge: 1} when unset.
// +optional
DeploymentStrategy *appsv1.DeploymentStrategy `json:"deploymentStrategy,omitempty"`

An operator with an RWO-backed agent would then set:

spec:
  declarative:
    deployment:
      deploymentStrategy:
        type: Recreate

Exposing the whole DeploymentStrategy keeps parity with core k8s and covers the Recreate case as well as tuned RollingUpdate values; a narrower strategyType enum would also solve the RWO case if a smaller surface is preferred.

Prior art

This is the same "extend SharedDeploymentSpec with one first-class, backward-compatible field" shape that was already accepted in #1646 (Add ExtraContainers to SharedDeploymentSpec).

Happy to open the PR for this if the direction and the field shape (full DeploymentStrategy vs. a strategyType enum) look good.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status
Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions