kubernetes/kops · error
AttachDetachReconcileSyncPeriod cannot be set to less than 1
Error message
AttachDetachReconcileSyncPeriod cannot be set to less than 1 second
What it means
BuildOptions in the KubeControllerManager component builder validates the AttachDetachReconcileSyncPeriod configured on the cluster spec. The kube-controller-manager itself refuses sub-second values for this flag, so kOps pre-emptively rejects anything under 1 second with this error to fail fast at cluster-spec validation time instead of at controller-manager startup.
Source
Thrown at pkg/model/components/kubecontrollermanager.go:73
{
klog.V(4).Infof("Kubernetes version %q supports AttachDetachReconcileSyncPeriod; will configure", b.ControlPlaneKubernetesVersion().String())
// If not set ... or set to 0s ... which is stupid
if kcm.AttachDetachReconcileSyncPeriod == nil ||
kcm.AttachDetachReconcileSyncPeriod.Duration.String() == "0s" {
klog.V(8).Infof("AttachDetachReconcileSyncPeriod is not set; will set to default %v", defaultAttachDetachReconcileSyncPeriod)
kcm.AttachDetachReconcileSyncPeriod = &metav1.Duration{Duration: defaultAttachDetachReconcileSyncPeriod}
// If less than 1 min and greater than 1 sec ... you get a warning
} else if kcm.AttachDetachReconcileSyncPeriod.Duration < defaultAttachDetachReconcileSyncPeriod &&
kcm.AttachDetachReconcileSyncPeriod.Duration > time.Second {
klog.Infof("KubeControllerManager AttachDetachReconcileSyncPeriod is set lower than recommended: %s", defaultAttachDetachReconcileSyncPeriod)
// If less than 1sec you get an error. Controller is coded to not allow configuration
// less than one second.
} else if kcm.AttachDetachReconcileSyncPeriod.Duration < time.Second {
return fmt.Errorf("AttachDetachReconcileSyncPeriod cannot be set to less than 1 second")
}
}
kcm.ClusterName = b.ClusterName
kcm.CloudProvider = "external"
if kcm.LogLevel == 0 {
kcm.LogLevel = 2
}
image, err := Image("kube-controller-manager", clusterSpec, b.AssetBuilder)
if err != nil {
return err
}
kcm.Image = image
// Doesn't seem to be any real downside to always doing a leader election
kcm.LeaderElection = &kops.LeaderElectionConfiguration{LeaderElect: new(true)}View on GitHub (pinned to 4c8573c808)
Solutions
- Set attachDetachReconcileSyncPeriod to at least 1s in cluster.spec.kubeControllerManager
- Remove the field entirely to fall back to the kOps default (defaultAttachDetachReconcileSyncPeriod)
- If faster reconciliation is needed, note the controller-manager hard-codes a 1s minimum, so choose 1s and tune other knobs instead
Example fix
// before
spec:
kubeControllerManager:
attachDetachReconcileSyncPeriod: 500ms
// after
spec:
kubeControllerManager:
attachDetachReconcileSyncPeriod: 1s Defensive patterns
Strategy: validation
Validate before calling
d, err := time.ParseDuration(cluster.Spec.KubeControllerManager.AttachDetachReconcileSyncPeriod.Duration.String())
if err != nil {
return fmt.Errorf("invalid attachDetachReconcileSyncPeriod: %w", err)
}
if d < time.Second {
return fmt.Errorf("attachDetachReconcileSyncPeriod must be >= 1s, got %s", d)
} Try / catch
if err := builder.BuildOptions(cluster); err != nil {
if strings.Contains(err.Error(), "AttachDetachReconcileSyncPeriod cannot be set to less than 1 second") {
cluster.Spec.KubeControllerManager.AttachDetachReconcileSyncPeriod = metav1.Duration{Duration: time.Second}
err = builder.BuildOptions(cluster)
}
return err
} Prevention
- Only set attachDetachReconcileSyncPeriod in multiples of seconds
- Omit the field to use the kOps default
- Add a unit test asserting durations >= 1s (see Test_Build_KCM_Builder_Change_Duration)
When it happens
Trigger: Setting cluster.spec.kubeControllerManager.attachDetachReconcileSyncPeriod to a duration below time.Second (e.g. "500ms", "0s") and then calling BuildOptions via the KCM builder, as exercised by Test_Build_KCM_Builder and Test_Build_KCM_Builder_Change_Duration.
Common situations: Operators tuning volume attach/detach reconciliation speed for stateful workloads copy a sub-second value from a blog or upstream flag docs; copying a k8s upstream flag default that is expressed in milliseconds; accidentally writing "0" meaning 'default' when the code interprets it as 0s.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- error populating configuration: %v
- InstanceGroup name is missing
- ClusterName is missing
- unknown load balancer Type: %q
- no networking mode set
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/07494d0f94de9bd0.
Report an issue: GitHub.