Merge pull request #124688 from neolit123/1.31-always-rotate-etcd-certs-on-upgrade

kubeadm: ensure that etcd certs are rotated on apiserver upgrade
This commit is contained in:
Kubernetes Prow Robot 2024-05-29 05:10:30 -07:00 committed by GitHub
commit 529896474f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -189,10 +189,18 @@ func (spm *KubeStaticPodPathManager) CleanupDirs() error {
func upgradeComponent(component string, certsRenewMgr *renewal.Manager, waiter apiclient.Waiter, pathMgr StaticPodPathManager, cfg *kubeadmapi.InitConfiguration, beforePodHash string, recoverManifests map[string]string) error {
// Special treatment is required for etcd case, when rollbackOldManifests should roll back etcd
// manifests only for the case when component is Etcd
// manifests only for the case when component is Etcd. Also check if the kube-apiserver needs an upgrade
// by comparing its manifests and later decide if etcd certs can be renewed and etcd can be restarted.
recoverEtcd := false
apiServerUpgrade := false
if component == constants.Etcd {
recoverEtcd = true
equal, _, err := staticpod.ManifestFilesAreEqual(pathMgr.RealManifestPath(constants.KubeAPIServer),
pathMgr.TempManifestPath(constants.KubeAPIServer))
if err != nil {
return err
}
apiServerUpgrade = !equal
}
fmt.Printf("[upgrade/staticpods] Preparing for %q upgrade\n", component)
@ -214,8 +222,12 @@ func upgradeComponent(component string, certsRenewMgr *renewal.Manager, waiter a
return err
}
if equal {
fmt.Printf("[upgrade/staticpods] Current and new manifests of %s are equal, skipping upgrade\n", component)
return nil
if !apiServerUpgrade {
fmt.Printf("[upgrade/staticpods] Current and new manifests of %s are equal, skipping upgrade\n", component)
return nil
}
klog.V(4).Infof("[upgrade/staticpods] Current and new manifests of %s are equal, but %s will be upgraded\n",
component, constants.KubeAPIServer)
} else {
klog.V(4).Infof("Pod manifest files diff:\n%s\n", diff)
}
@ -228,6 +240,15 @@ func upgradeComponent(component string, certsRenewMgr *renewal.Manager, waiter a
}
}
// This can only happen if the component is etcd, cert renewal is enabled and kube-apiserver needs an upgrade
if equal && certsRenewMgr != nil {
fmt.Printf("[upgrade/staticpods] Restarting the %s static pod and backing up its manifest to %q\n",
component, backupManifestPath)
} else {
fmt.Printf("[upgrade/staticpods] Moving new manifest to %q and backing up old manifest to %q\n",
currentManifestPath, backupManifestPath)
}
// Move the old manifest into the old-manifests directory
if err := pathMgr.MoveFile(currentManifestPath, backupManifestPath); err != nil {
return rollbackOldManifests(recoverManifests, err, pathMgr, recoverEtcd)
@ -238,8 +259,6 @@ func upgradeComponent(component string, certsRenewMgr *renewal.Manager, waiter a
return rollbackOldManifests(recoverManifests, err, pathMgr, recoverEtcd)
}
fmt.Printf("[upgrade/staticpods] Moved new manifest to %q and backed up old manifest to %q\n", currentManifestPath, backupManifestPath)
fmt.Println("[upgrade/staticpods] Waiting for the kubelet to restart the component")
fmt.Printf("[upgrade/staticpods] This can take up to %v\n", kubeadmapi.GetActiveTimeouts().UpgradeManifests.Duration)
@ -247,8 +266,10 @@ func upgradeComponent(component string, certsRenewMgr *renewal.Manager, waiter a
// notice the removal of the Static Pod, leading to a false positive below where we check that the API endpoint is healthy
// If we don't do this, there is a case where we remove the Static Pod manifest, kubelet is slow to react, kubeadm checks the
// API endpoint below of the OLD Static Pod component and proceeds quickly enough, which might lead to unexpected results.
if err := waiter.WaitForStaticPodHashChange(cfg.NodeRegistration.Name, component, beforePodHash); err != nil {
return rollbackOldManifests(recoverManifests, err, pathMgr, recoverEtcd)
if !equal {
if err := waiter.WaitForStaticPodHashChange(cfg.NodeRegistration.Name, component, beforePodHash); err != nil {
return rollbackOldManifests(recoverManifests, err, pathMgr, recoverEtcd)
}
}
// Wait for the static pod component to come up and register itself as a mirror pod
@ -453,11 +474,16 @@ func StaticPodControlPlane(client clientset.Interface, waiter apiclient.Waiter,
}
}
// Write the updated static Pod manifests into the temporary directory.
// As part of the design, this must be called before the below performEtcdStaticPodUpgrade() call.
fmt.Printf("[upgrade/staticpods] Writing new Static Pod manifests to %q\n", pathMgr.TempManifestDir())
err = controlplane.CreateInitStaticPodManifestFiles(pathMgr.TempManifestDir(), pathMgr.PatchesDir(), cfg, false /* isDryRun */)
if err != nil {
return errors.Wrap(err, "error creating init static pod manifest files")
}
// etcd upgrade is done prior to other control plane components
if !isExternalEtcd && etcdUpgrade {
// set the TLS upgrade flag for all components
fmt.Printf("[upgrade/etcd] Upgrading to TLS for %s\n", constants.Etcd)
// Perform etcd upgrade using common to all control plane components function
fatal, err := performEtcdStaticPodUpgrade(certsRenewMgr, client, waiter, pathMgr, cfg, recoverManifests, oldEtcdClient, newEtcdClient)
if err != nil {
@ -468,13 +494,7 @@ func StaticPodControlPlane(client clientset.Interface, waiter apiclient.Waiter,
}
}
// Write the updated static Pod manifests into the temporary directory
fmt.Printf("[upgrade/staticpods] Writing new Static Pod manifests to %q\n", pathMgr.TempManifestDir())
err = controlplane.CreateInitStaticPodManifestFiles(pathMgr.TempManifestDir(), pathMgr.PatchesDir(), cfg, false /* isDryRun */)
if err != nil {
return errors.Wrap(err, "error creating init static pod manifest files")
}
// Upgrade the rest of the control plane components
for _, component := range constants.ControlPlaneComponents {
if err = upgradeComponent(component, certsRenewMgr, waiter, pathMgr, cfg, beforePodHashMap[component], recoverManifests); err != nil {
return err