mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-02-22 15:19:12 +00:00
Merge pull request #134319 from neolit123/1.35-refactor-fetch-init-config-flags
kubeadm: rework the FetchInitConfigurationFromCluster node flags
This commit is contained in:
@@ -49,6 +49,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/errors"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
||||
staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -346,7 +347,10 @@ func getInternalCfg(cfgPath string, client kubernetes.Interface, cfg kubeadmapiv
|
||||
// In case the user is not providing a custom config, try to get current config from the cluster.
|
||||
// NB. this operation should not block, because we want to allow certificate renewal also in case of not-working clusters
|
||||
if cfgPath == "" && client != nil {
|
||||
internalcfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, logPrefix, false, false)
|
||||
getNodeRegistration := true
|
||||
getAPIEndpoint := staticpodutil.IsControlPlaneNode()
|
||||
getComponentConfigs := true
|
||||
internalcfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, logPrefix, getNodeRegistration, getAPIEndpoint, getComponentConfigs)
|
||||
if err == nil {
|
||||
printer.Println() // add empty line to separate the FetchInitConfigurationFromCluster output from the command output
|
||||
// certificate renewal or expiration checking doesn't depend on a running cluster, which means the CertificatesDir
|
||||
|
||||
@@ -709,7 +709,10 @@ func fetchInitConfigurationFromJoinConfiguration(cfg *kubeadmapi.JoinConfigurati
|
||||
|
||||
// fetchInitConfiguration reads the cluster configuration from the kubeadm-admin configMap
|
||||
func fetchInitConfiguration(client clientset.Interface) (*kubeadmapi.InitConfiguration, error) {
|
||||
initConfiguration, err := configutil.FetchInitConfigurationFromCluster(client, nil, "preflight", true, false)
|
||||
getNodeRegistration := false
|
||||
getAPIEndpoint := false
|
||||
getComponentConfigs := true
|
||||
initConfiguration, err := configutil.FetchInitConfigurationFromCluster(client, nil, "preflight", getNodeRegistration, getAPIEndpoint, getComponentConfigs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap")
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/errors"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
utilruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime"
|
||||
staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -132,7 +133,10 @@ func newResetData(cmd *cobra.Command, opts *resetOptions, in io.Reader, out io.W
|
||||
|
||||
if err == nil {
|
||||
klog.V(1).Infof("[reset] Loaded client set from kubeconfig file: %s", opts.kubeconfigPath)
|
||||
initCfg, err = configutil.FetchInitConfigurationFromCluster(client, nil, "reset", false, false)
|
||||
getNodeRegistration := true
|
||||
getAPIEndpoint := staticpodutil.IsControlPlaneNode()
|
||||
getComponentConfigs := true
|
||||
initCfg, err = configutil.FetchInitConfigurationFromCluster(client, nil, "reset", getNodeRegistration, getAPIEndpoint, getComponentConfigs)
|
||||
if err != nil {
|
||||
klog.Warningf("[reset] Unable to fetch the kubeadm-config ConfigMap from cluster: %v", err)
|
||||
}
|
||||
|
||||
@@ -238,7 +238,10 @@ func newApplyData(cmd *cobra.Command, args []string, applyFlags *applyFlags) (*a
|
||||
|
||||
// Fetches the cluster configuration.
|
||||
klog.V(1).Infoln("[upgrade] retrieving configuration from cluster")
|
||||
initCfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", false, false)
|
||||
getNodeRegistration := true
|
||||
isControlPlaneNode := true
|
||||
getComponentConfigs := true
|
||||
initCfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", getNodeRegistration, isControlPlaneNode, getComponentConfigs)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
_, _ = printer.Printf("[upgrade] In order to upgrade, a ConfigMap called %q in the %q namespace must exist.\n", constants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
|
||||
|
||||
@@ -45,6 +45,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/errors"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
||||
staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod"
|
||||
)
|
||||
|
||||
// enforceRequirements verifies that it's okay to upgrade and then returns the variables needed for the rest of the procedure
|
||||
@@ -92,7 +93,10 @@ func enforceRequirements(flagSet *pflag.FlagSet, flags *applyPlanFlags, args []s
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
initCfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, "upgrade/config", false, false)
|
||||
getNodeRegistration := true
|
||||
getAPIEndpoint := staticpodutil.IsControlPlaneNode()
|
||||
getComponentConfigs := true
|
||||
initCfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, "upgrade/config", getNodeRegistration, getAPIEndpoint, getComponentConfigs)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errors.Wrap(err, "[upgrade/init config] FATAL")
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/errors"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
||||
staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod"
|
||||
)
|
||||
|
||||
type diffFlags struct {
|
||||
@@ -106,7 +107,7 @@ func validateManifestsPath(manifests ...string) (err error) {
|
||||
}
|
||||
|
||||
// FetchInitConfigurationFunc defines the signature of the function which will fetch InitConfiguration from cluster.
|
||||
type FetchInitConfigurationFunc func(client clientset.Interface, printer output.Printer, logPrefix string, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error)
|
||||
type FetchInitConfigurationFunc func(client clientset.Interface, printer output.Printer, logPrefix string, getNodeRegistration, getAPIEndpoint, getComponentConfigs bool) (*kubeadmapi.InitConfiguration, error)
|
||||
|
||||
func runDiff(fs *pflag.FlagSet, flags *diffFlags, args []string, fetchInitConfigurationFromCluster FetchInitConfigurationFunc) error {
|
||||
externalCfg := &v1beta4.UpgradeConfiguration{}
|
||||
@@ -119,7 +120,10 @@ func runDiff(fs *pflag.FlagSet, flags *diffFlags, args []string, fetchInitConfig
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", flags.kubeConfigPath)
|
||||
}
|
||||
initCfg, err := fetchInitConfigurationFromCluster(client, &output.TextPrinter{}, "upgrade/diff", false, true)
|
||||
getNodeRegistration := true
|
||||
getAPIEndpoint := staticpodutil.IsControlPlaneNode()
|
||||
getComponentConfigs := false
|
||||
initCfg, err := fetchInitConfigurationFromCluster(client, &output.TextPrinter{}, "upgrade/diff", getNodeRegistration, getAPIEndpoint, getComponentConfigs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ func createTestRunDiffFile(contents []byte) (string, error) {
|
||||
return file.Name(), nil
|
||||
}
|
||||
|
||||
func fakeFetchInitConfig(client clientset.Interface, printer output.Printer, logPrefix string, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
func fakeFetchInitConfig(client clientset.Interface, printer output.Printer, logPrefix string, getNodeRegistration, getAPIEndpoint, getComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
return &kubeadmapi.InitConfiguration{
|
||||
ClusterConfiguration: kubeadmapi.ClusterConfiguration{
|
||||
KubernetesVersion: "v1.0.1",
|
||||
|
||||
@@ -19,7 +19,6 @@ package upgrade
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
@@ -40,6 +39,7 @@ import (
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/errors"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/output"
|
||||
staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod"
|
||||
)
|
||||
|
||||
// nodeOptions defines all the options exposed via flags by kubeadm upgrade node.
|
||||
@@ -165,13 +165,8 @@ 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, nodeOptions *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) {
|
||||
klog.V(1).Infof("assuming this is not a control plane node because %q is missing", filepath)
|
||||
isControlPlaneNode = false
|
||||
}
|
||||
isControlPlaneNode := staticpodutil.IsControlPlaneNode()
|
||||
|
||||
if len(nodeOptions.kubeConfigPath) == 0 {
|
||||
// Update the kubeconfig path depending on whether this is a control plane node or not.
|
||||
nodeOptions.kubeConfigPath = constants.GetKubeletKubeConfigPath()
|
||||
@@ -207,9 +202,10 @@ func newNodeData(cmd *cobra.Command, nodeOptions *nodeOptions, out io.Writer) (*
|
||||
}
|
||||
|
||||
// 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
|
||||
initCfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", !isControlPlaneNode, false)
|
||||
getNodeRegistration := true
|
||||
getAPIEndpoint := isControlPlaneNode
|
||||
getComponentConfigs := true
|
||||
initCfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", getNodeRegistration, getAPIEndpoint, getComponentConfigs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap")
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ import (
|
||||
)
|
||||
|
||||
// FetchInitConfigurationFromCluster fetches configuration from a ConfigMap in the cluster
|
||||
func FetchInitConfigurationFromCluster(client clientset.Interface, printer output.Printer, logPrefix string, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
func FetchInitConfigurationFromCluster(client clientset.Interface, printer output.Printer, logPrefix string, getNodeRegistration, getAPIEndpoint, getComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
if printer == nil {
|
||||
printer = &output.TextPrinter{}
|
||||
}
|
||||
@@ -60,7 +60,7 @@ func FetchInitConfigurationFromCluster(client clientset.Interface, printer outpu
|
||||
_, _ = printer.Printf("[%s] Use 'kubeadm init phase upload-config kubeadm --config your-config-file' to re-upload it.\n", logPrefix)
|
||||
|
||||
// Fetch the actual config from cluster
|
||||
cfg, err := getInitConfigurationFromCluster(constants.KubernetesDir, client, newControlPlane, skipComponentConfigs)
|
||||
cfg, err := getInitConfigurationFromCluster(constants.KubernetesDir, client, getNodeRegistration, getAPIEndpoint, getComponentConfigs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -75,7 +75,7 @@ func FetchInitConfigurationFromCluster(client clientset.Interface, printer outpu
|
||||
}
|
||||
|
||||
// getInitConfigurationFromCluster is separate only for testing purposes, don't call it directly, use FetchInitConfigurationFromCluster instead
|
||||
func getInitConfigurationFromCluster(kubeconfigDir string, client clientset.Interface, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
func getInitConfigurationFromCluster(kubeconfigDir string, client clientset.Interface, getNodeRegistration, getAPIEndpoint, getComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
// Also, the config map really should be KubeadmConfigConfigMap...
|
||||
configMap, err := apiclient.GetConfigMapWithShortRetry(client, metav1.NamespaceSystem, constants.KubeadmConfigConfigMap)
|
||||
if err != nil {
|
||||
@@ -105,26 +105,28 @@ func getInitConfigurationFromCluster(kubeconfigDir string, client clientset.Inte
|
||||
return nil, errors.Wrap(err, "failed to decode cluster configuration data")
|
||||
}
|
||||
|
||||
if !skipComponentConfigs {
|
||||
if getComponentConfigs {
|
||||
// get the component configs from the corresponding config maps
|
||||
if err := componentconfigs.FetchFromCluster(&initcfg.ClusterConfiguration, client); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get component configs")
|
||||
}
|
||||
}
|
||||
|
||||
// if this isn't a new controlplane instance (e.g. in case of kubeadm upgrades)
|
||||
// get nodes specific information as well
|
||||
if !newControlPlane {
|
||||
if getNodeRegistration {
|
||||
// gets the nodeRegistration for the current from the node object
|
||||
kubeconfigFile := filepath.Join(kubeconfigDir, constants.KubeletKubeConfigFileName)
|
||||
if err := GetNodeRegistration(kubeconfigFile, client, &initcfg.NodeRegistration, &initcfg.ClusterConfiguration); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get node registration")
|
||||
}
|
||||
// gets the APIEndpoint for the current node
|
||||
if err := getAPIEndpoint(client, initcfg.NodeRegistration.Name, &initcfg.LocalAPIEndpoint); err != nil {
|
||||
}
|
||||
|
||||
if getAPIEndpoint {
|
||||
// gets the APIEndpoint for the current control plane node
|
||||
if err := GetAPIEndpoint(client, initcfg.NodeRegistration.Name, &initcfg.LocalAPIEndpoint); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to getAPIEndpoint")
|
||||
}
|
||||
}
|
||||
|
||||
return initcfg, nil
|
||||
}
|
||||
|
||||
@@ -257,7 +259,8 @@ func getNodeNameFromSSR(client clientset.Interface) (string, error) {
|
||||
return strings.TrimPrefix(user, constants.NodesUserPrefix), nil
|
||||
}
|
||||
|
||||
func getAPIEndpoint(client clientset.Interface, nodeName string, apiEndpoint *kubeadmapi.APIEndpoint) error {
|
||||
// GetAPIEndpoint gets the API endpoint for a given node.
|
||||
func GetAPIEndpoint(client clientset.Interface, nodeName string, apiEndpoint *kubeadmapi.APIEndpoint) error {
|
||||
return getAPIEndpointWithRetry(client, nodeName, apiEndpoint,
|
||||
constants.KubernetesAPICallRetryInterval, kubeadmapi.GetActiveTimeouts().KubernetesAPICall.Duration)
|
||||
}
|
||||
|
||||
@@ -491,13 +491,14 @@ func TestGetInitConfigurationFromCluster(t *testing.T) {
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
fileContents []byte
|
||||
node *v1.Node
|
||||
staticPods []testresources.FakeStaticPod
|
||||
configMaps []testresources.FakeConfigMap
|
||||
newControlPlane bool
|
||||
expectedError bool
|
||||
name string
|
||||
fileContents []byte
|
||||
node *v1.Node
|
||||
staticPods []testresources.FakeStaticPod
|
||||
configMaps []testresources.FakeConfigMap
|
||||
getNodeRegistration bool
|
||||
getAPIEndpoint bool
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "invalid - No kubeadm-config ConfigMap",
|
||||
@@ -556,6 +557,8 @@ func TestGetInitConfigurationFromCluster(t *testing.T) {
|
||||
Taints: []v1.Taint{kubeadmconstants.ControlPlaneTaint},
|
||||
},
|
||||
},
|
||||
getNodeRegistration: true,
|
||||
getAPIEndpoint: true,
|
||||
},
|
||||
{
|
||||
name: "valid v1beta3 - new control plane == true", // InitConfiguration composed with data from different places, without node specific information
|
||||
@@ -588,7 +591,8 @@ func TestGetInitConfigurationFromCluster(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
newControlPlane: true,
|
||||
getNodeRegistration: false,
|
||||
getAPIEndpoint: false,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -629,7 +633,8 @@ func TestGetInitConfigurationFromCluster(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
cfg, err := getInitConfigurationFromCluster(tmpdir, client, rt.newControlPlane, false)
|
||||
getComponentConfigs := true
|
||||
cfg, err := getInitConfigurationFromCluster(tmpdir, client, rt.getNodeRegistration, rt.getAPIEndpoint, getComponentConfigs)
|
||||
if rt.expectedError != (err != nil) {
|
||||
t.Errorf("unexpected return err from getInitConfigurationFromCluster: %v", err)
|
||||
return
|
||||
@@ -649,13 +654,13 @@ func TestGetInitConfigurationFromCluster(t *testing.T) {
|
||||
if cfg.NodeRegistration.ImagePullPolicy != kubeadmapiv1.DefaultImagePullPolicy {
|
||||
t.Errorf("invalid cfg.NodeRegistration.ImagePullPolicy %v", cfg.NodeRegistration.ImagePullPolicy)
|
||||
}
|
||||
if !rt.newControlPlane && (cfg.LocalAPIEndpoint.AdvertiseAddress != "1.2.3.4" || cfg.LocalAPIEndpoint.BindPort != 1234) {
|
||||
if rt.getNodeRegistration && rt.getAPIEndpoint && (cfg.LocalAPIEndpoint.AdvertiseAddress != "1.2.3.4" || cfg.LocalAPIEndpoint.BindPort != 1234) {
|
||||
t.Errorf("invalid cfg.LocalAPIEndpoint: %v", cfg.LocalAPIEndpoint)
|
||||
}
|
||||
if !rt.newControlPlane && (cfg.NodeRegistration.Name != nodeName || cfg.NodeRegistration.CRISocket != "myCRIsocket" || len(cfg.NodeRegistration.Taints) != 1) {
|
||||
if rt.getNodeRegistration && (cfg.NodeRegistration.Name != nodeName || cfg.NodeRegistration.CRISocket != "myCRIsocket" || len(cfg.NodeRegistration.Taints) != 1) {
|
||||
t.Errorf("invalid cfg.NodeRegistration: %v", cfg.NodeRegistration)
|
||||
}
|
||||
if rt.newControlPlane && len(cfg.NodeRegistration.CRISocket) > 0 {
|
||||
if !rt.getNodeRegistration && len(cfg.NodeRegistration.CRISocket) > 0 {
|
||||
t.Errorf("invalid cfg.NodeRegistration.CRISocket: expected empty CRISocket, but got %v", cfg.NodeRegistration.CRISocket)
|
||||
}
|
||||
if _, ok := cfg.ComponentConfigs[componentconfigs.KubeletGroup]; !ok {
|
||||
|
||||
@@ -419,3 +419,18 @@ func DeepHashObject(hasher hash.Hash, objectToWrite interface{}) {
|
||||
hasher.Reset()
|
||||
fmt.Fprintf(hasher, "%v", dump.ForHash(objectToWrite))
|
||||
}
|
||||
|
||||
// IsControlPlaneNode returns true if the kube-apiserver static pod manifest is present
|
||||
// on the host.
|
||||
func IsControlPlaneNode() bool {
|
||||
isControlPlaneNode := true
|
||||
|
||||
filepath := kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeAPIServer,
|
||||
kubeadmconstants.GetStaticPodDirectory())
|
||||
|
||||
if _, err := os.Stat(filepath); os.IsNotExist(err) {
|
||||
isControlPlaneNode = false
|
||||
}
|
||||
|
||||
return isControlPlaneNode
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user