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.
This commit is contained in:
Lubomir I. Ivanov 2024-02-01 16:32:11 +02:00
parent 11b9740436
commit 774d666d1c

View File

@ -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,