mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
use new kubeadm-config in kubeadm join control-plane & kubeadm upgrade/upgrade node
This commit is contained in:
parent
3f70af3685
commit
8af751fe90
@ -48,6 +48,7 @@ import (
|
|||||||
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
|
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
|
||||||
markmasterphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster"
|
markmasterphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster"
|
||||||
patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode"
|
patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode"
|
||||||
|
uploadconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||||
@ -300,21 +301,22 @@ func (j *Join) Run(out io.Writer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the node should host a new control plane instance
|
// If the node should host a new control plane instance
|
||||||
|
var initConfiguration *kubeadmapi.InitConfiguration
|
||||||
if j.cfg.ControlPlane == true {
|
if j.cfg.ControlPlane == true {
|
||||||
// Retrives the kubeadm configuration used during kubeadm init
|
// Retrives the kubeadm configuration used during kubeadm init
|
||||||
glog.V(1).Infoln("[join] retrieving KubeConfig objects")
|
glog.V(1).Infoln("[join] retrieving KubeConfig objects")
|
||||||
clusterConfiguration, err := j.FetchInitClusterConfiguration(tlsBootstrapCfg)
|
initConfiguration, err = j.FetchInitConfiguration(tlsBootstrapCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// injects into the kubeadm configuration used for init the information about the joining node
|
// injects into the kubeadm configuration the information about the joining node
|
||||||
clusterConfiguration.NodeRegistration = j.cfg.NodeRegistration
|
initConfiguration.NodeRegistration = j.cfg.NodeRegistration
|
||||||
clusterConfiguration.APIEndpoint.AdvertiseAddress = j.cfg.APIEndpoint.AdvertiseAddress
|
initConfiguration.APIEndpoint = j.cfg.APIEndpoint
|
||||||
|
|
||||||
// Checks if the cluster configuration supports
|
// Checks if the cluster configuration supports
|
||||||
// joining a new control plane instance and if all the necessary certificates are provided
|
// joining a new control plane instance and if all the necessary certificates are provided
|
||||||
if err = j.CheckIfReadyForAdditionalControlPlane(clusterConfiguration); err != nil {
|
if err = j.CheckIfReadyForAdditionalControlPlane(initConfiguration); err != nil {
|
||||||
// outputs the not ready for hosting a new control plane instance message
|
// outputs the not ready for hosting a new control plane instance message
|
||||||
ctx := map[string]string{
|
ctx := map[string]string{
|
||||||
"Error": err.Error(),
|
"Error": err.Error(),
|
||||||
@ -327,11 +329,11 @@ func (j *Join) Run(out io.Writer) error {
|
|||||||
|
|
||||||
// run kubeadm init preflight checks for checking all the prequisites
|
// run kubeadm init preflight checks for checking all the prequisites
|
||||||
glog.Infoln("[join] running pre-flight checks before initializing the new control plane instance")
|
glog.Infoln("[join] running pre-flight checks before initializing the new control plane instance")
|
||||||
preflight.RunInitMasterChecks(utilsexec.New(), clusterConfiguration, j.ignorePreflightErrors)
|
preflight.RunInitMasterChecks(utilsexec.New(), initConfiguration, j.ignorePreflightErrors)
|
||||||
|
|
||||||
// Prepares the node for hosting a new control plane instance by writing necessary
|
// Prepares the node for hosting a new control plane instance by writing necessary
|
||||||
// KubeConfig files, and static pod manifests
|
// KubeConfig files, and static pod manifests
|
||||||
if err = j.PrepareForHostingControlPlane(clusterConfiguration); err != nil {
|
if err = j.PrepareForHostingControlPlane(initConfiguration); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -348,8 +350,8 @@ func (j *Join) Run(out io.Writer) error {
|
|||||||
|
|
||||||
// if the node is hosting a new control plane instance
|
// if the node is hosting a new control plane instance
|
||||||
if j.cfg.ControlPlane == true {
|
if j.cfg.ControlPlane == true {
|
||||||
// Marks the node with master taint and label.
|
// Completes the control plane setup
|
||||||
if err := j.MarkMaster(); err != nil {
|
if err := j.PostInstallControlPlane(initConfiguration); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,52 +369,48 @@ func (j *Join) Run(out io.Writer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchInitClusterConfiguration reads the cluster configuration from the kubeadm-admin configMap,
|
// FetchInitConfiguration reads the cluster configuration from the kubeadm-admin configMap,
|
||||||
func (j *Join) FetchInitClusterConfiguration(tlsBootstrapCfg *clientcmdapi.Config) (*kubeadmapi.InitConfiguration, error) {
|
func (j *Join) FetchInitConfiguration(tlsBootstrapCfg *clientcmdapi.Config) (*kubeadmapi.InitConfiguration, error) {
|
||||||
// creates a client to access the cluster using the bootstrap token identity
|
// creates a client to access the cluster using the bootstrap token identity
|
||||||
tlsClient, err := kubeconfigutil.ToClientSet(tlsBootstrapCfg)
|
tlsClient, err := kubeconfigutil.ToClientSet(tlsBootstrapCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Unable to access the cluster")
|
return nil, errors.Wrap(err, "Unable to access the cluster")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetches the cluster configuration
|
// Fetches the init configuration
|
||||||
kubeadmConfig, err := configutil.FetchConfigFromFileOrCluster(tlsClient, os.Stdout, "join", "")
|
initConfiguration, err := configutil.FetchConfigFromFileOrCluster(tlsClient, os.Stdout, "join", "", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Unable to fetch the kubeadm-config ConfigMap")
|
return nil, errors.Wrap(err, "Unable to fetch the kubeadm-config ConfigMap")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts public API struct to internal API
|
return initConfiguration, nil
|
||||||
clusterConfiguration := &kubeadmapi.InitConfiguration{}
|
|
||||||
kubeadmscheme.Scheme.Convert(kubeadmConfig, clusterConfiguration, nil)
|
|
||||||
|
|
||||||
return clusterConfiguration, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckIfReadyForAdditionalControlPlane ensures that the cluster is in a state that supports
|
// CheckIfReadyForAdditionalControlPlane ensures that the cluster is in a state that supports
|
||||||
// joining an additional control plane instance and if the node is ready to join
|
// joining an additional control plane instance and if the node is ready to join
|
||||||
func (j *Join) CheckIfReadyForAdditionalControlPlane(clusterConfiguration *kubeadmapi.InitConfiguration) error {
|
func (j *Join) CheckIfReadyForAdditionalControlPlane(initConfiguration *kubeadmapi.InitConfiguration) error {
|
||||||
// blocks if the cluster was created without a stable control plane endpoint
|
// blocks if the cluster was created without a stable control plane endpoint
|
||||||
if clusterConfiguration.ControlPlaneEndpoint == "" {
|
if initConfiguration.ControlPlaneEndpoint == "" {
|
||||||
return fmt.Errorf("unable to add a new control plane instance a cluster that doesn't have a stable controlPlaneEndpoint address")
|
return fmt.Errorf("unable to add a new control plane instance a cluster that doesn't have a stable controlPlaneEndpoint address")
|
||||||
}
|
}
|
||||||
|
|
||||||
// blocks if the cluster was created without an external etcd cluster
|
// blocks if the cluster was created without an external etcd cluster
|
||||||
if clusterConfiguration.Etcd.External == nil {
|
if initConfiguration.Etcd.External == nil {
|
||||||
return fmt.Errorf("unable to add a new control plane instance on a cluster that doesn't use an external etcd")
|
return fmt.Errorf("unable to add a new control plane instance on a cluster that doesn't use an external etcd")
|
||||||
}
|
}
|
||||||
|
|
||||||
// blocks if control plane is self-hosted
|
// blocks if control plane is self-hosted
|
||||||
if features.Enabled(clusterConfiguration.FeatureGates, features.SelfHosting) {
|
if features.Enabled(initConfiguration.FeatureGates, features.SelfHosting) {
|
||||||
return fmt.Errorf("self-hosted clusters are deprecated and won't be supported by `kubeadm join --experimental-control-plane`")
|
return fmt.Errorf("self-hosted clusters are deprecated and won't be supported by `kubeadm join --experimental-control-plane`")
|
||||||
}
|
}
|
||||||
|
|
||||||
// blocks if the certificates for the control plane are stored in secrets (instead of the local pki folder)
|
// blocks if the certificates for the control plane are stored in secrets (instead of the local pki folder)
|
||||||
if features.Enabled(clusterConfiguration.FeatureGates, features.StoreCertsInSecrets) {
|
if features.Enabled(initConfiguration.FeatureGates, features.StoreCertsInSecrets) {
|
||||||
return fmt.Errorf("certificates stored in secrets, as well as self-hosted clusters are deprecated and won't be supported by `kubeadm join --experimental-control-plane`")
|
return fmt.Errorf("certificates stored in secrets, as well as self-hosted clusters are deprecated and won't be supported by `kubeadm join --experimental-control-plane`")
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks if the certificates that must be equal across contolplane instances are provided
|
// checks if the certificates that must be equal across contolplane instances are provided
|
||||||
if ret, err := certsphase.SharedCertificateExists(clusterConfiguration); !ret {
|
if ret, err := certsphase.SharedCertificateExists(initConfiguration); !ret {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,28 +418,28 @@ func (j *Join) CheckIfReadyForAdditionalControlPlane(clusterConfiguration *kubea
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PrepareForHostingControlPlane makes all preparation activities require for a node hosting a new control plane instance
|
// PrepareForHostingControlPlane makes all preparation activities require for a node hosting a new control plane instance
|
||||||
func (j *Join) PrepareForHostingControlPlane(clusterConfiguration *kubeadmapi.InitConfiguration) error {
|
func (j *Join) PrepareForHostingControlPlane(initConfiguration *kubeadmapi.InitConfiguration) error {
|
||||||
|
|
||||||
// Creates the admin kubeconfig file for the admin and for kubeadm itself.
|
// Creates the admin kubeconfig file for the admin and for kubeadm itself.
|
||||||
if err := kubeconfigphase.CreateAdminKubeConfigFile(kubeadmconstants.KubernetesDir, clusterConfiguration); err != nil {
|
if err := kubeconfigphase.CreateAdminKubeConfigFile(kubeadmconstants.KubernetesDir, initConfiguration); err != nil {
|
||||||
return errors.Wrap(err, "error generating the admin kubeconfig file")
|
return errors.Wrap(err, "error generating the admin kubeconfig file")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate missing certificates (if any)
|
// Generate missing certificates (if any)
|
||||||
if err := certsphase.CreatePKIAssets(clusterConfiguration); err != nil {
|
if err := certsphase.CreatePKIAssets(initConfiguration); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate kubeconfig files for controller manager, scheduler and for the admin/kubeadm itself
|
// Generate kubeconfig files for controller manager, scheduler and for the admin/kubeadm itself
|
||||||
// NB. The kubeconfig file for kubelet will be generated by the TLS bootstrap process in
|
// NB. The kubeconfig file for kubelet will be generated by the TLS bootstrap process in
|
||||||
// following steps of the join --experimental-control plane workflow
|
// following steps of the join --experimental-control plane workflow
|
||||||
if err := kubeconfigphase.CreateJoinControlPlaneKubeConfigFiles(kubeadmconstants.KubernetesDir, clusterConfiguration); err != nil {
|
if err := kubeconfigphase.CreateJoinControlPlaneKubeConfigFiles(kubeadmconstants.KubernetesDir, initConfiguration); err != nil {
|
||||||
return errors.Wrap(err, "error generating kubeconfig files")
|
return errors.Wrap(err, "error generating kubeconfig files")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates static pod manifests file for the control plane components to be deployed on this node
|
// Creates static pod manifests file for the control plane components to be deployed on this node
|
||||||
// Static pods will be created and managed by the kubelet as soon as it starts
|
// Static pods will be created and managed by the kubelet as soon as it starts
|
||||||
if err := controlplanephase.CreateInitStaticPodManifestFiles(kubeadmconstants.GetStaticPodDirectory(), clusterConfiguration); err != nil {
|
if err := controlplanephase.CreateInitStaticPodManifestFiles(kubeadmconstants.GetStaticPodDirectory(), initConfiguration); err != nil {
|
||||||
return errors.Wrap(err, "error creating static pod manifest files for the control plane components")
|
return errors.Wrap(err, "error creating static pod manifest files for the control plane components")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,8 +486,10 @@ func (j *Join) BootstrapKubelet(tlsBootstrapCfg *clientcmdapi.Config) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write env file with flags for the kubelet to use. Also register taints
|
// Write env file with flags for the kubelet to use. We do not need to write the --register-with-taints for the master,
|
||||||
if err := kubeletphase.WriteKubeletDynamicEnvFile(&j.cfg.NodeRegistration, j.cfg.FeatureGates, true, kubeadmconstants.KubeletRunDirectory); err != nil {
|
// as we handle that ourselves in the markmaster phase
|
||||||
|
// TODO: Maybe we want to do that some time in the future, in order to remove some logic from the markmaster phase?
|
||||||
|
if err := kubeletphase.WriteKubeletDynamicEnvFile(&j.cfg.NodeRegistration, j.cfg.FeatureGates, false, kubeadmconstants.KubeletRunDirectory); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,8 +527,8 @@ func (j *Join) BootstrapKubelet(tlsBootstrapCfg *clientcmdapi.Config) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkMaster marks the new node as master
|
// PostInstallControlPlane marks the new node as master and update the cluster status with information about current node
|
||||||
func (j *Join) MarkMaster() error {
|
func (j *Join) PostInstallControlPlane(initConfiguration *kubeadmapi.InitConfiguration) error {
|
||||||
kubeConfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.AdminKubeConfigFileName)
|
kubeConfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.AdminKubeConfigFileName)
|
||||||
|
|
||||||
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
|
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
|
||||||
@ -536,8 +536,13 @@ func (j *Join) MarkMaster() error {
|
|||||||
return errors.Wrap(err, "couldn't create kubernetes client")
|
return errors.Wrap(err, "couldn't create kubernetes client")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = markmasterphase.MarkMaster(client, j.cfg.NodeRegistration.Name, j.cfg.NodeRegistration.Taints)
|
glog.V(1).Info("[join] uploading currently used configuration to the cluster")
|
||||||
if err != nil {
|
if err := uploadconfigphase.UploadConfiguration(initConfiguration, client); err != nil {
|
||||||
|
return fmt.Errorf("error uploading configuration: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(1).Info("[join] marking the master with right label")
|
||||||
|
if err = markmasterphase.MarkMaster(client, initConfiguration.NodeRegistration.Name, initConfiguration.NodeRegistration.Taints); err != nil {
|
||||||
return errors.Wrap(err, "error applying master label and taints")
|
return errors.Wrap(err, "error applying master label and taints")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ func enforceRequirements(flags *applyPlanFlags, dryRun bool, newK8sVersion strin
|
|||||||
|
|
||||||
// Fetch the configuration from a file or ConfigMap and validate it
|
// Fetch the configuration from a file or ConfigMap and validate it
|
||||||
fmt.Println("[upgrade/config] Making sure the configuration is correct:")
|
fmt.Println("[upgrade/config] Making sure the configuration is correct:")
|
||||||
cfg, err := configutil.FetchConfigFromFileOrCluster(client, os.Stdout, "upgrade/config", flags.cfgPath)
|
cfg, err := configutil.FetchConfigFromFileOrCluster(client, os.Stdout, "upgrade/config", flags.cfgPath, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if apierrors.IsNotFound(err) {
|
if apierrors.IsNotFound(err) {
|
||||||
fmt.Printf("[upgrade/config] In order to upgrade, a ConfigMap called %q in the %s namespace must exist.\n", constants.InitConfigurationConfigMap, metav1.NamespaceSystem)
|
fmt.Printf("[upgrade/config] In order to upgrade, a ConfigMap called %q in the %s namespace must exist.\n", constants.InitConfigurationConfigMap, metav1.NamespaceSystem)
|
||||||
|
@ -150,10 +150,6 @@ func NewCmdUpgradeControlPlane() *cobra.Command {
|
|||||||
|
|
||||||
options.AddKubeConfigFlag(cmd.Flags(), &flags.kubeConfigPath)
|
options.AddKubeConfigFlag(cmd.Flags(), &flags.kubeConfigPath)
|
||||||
cmd.Flags().BoolVar(&flags.dryRun, "dry-run", flags.dryRun, "Do not change any state, just output the actions that would be performed.")
|
cmd.Flags().BoolVar(&flags.dryRun, "dry-run", flags.dryRun, "Do not change any state, just output the actions that would be performed.")
|
||||||
|
|
||||||
//TODO: following values should retrieved form the kubeadm-config config map; remove as soon as the new config wil be in place
|
|
||||||
cmd.Flags().StringVar(&flags.advertiseAddress, "apiserver-advertise-address", flags.advertiseAddress, "If the node is joining as a master, the IP address the API Server will advertise it's listening on.")
|
|
||||||
cmd.Flags().StringVar(&flags.nodeName, "node-name", flags.nodeName, "Specify the node name.")
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,16 +227,11 @@ func RunUpgradeControlPlane(flags *controlplaneUpgradeFlags) error {
|
|||||||
waiter := apiclient.NewKubeWaiter(client, upgrade.UpgradeManifestTimeout, os.Stdout)
|
waiter := apiclient.NewKubeWaiter(client, upgrade.UpgradeManifestTimeout, os.Stdout)
|
||||||
|
|
||||||
// Fetches the cluster configuration
|
// Fetches the cluster configuration
|
||||||
cfg, err := configutil.FetchConfigFromFileOrCluster(client, os.Stdout, "upgrade", "")
|
cfg, err := configutil.FetchConfigFromFileOrCluster(client, os.Stdout, "upgrade", "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to fetch the kubeadm-config ConfigMap: %v", err)
|
return fmt.Errorf("Unable to fetch the kubeadm-config ConfigMap: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: as soon as the new config wil be in place check if the node is a known control plane instance
|
|
||||||
// and retrive corresponding infos (now are temporary managed as flag)
|
|
||||||
cfg.NodeRegistration.Name = flags.nodeName
|
|
||||||
cfg.APIEndpoint.AdvertiseAddress = flags.advertiseAddress
|
|
||||||
|
|
||||||
// Rotate API server certificate if needed
|
// Rotate API server certificate if needed
|
||||||
if err := upgrade.BackupAPIServerCertIfNeeded(cfg, flags.dryRun); err != nil {
|
if err := upgrade.BackupAPIServerCertIfNeeded(cfg, flags.dryRun); err != nil {
|
||||||
return fmt.Errorf("Unable to rotate API server certificate: %v", err)
|
return fmt.Errorf("Unable to rotate API server certificate: %v", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user