Skip to content

Commit 33ccc51

Browse files
authored
Merge pull request kubernetes#125780 from chrischdi/pr-kubeadm-control-plane-kubelet-local-init
kubeadm: consider feature gate ControlPlaneKubeletLocalMode on init and upgrade
2 parents de00a3c + 8871513 commit 33ccc51

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed

cmd/kubeadm/app/cmd/phases/init/kubeconfig.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
2727
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
2828
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
29+
"k8s.io/kubernetes/cmd/kubeadm/app/features"
2930
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
3031
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
3132
)
@@ -157,7 +158,16 @@ func runKubeConfigFile(kubeConfigFileName string) func(workflow.RunData) error {
157158
cfg.CertificatesDir = data.CertificateWriteDir()
158159
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
159160

161+
initConfiguration := data.Cfg().DeepCopy()
162+
163+
if features.Enabled(cfg.FeatureGates, features.ControlPlaneKubeletLocalMode) {
164+
if kubeConfigFileName == kubeadmconstants.KubeletKubeConfigFileName {
165+
// Unset the ControlPlaneEndpoint so the creation falls back to the LocalAPIEndpoint for the kubelet's kubeconfig.
166+
initConfiguration.ControlPlaneEndpoint = ""
167+
}
168+
}
169+
160170
// creates the KubeConfig file (or use existing)
161-
return kubeconfigphase.CreateKubeConfigFile(kubeConfigFileName, data.KubeConfigDir(), data.Cfg())
171+
return kubeconfigphase.CreateKubeConfigFile(kubeConfigFileName, data.KubeConfigDir(), initConfiguration)
162172
}
163173
}

cmd/kubeadm/app/cmd/phases/upgrade/node/controlplane.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
2626
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
27+
"k8s.io/kubernetes/cmd/kubeadm/app/features"
2728
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
2829
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
2930
)
@@ -82,6 +83,12 @@ func runControlPlane() func(c workflow.RunData) error {
8283
return errors.Wrap(err, "failed to perform addons upgrade")
8384
}
8485

86+
if features.Enabled(cfg.FeatureGates, features.ControlPlaneKubeletLocalMode) {
87+
if err := upgrade.UpdateKubeletLocalMode(cfg, dryRun); err != nil {
88+
return errors.Wrap(err, "failed to update kubelet local mode")
89+
}
90+
}
91+
8592
fmt.Println("[upgrade] The control plane instance for this node was successfully updated!")
8693

8794
return nil

cmd/kubeadm/app/phases/upgrade/postupgrade.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ import (
3131
errorsutil "k8s.io/apimachinery/pkg/util/errors"
3232
"k8s.io/apimachinery/pkg/util/sets"
3333
clientset "k8s.io/client-go/kubernetes"
34+
"k8s.io/client-go/tools/clientcmd"
3435
"k8s.io/klog/v2"
3536

3637
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
3738
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
39+
"k8s.io/kubernetes/cmd/kubeadm/app/features"
3840
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
3941
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
4042
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
@@ -109,6 +111,12 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.InitCon
109111
errs = append(errs, err)
110112
}
111113

114+
if features.Enabled(cfg.FeatureGates, features.ControlPlaneKubeletLocalMode) {
115+
if err := UpdateKubeletLocalMode(cfg, dryRun); err != nil {
116+
return errors.Wrap(err, "failed to update kubelet local mode")
117+
}
118+
}
119+
112120
return errorsutil.NewAggregate(errs)
113121
}
114122

@@ -281,3 +289,61 @@ func GetKubeletDir(dryRun bool) (string, error) {
281289
}
282290
return kubeadmconstants.KubeletRunDirectory, nil
283291
}
292+
293+
// UpdateKubeletLocalMode changes the Server URL in the kubelets kubeconfig to the local API endpoint if it is currently
294+
// set to the ControlPlaneEndpoint.
295+
// TODO: remove this function once kubeletKubeConfigFilePath goes GA and is hardcoded to enabled by default:
296+
// https://github.com/kubernetes/kubeadm/issues/2271
297+
func UpdateKubeletLocalMode(cfg *kubeadmapi.InitConfiguration, dryRun bool) error {
298+
kubeletKubeConfigFilePath := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName)
299+
300+
if _, err := os.Stat(kubeletKubeConfigFilePath); err != nil {
301+
if os.IsNotExist(err) {
302+
klog.V(2).Infof("Could not mutate the Server URL in %s: %v", kubeletKubeConfigFilePath, err)
303+
return nil
304+
}
305+
return err
306+
}
307+
308+
config, err := clientcmd.LoadFromFile(kubeletKubeConfigFilePath)
309+
if err != nil {
310+
return err
311+
}
312+
313+
configContext, ok := config.Contexts[config.CurrentContext]
314+
if !ok {
315+
return errors.Errorf("cannot find cluster for active context in kubeconfig %q", kubeletKubeConfigFilePath)
316+
}
317+
318+
localAPIEndpoint, err := kubeadmutil.GetLocalAPIEndpoint(&cfg.LocalAPIEndpoint)
319+
if err != nil {
320+
return err
321+
}
322+
323+
controlPlaneAPIEndpoint, err := kubeadmutil.GetControlPlaneEndpoint(cfg.ControlPlaneEndpoint, &cfg.LocalAPIEndpoint)
324+
if err != nil {
325+
return err
326+
}
327+
328+
// Skip changing kubeconfig file if Server does not match the ControlPlaneEndoint.
329+
if config.Clusters[configContext.Cluster].Server != controlPlaneAPIEndpoint || controlPlaneAPIEndpoint == localAPIEndpoint {
330+
klog.V(2).Infof("Skipping update of the Server URL in %s, because it's already not equal to %q or already matches the localAPIEndpoint", kubeletKubeConfigFilePath, cfg.ControlPlaneEndpoint)
331+
return nil
332+
}
333+
334+
if dryRun {
335+
fmt.Printf("[dryrun] Would change the Server URL from %q to %q in %s and try to restart kubelet\n", config.Clusters[configContext.Cluster].Server, localAPIEndpoint, kubeletKubeConfigFilePath)
336+
return nil
337+
}
338+
339+
klog.V(1).Infof("Changing the Server URL from %q to %q in %s", config.Clusters[configContext.Cluster].Server, localAPIEndpoint, kubeletKubeConfigFilePath)
340+
config.Clusters[configContext.Cluster].Server = localAPIEndpoint
341+
342+
if err := clientcmd.WriteToFile(*config, kubeletKubeConfigFilePath); err != nil {
343+
return err
344+
}
345+
346+
kubeletphase.TryRestartKubelet()
347+
348+
return nil
349+
}

0 commit comments

Comments
 (0)