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. // supported by this api will be exposed as a flag.
type nodeOptions struct { type nodeOptions struct {
kubeConfigPath string kubeConfigPath string
isControlPlaneNode bool
etcdUpgrade bool etcdUpgrade bool
renewCerts bool renewCerts bool
dryRun 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. // newNodeOptions returns a struct ready for being used for creating cmd kubeadm upgrade node flags.
func newNodeOptions() *nodeOptions { 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{ return &nodeOptions{
kubeConfigPath: kubeConfigPath, kubeConfigPath: "", // This is populated in newNodeData() on runtime
isControlPlaneNode: isControlPlaneNode, dryRun: false,
dryRun: false, renewCerts: true,
renewCerts: true, etcdUpgrade: 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 // 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 // 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) { 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) client, err := getClient(options.kubeConfigPath, options.dryRun)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", options.kubeConfigPath) 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 // 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 // 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 // (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 { 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")
} }
@ -165,7 +163,7 @@ func newNodeData(cmd *cobra.Command, args []string, options *nodeOptions, out io
dryRun: options.dryRun, dryRun: options.dryRun,
cfg: cfg, cfg: cfg,
client: client, client: client,
isControlPlaneNode: options.isControlPlaneNode, isControlPlaneNode: isControlPlaneNode,
patchesDir: options.patchesDir, patchesDir: options.patchesDir,
ignorePreflightErrors: ignorePreflightErrorsSet, ignorePreflightErrors: ignorePreflightErrorsSet,
kubeConfigPath: options.kubeConfigPath, kubeConfigPath: options.kubeConfigPath,