From 774d666d1ce3c36c29882da521471e71dd352a49 Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Thu, 1 Feb 2024 16:32:11 +0200 Subject: [PATCH] kubeadm: better checks if the node is CP during "upgrade node" Currently --rootfs does not work with "upgrade node" for CP nodes because the only check of CP nodes is performed in newNodeOptions() which runs before the root kubeadm command is run, thus the chroot() path coming from --rootfs is not applied yet. To work around that call the "isControlPlaneNode" check when constructing the command data on command runtime. --- cmd/kubeadm/app/cmd/upgrade/node.go | 42 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/cmd/kubeadm/app/cmd/upgrade/node.go b/cmd/kubeadm/app/cmd/upgrade/node.go index 0523172d339..9998436edb2 100644 --- a/cmd/kubeadm/app/cmd/upgrade/node.go +++ b/cmd/kubeadm/app/cmd/upgrade/node.go @@ -41,7 +41,6 @@ import ( // supported by this api will be exposed as a flag. type nodeOptions struct { kubeConfigPath string - isControlPlaneNode bool etcdUpgrade bool renewCerts bool dryRun bool @@ -106,26 +105,11 @@ func newCmdNode(out io.Writer) *cobra.Command { // newNodeOptions returns a struct ready for being used for creating cmd kubeadm upgrade node flags. func newNodeOptions() *nodeOptions { - kubeConfigPath := constants.GetKubeletKubeConfigPath() - - // isControlPlaneNode checks if a node is a control-plane node by looking up - // the kube-apiserver manifest file - isControlPlaneNode := true - filepath := constants.GetStaticPodFilepath(constants.KubeAPIServer, constants.GetStaticPodDirectory()) - if _, err := os.Stat(filepath); os.IsNotExist(err) { - isControlPlaneNode = false - } - - if isControlPlaneNode { - kubeConfigPath = constants.GetAdminKubeConfigPath() - } - return &nodeOptions{ - kubeConfigPath: kubeConfigPath, - isControlPlaneNode: isControlPlaneNode, - dryRun: false, - renewCerts: true, - etcdUpgrade: true, + kubeConfigPath: "", // This is populated in newNodeData() on runtime + dryRun: false, + renewCerts: true, + etcdUpgrade: true, } } @@ -141,6 +125,20 @@ func addUpgradeNodeFlags(flagSet *flag.FlagSet, nodeOptions *nodeOptions) { // This func takes care of validating nodeOptions passed to the command, and then it converts // options into the internal InitConfiguration type that is used as input all the phases in the kubeadm upgrade node workflow func newNodeData(cmd *cobra.Command, args []string, options *nodeOptions, out io.Writer) (*nodeData, error) { + // Checks if a node is a control-plane node by looking up the kube-apiserver manifest file + isControlPlaneNode := true + filepath := constants.GetStaticPodFilepath(constants.KubeAPIServer, constants.GetStaticPodDirectory()) + if _, err := os.Stat(filepath); os.IsNotExist(err) { + isControlPlaneNode = false + } + if len(options.kubeConfigPath) == 0 { + // Update the kubeconfig path depending on whether this is a control plane node or not. + options.kubeConfigPath = constants.GetKubeletKubeConfigPath() + if isControlPlaneNode { + options.kubeConfigPath = constants.GetAdminKubeConfigPath() + } + } + client, err := getClient(options.kubeConfigPath, options.dryRun) if err != nil { return nil, errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", options.kubeConfigPath) @@ -148,7 +146,7 @@ func newNodeData(cmd *cobra.Command, args []string, options *nodeOptions, out io // Fetches the cluster configuration // NB in case of control-plane node, we are reading all the info for the node; in case of NOT control-plane node // (worker node), we are not reading local API address and the CRI socket from the node object - cfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", !options.isControlPlaneNode, false) + cfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", !isControlPlaneNode, false) if err != nil { return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap") } @@ -165,7 +163,7 @@ func newNodeData(cmd *cobra.Command, args []string, options *nodeOptions, out io dryRun: options.dryRun, cfg: cfg, client: client, - isControlPlaneNode: options.isControlPlaneNode, + isControlPlaneNode: isControlPlaneNode, patchesDir: options.patchesDir, ignorePreflightErrors: ignorePreflightErrorsSet, kubeConfigPath: options.kubeConfigPath,