kubeadm: fix dry-run for kubelet-wait-bootstrap phase

This commit is contained in:
Christian Schlotter 2025-02-03 14:46:27 +01:00
parent 20fbdeac96
commit 6c093b1699
No known key found for this signature in database
GPG Key ID: 0E487122453EB0AC
2 changed files with 48 additions and 35 deletions

View File

@ -609,7 +609,9 @@ func (j *joinData) Client() (clientset.Interface, error) {
AppendReactor(dryRun.GetKubeadmConfigReactor()).
AppendReactor(dryRun.GetKubeadmCertsReactor()).
AppendReactor(dryRun.GetKubeProxyConfigReactor()).
AppendReactor(dryRun.GetKubeletConfigReactor())
AppendReactor(dryRun.GetKubeletConfigReactor()).
AppendReactor(dryRun.GetNodeReactor()).
AppendReactor(dryRun.PatchNodeReactor())
j.client = dryRun.FakeClient()
return j.client, nil

View File

@ -293,44 +293,55 @@ func runKubeletWaitBootstrapPhase(c workflow.RunData) (returnErr error) {
return err
}
bootstrapKubeConfigFile := filepath.Join(data.KubeConfigDir(), kubeadmconstants.KubeletBootstrapKubeConfigFileName)
// Deletes the bootstrapKubeConfigFile, so the credential used for TLS bootstrap is removed from disk
defer func() {
_ = os.Remove(bootstrapKubeConfigFile)
}()
var client clientset.Interface
// Apply patches to the in-memory kubelet configuration so that any configuration changes like kubelet healthz
// address and port options are respected during the wait below. WriteConfigToDisk already applied patches to
// the kubelet.yaml written to disk. This should be done after WriteConfigToDisk because both use the same config
// in memory and we don't want patches to be applied two times to the config that is written to disk.
if err := kubeletphase.ApplyPatchesToConfig(&initCfg.ClusterConfiguration, data.PatchesDir()); err != nil {
return errors.Wrap(err, "could not apply patches to the in-memory kubelet configuration")
}
if data.DryRun() {
fmt.Println("[kubelet-wait] Would wait for the kubelet to be bootstrapped")
// Now the kubelet will perform the TLS Bootstrap, transforming /etc/kubernetes/bootstrap-kubelet.conf to /etc/kubernetes/kubelet.conf
// Wait for the kubelet to create the /etc/kubernetes/kubelet.conf kubeconfig file. If this process
// times out, display a somewhat user-friendly message.
waiter := apiclient.NewKubeWaiter(nil, 0, os.Stdout)
waiter.SetTimeout(cfg.Timeouts.KubeletHealthCheck.Duration)
kubeletConfig := initCfg.ClusterConfiguration.ComponentConfigs[componentconfigs.KubeletGroup].Get()
kubeletConfigTyped, ok := kubeletConfig.(*kubeletconfig.KubeletConfiguration)
if !ok {
return errors.New("could not convert the KubeletConfiguration to a typed object")
}
if err := waiter.WaitForKubelet(kubeletConfigTyped.HealthzBindAddress, *kubeletConfigTyped.HealthzPort); err != nil {
fmt.Printf(kubeadmJoinFailMsg, err)
return err
}
// Use the dry-run client.
if client, err = data.Client(); err != nil {
return errors.Wrap(err, "could not get client for dry-run")
}
} else {
bootstrapKubeConfigFile := filepath.Join(data.KubeConfigDir(), kubeadmconstants.KubeletBootstrapKubeConfigFileName)
// Deletes the bootstrapKubeConfigFile, so the credential used for TLS bootstrap is removed from disk
defer func() {
_ = os.Remove(bootstrapKubeConfigFile)
}()
if err := waitForTLSBootstrappedClient(cfg.Timeouts.TLSBootstrap.Duration); err != nil {
fmt.Printf(kubeadmJoinFailMsg, err)
return err
}
// Apply patches to the in-memory kubelet configuration so that any configuration changes like kubelet healthz
// address and port options are respected during the wait below. WriteConfigToDisk already applied patches to
// the kubelet.yaml written to disk. This should be done after WriteConfigToDisk because both use the same config
// in memory and we don't want patches to be applied two times to the config that is written to disk.
if err := kubeletphase.ApplyPatchesToConfig(&initCfg.ClusterConfiguration, data.PatchesDir()); err != nil {
return errors.Wrap(err, "could not apply patches to the in-memory kubelet configuration")
}
// When we know the /etc/kubernetes/kubelet.conf file is available, get the client
client, err := kubeconfigutil.ClientSetFromFile(kubeadmconstants.GetKubeletKubeConfigPath())
if err != nil {
return err
// Now the kubelet will perform the TLS Bootstrap, transforming /etc/kubernetes/bootstrap-kubelet.conf to /etc/kubernetes/kubelet.conf
// Wait for the kubelet to create the /etc/kubernetes/kubelet.conf kubeconfig file. If this process
// times out, display a somewhat user-friendly message.
waiter := apiclient.NewKubeWaiter(nil, 0, os.Stdout)
waiter.SetTimeout(cfg.Timeouts.KubeletHealthCheck.Duration)
kubeletConfig := initCfg.ClusterConfiguration.ComponentConfigs[componentconfigs.KubeletGroup].Get()
kubeletConfigTyped, ok := kubeletConfig.(*kubeletconfig.KubeletConfiguration)
if !ok {
return errors.New("could not convert the KubeletConfiguration to a typed object")
}
if err := waiter.WaitForKubelet(kubeletConfigTyped.HealthzBindAddress, *kubeletConfigTyped.HealthzPort); err != nil {
fmt.Printf(kubeadmJoinFailMsg, err)
return err
}
if err := waitForTLSBootstrappedClient(cfg.Timeouts.TLSBootstrap.Duration); err != nil {
fmt.Printf(kubeadmJoinFailMsg, err)
return err
}
// When we know the /etc/kubernetes/kubelet.conf file is available, get the client
client, err = kubeconfigutil.ClientSetFromFile(kubeadmconstants.GetKubeletKubeConfigPath())
if err != nil {
return err
}
}
if !features.Enabled(initCfg.ClusterConfiguration.FeatureGates, features.NodeLocalCRISocket) {