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.
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-604every agent Deployment is rendered with: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 aReadWriteOncevolume. 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 staysPendingonMulti-Attach/FailedAttachVolumeand the rollout stalls indefinitely.Any operator attaching persistent, node-bound storage to an agent (via the existing
volumes/volumeMountsfields) 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: 0is precisely the setting that makes RWO unusable across a rollout.Proposal
Add an optional rollout-strategy field to
SharedDeploymentSpecand use it inmanifest_builder.goinstead of the hardcoded literal, falling back to the currentRollingUpdate{0,1}when unset (fully backward compatible). For example:An operator with an RWO-backed agent would then set:
Exposing the whole
DeploymentStrategykeeps parity with core k8s and covers theRecreatecase as well as tunedRollingUpdatevalues; a narrowerstrategyTypeenum would also solve the RWO case if a smaller surface is preferred.Prior art
This is the same "extend
SharedDeploymentSpecwith one first-class, backward-compatible field" shape that was already accepted in #1646 (AddExtraContainerstoSharedDeploymentSpec).Happy to open the PR for this if the direction and the field shape (full
DeploymentStrategyvs. astrategyTypeenum) look good.