diff --git a/cmd/kubeadm/app/cmd/phases/upgrade/node/kubeletconfig.go b/cmd/kubeadm/app/cmd/phases/upgrade/node/kubeletconfig.go index 5ec99c4e260..f853a468735 100644 --- a/cmd/kubeadm/app/cmd/phases/upgrade/node/kubeletconfig.go +++ b/cmd/kubeadm/app/cmd/phases/upgrade/node/kubeletconfig.go @@ -20,15 +20,21 @@ import ( "fmt" "os" "path/filepath" + "strings" "github.com/pkg/errors" + "k8s.io/klog/v2" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" + patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode" "k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade" + configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun" ) @@ -86,6 +92,31 @@ func runKubeletConfigPhase() func(c workflow.RunData) error { return nil } + // Handle a dupliate prefix URL scheme in the Node CRI socket. + // Older versions of kubeadm(v1.24.0~2) upgrade may add one or two extra prefix `unix://` + // TODO: this fix can be removed in 1.26 once all user node sockets have a correct URL scheme: + // https://github.com/kubernetes/kubeadm/issues/2426 + var dupURLScheme bool + nro := &kubeadmapi.NodeRegistrationOptions{} + if !dryRun { + if err := configutil.GetNodeRegistration(data.KubeConfigPath(), data.Client(), nro); err != nil { + return errors.Wrap(err, "could not retrieve the node registration options for this node") + } + dupURLScheme = strings.HasPrefix(nro.CRISocket, kubeadmapiv1.DefaultContainerRuntimeURLScheme+"://"+kubeadmapiv1.DefaultContainerRuntimeURLScheme+"://") + } + if dupURLScheme { + if !dryRun { + newSocket := strings.ReplaceAll(nro.CRISocket, kubeadmapiv1.DefaultContainerRuntimeURLScheme+"://", "") + newSocket = kubeadmapiv1.DefaultContainerRuntimeURLScheme + "://" + newSocket + klog.V(2).Infof("ensuring that Node %q has a CRI socket annotation with correct URL scheme %q", nro.Name, newSocket) + if err := patchnodephase.AnnotateCRISocket(data.Client(), nro.Name, newSocket); err != nil { + return errors.Wrapf(err, "error updating the CRI socket for Node %q", nro.Name) + } + } else { + fmt.Println("[upgrade] Would update the node CRI socket path to remove dup URL scheme prefix") + } + } + fmt.Println("[upgrade] The configuration for this node was successfully updated!") fmt.Println("[upgrade] Now you should go ahead and upgrade the kubelet package using your package manager.") return nil diff --git a/cmd/kubeadm/app/cmd/upgrade/common.go b/cmd/kubeadm/app/cmd/upgrade/common.go index 8e02e0d4c6c..fbe31298aa4 100644 --- a/cmd/kubeadm/app/cmd/upgrade/common.go +++ b/cmd/kubeadm/app/cmd/upgrade/common.go @@ -35,11 +35,13 @@ import ( "k8s.io/klog/v2" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" "k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs" "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/features" + patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode" "k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade" "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig" "k8s.io/kubernetes/cmd/kubeadm/app/preflight" @@ -223,6 +225,24 @@ func enforceRequirements(flags *applyPlanFlags, args []string, dryRun bool, upgr printConfiguration(&cfg.ClusterConfiguration, os.Stdout, printer) } + // Handle a dupliate prefix URL scheme in the Node CRI socket. + // Older versions of kubeadm(v1.24.0~2) upgrade may add one or two extra prefix `unix://` + // TODO: this fix can be removed in 1.26 once all user node sockets have a correct URL scheme: + // https://github.com/kubernetes/kubeadm/issues/2426 + dupURLScheme := strings.HasPrefix(cfg.NodeRegistration.CRISocket, kubeadmapiv1.DefaultContainerRuntimeURLScheme+"://"+kubeadmapiv1.DefaultContainerRuntimeURLScheme+"://") + if dupURLScheme { + socket := strings.ReplaceAll(cfg.NodeRegistration.CRISocket, kubeadmapiv1.DefaultContainerRuntimeURLScheme+"://", "") + cfg.NodeRegistration.CRISocket = kubeadmapiv1.DefaultContainerRuntimeURLScheme + "://" + socket + hostname, err := os.Hostname() + if err != nil { + return nil, nil, nil, errors.Wrapf(err, "failed to get hostname") + } + klog.V(2).Infof("ensuring that Node %q has a CRI socket annotation with correct URL scheme %q", hostname, cfg.NodeRegistration.CRISocket) + if err := patchnodephase.AnnotateCRISocket(client, hostname, cfg.NodeRegistration.CRISocket); err != nil { + return nil, nil, nil, errors.Wrapf(err, "error updating the CRI socket for Node %q", cfg.NodeRegistration.CRISocket) + } + } + // Use a real version getter interface that queries the API server, the kubeadm client and the Kubernetes CI system for latest versions return client, upgrade.NewOfflineVersionGetter(upgrade.NewKubeVersionGetter(client), newK8sVersion), cfg, nil }