{"record":{"id":"bbc69c343c460e32","repo":"kubernetes/kubernetes","slug":"external-etcd-detected-won-t-try-to-change-any-et","errorCode":null,"errorMessage":"external etcd detected, won't try to change any etcd state","messagePattern":"external etcd detected, won't try to change any etcd state","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"info","filePath":"cmd/kubeadm/app/phases/upgrade/staticpods.go","lineNumber":287,"sourceCode":"\t\t\treturn rollbackOldManifests(recoverManifests, err, pathMgr, recoverEtcd)\n\t\t}\n\t}\n\n\t// Wait for the static pod component to come up and register itself as a mirror pod\n\tif err := waiter.WaitForPodsWithLabel(\"component=\" + component); err != nil {\n\t\treturn rollbackOldManifests(recoverManifests, err, pathMgr, recoverEtcd)\n\t}\n\n\tfmt.Printf(\"[upgrade/staticpods] Component %q upgraded successfully!\\n\", component)\n\n\treturn nil\n}\n\n// performEtcdStaticPodUpgrade performs upgrade of etcd, it returns bool which indicates fatal error or not and the actual error.\nfunc performEtcdStaticPodUpgrade(certsRenewMgr *renewal.Manager, client clientset.Interface, waiter apiclient.Waiter, pathMgr StaticPodPathManager, cfg *kubeadmapi.InitConfiguration, recoverManifests map[string]string, oldEtcdClient, newEtcdClient etcdutil.ClusterInterrogator) (bool, error) {\n\t// Add etcd static pod spec only if external etcd is not configured\n\tif cfg.Etcd.External != nil {\n\t\treturn false, errors.New(\"external etcd detected, won't try to change any etcd state\")\n\t}\n\n\t// Checking health state of etcd before proceeding with the upgrade\n\terr := oldEtcdClient.CheckClusterHealth()\n\tif err != nil {\n\t\treturn true, errors.Wrap(err, \"etcd cluster is not healthy\")\n\t}\n\n\t// Backing up etcd data store\n\tbackupEtcdDir := pathMgr.BackupEtcdDir()\n\trunningEtcdDir := cfg.Etcd.Local.DataDir\n\toutput, err := filesutil.CopyDir(runningEtcdDir, backupEtcdDir)\n\tif err != nil {\n\t\treturn true, errors.Wrapf(err, \"failed to back up etcd data, output: %q\", output)\n\t}\n\n\t// Get the desired etcd version. That's either the one specified by the user in cfg.Etcd.Local.ImageTag\n\t// or the kubeadm preferred one for the desired Kubernetes version","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/kubernetes/kubernetes/blob/b882c60b4023bdf09264c2d5d30a2cadebc240fb/cmd/kubeadm/app/phases/upgrade/staticpods.go#L269-L305","documentation":"Returned by performEtcdStaticPodUpgrade when cfg.Etcd.External != nil. It is a deliberate, non-fatal abort: kubeadm detects an externally-managed etcd and refuses to touch etcd state during a control-plane static-pod upgrade. The function returns fatal=false, signalling the caller that etcd upgrade was intentionally skipped rather than a hard failure.","triggerScenarios":"Running 'kubeadm upgrade apply'/'upgrade node' on a cluster whose ClusterConfiguration.Etcd.External is populated (etcd endpoints/caCert/keyFile set), then kubeadm reaching the etcd static-pod upgrade phase via performEtcdStaticPodUpgrade.","commonSituations":"Clusters provisioned with external/managed etcd (e.g. etcd running on separate hosts or a managed service). This is expected and benign; the operator must upgrade external etcd themselves.","solutions":["No action required for kubeadm: this is informational. Upgrade the external etcd cluster separately.","If you expected stacked (local) etcd, verify your config does not set etcd.external; switch to local etcd config to let kubeadm manage etcd.","Confirm the caller treats fatal=false as non-terminal (the upgrade of other static pods continues)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if cfg.Etcd.External != nil {\n    // external etcd: skip etcd upgrade, log and continue\n    klog.Info(\"external etcd configured; skipping etcd static-pod upgrade\")\n    return nil\n}\nreturn performEtcdStaticPodUpgrade(...)","typeGuard":null,"tryCatchPattern":"fatal, err := performEtcdStaticPodUpgrade(...)\nif err != nil && !fatal && strings.Contains(err.Error(), \"external etcd detected\") {\n    klog.Infof(\"skipping etcd upgrade: %v\", err)\n    err = nil\n}","preventionTips":["Detect external etcd up front (cfg.Etcd.External != nil) and branch before calling etcd upgrade code.","Treat fatal=false returns as intentional skips, not failures.","Upgrade external etcd out-of-band; document the split responsibility."],"tags":["kubeadm","upgrade","etcd","external-etcd"],"analyzedSha":"b882c60b4023bdf09264c2d5d30a2cadebc240fb","analyzedAt":"2026-08-07T04:07:48.144Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}