diff --git a/cmd/kubeadm/app/apis/kubeadm/types.go b/cmd/kubeadm/app/apis/kubeadm/types.go index b3d4c63d87..9bf657f70f 100644 --- a/cmd/kubeadm/app/apis/kubeadm/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/types.go @@ -307,3 +307,50 @@ type AuditPolicyConfiguration struct { LogMaxAge *int32 //TODO(chuckha) add other options for audit policy. } + +// CommonConfiguration defines the list of common configuration elements and the getter +// methods that must exist for both the MasterConfiguration and NodeConfiguration objects. +// This is used internally to deduplicate the kubeadm preflight checks. +type CommonConfiguration interface { + GetCRISocket() string + GetNodeName() string + GetKubernetesVersion() string +} + +// GetCRISocket will return the CRISocket that is defined for the MasterConfiguration. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *MasterConfiguration) GetCRISocket() string { + return cfg.CRISocket +} + +// GetNodeName will return the NodeName that is defined for the MasterConfiguration. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *MasterConfiguration) GetNodeName() string { + return cfg.NodeName +} + +// GetKubernetesVersion will return the KubernetesVersion that is defined for the MasterConfiguration. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *MasterConfiguration) GetKubernetesVersion() string { + return cfg.KubernetesVersion +} + +// GetCRISocket will return the CRISocket that is defined for the NodeConfiguration. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *NodeConfiguration) GetCRISocket() string { + return cfg.CRISocket +} + +// GetNodeName will return the NodeName that is defined for the NodeConfiguration. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *NodeConfiguration) GetNodeName() string { + return cfg.NodeName +} + +// GetKubernetesVersion will return an empty string since KubernetesVersion is not a +// defined property for NodeConfiguration. This will just cause the regex validation +// of the defined version to be skipped during the preflight checks. +// This is used internally to deduplicate the kubeadm preflight checks. +func (cfg *NodeConfiguration) GetKubernetesVersion() string { + return "" +} diff --git a/cmd/kubeadm/app/preflight/BUILD b/cmd/kubeadm/app/preflight/BUILD index edeaa6d79c..ae8a3d5db8 100644 --- a/cmd/kubeadm/app/preflight/BUILD +++ b/cmd/kubeadm/app/preflight/BUILD @@ -53,6 +53,7 @@ go_library( "//cmd/kube-controller-manager/app/options:go_default_library", "//cmd/kube-scheduler/app:go_default_library", "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//pkg/apis/core/validation:go_default_library", "//pkg/kubeapiserver/authorizer/modes:go_default_library", diff --git a/cmd/kubeadm/app/preflight/checks.go b/cmd/kubeadm/app/preflight/checks.go index fd0559f3af..4336a019d0 100644 --- a/cmd/kubeadm/app/preflight/checks.go +++ b/cmd/kubeadm/app/preflight/checks.go @@ -48,6 +48,7 @@ import ( cmoptions "k8s.io/kubernetes/cmd/kube-controller-manager/app/options" schedulerapp "k8s.io/kubernetes/cmd/kube-scheduler/app" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmdefaults "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/pkg/apis/core/validation" authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" @@ -583,7 +584,7 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) { &system.KernelValidator{Reporter: reporter}} // run the docker validator only with dockershim - if sysver.CRISocket == "/var/run/dockershim.sock" { + if sysver.CRISocket == kubeadmdefaults.DefaultCRISocket { // https://github.com/kubernetes/kubeadm/issues/533 validators = append(validators, &system.DockerValidator{Reporter: reporter}) } @@ -873,46 +874,17 @@ func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfi return err } - // check if we can use crictl to perform checks via the CRI - glog.V(1).Infoln("checking if we can use crictl to perform checks via the CRI") - criCtlChecker := InPathCheck{ - executable: "crictl", - mandatory: false, - exec: execer, - suggestion: fmt.Sprintf("go get %v", kubeadmconstants.CRICtlPackage), - } - manifestsDir := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName) - checks := []Checker{ KubernetesVersionCheck{KubernetesVersion: cfg.KubernetesVersion, KubeadmVersion: kubeadmversion.Get().GitVersion}, - SystemVerificationCheck{CRISocket: cfg.CRISocket}, - IsPrivilegedUserCheck{}, - HostnameCheck{nodeName: cfg.NodeName}, - KubeletVersionCheck{KubernetesVersion: cfg.KubernetesVersion, exec: execer}, - ServiceCheck{Service: "kubelet", CheckIfActive: false}, - ServiceCheck{Service: "docker", CheckIfActive: true}, // assume docker FirewalldCheck{ports: []int{int(cfg.API.BindPort), 10250}}, PortOpenCheck{port: int(cfg.API.BindPort)}, - PortOpenCheck{port: 10250}, PortOpenCheck{port: 10251}, PortOpenCheck{port: 10252}, FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeAPIServer, manifestsDir)}, FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeControllerManager, manifestsDir)}, FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeScheduler, manifestsDir)}, FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.Etcd, manifestsDir)}, - FileContentCheck{Path: bridgenf, Content: []byte{'1'}}, - SwapCheck{}, - InPathCheck{executable: "ip", mandatory: true, exec: execer}, - InPathCheck{executable: "iptables", mandatory: true, exec: execer}, - InPathCheck{executable: "mount", mandatory: true, exec: execer}, - InPathCheck{executable: "nsenter", mandatory: true, exec: execer}, - InPathCheck{executable: "ebtables", mandatory: false, exec: execer}, - InPathCheck{executable: "ethtool", mandatory: false, exec: execer}, - InPathCheck{executable: "socat", mandatory: false, exec: execer}, - InPathCheck{executable: "tc", mandatory: false, exec: execer}, - InPathCheck{executable: "touch", mandatory: false, exec: execer}, - criCtlChecker, ExtraArgsCheck{ APIServerExtraArgs: cfg.APIServerExtraArgs, ControllerManagerExtraArgs: cfg.ControllerManagerExtraArgs, @@ -922,6 +894,7 @@ func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfi HTTPProxyCIDRCheck{Proto: "https", CIDR: cfg.Networking.ServiceSubnet}, HTTPProxyCIDRCheck{Proto: "https", CIDR: cfg.Networking.PodSubnet}, } + checks = addCommonChecks(execer, cfg, checks) if len(cfg.Etcd.Endpoints) == 0 { // Only do etcd related checks when no external endpoints were specified @@ -972,50 +945,13 @@ func RunJoinNodeChecks(execer utilsexec.Interface, cfg *kubeadmapi.NodeConfigura return err } - // check if we can use crictl to perform checks via the CRI - criCtlChecker := InPathCheck{ - executable: "crictl", - mandatory: false, - exec: execer, - suggestion: fmt.Sprintf("go get %v", kubeadmconstants.CRICtlPackage), - } - warns, _ := criCtlChecker.Check() - useCRI := len(warns) == 0 - checks := []Checker{ - SystemVerificationCheck{CRISocket: cfg.CRISocket}, - IsPrivilegedUserCheck{}, - HostnameCheck{cfg.NodeName}, - KubeletVersionCheck{exec: execer}, - ServiceCheck{Service: "kubelet", CheckIfActive: false}, - PortOpenCheck{port: 10250}, DirAvailableCheck{Path: filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName)}, FileAvailableCheck{Path: cfg.CACertPath}, FileAvailableCheck{Path: filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName)}, FileAvailableCheck{Path: filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletBootstrapKubeConfigFileName)}, } - if useCRI { - checks = append(checks, CRICheck{socket: cfg.CRISocket, exec: execer}) - } else { - // assume docker - checks = append(checks, ServiceCheck{Service: "docker", CheckIfActive: true}) - } - //non-windows checks - if runtime.GOOS == "linux" { - checks = append(checks, - FileContentCheck{Path: bridgenf, Content: []byte{'1'}}, - SwapCheck{}, - InPathCheck{executable: "ip", mandatory: true, exec: execer}, - InPathCheck{executable: "iptables", mandatory: true, exec: execer}, - InPathCheck{executable: "mount", mandatory: true, exec: execer}, - InPathCheck{executable: "nsenter", mandatory: true, exec: execer}, - InPathCheck{executable: "ebtables", mandatory: false, exec: execer}, - InPathCheck{executable: "ethtool", mandatory: false, exec: execer}, - InPathCheck{executable: "socat", mandatory: false, exec: execer}, - InPathCheck{executable: "tc", mandatory: false, exec: execer}, - InPathCheck{executable: "touch", mandatory: false, exec: execer}, - criCtlChecker) - } + checks = addCommonChecks(execer, cfg, checks) var bridgenf6Check Checker for _, server := range cfg.DiscoveryTokenAPIServers { @@ -1041,6 +977,51 @@ func RunJoinNodeChecks(execer utilsexec.Interface, cfg *kubeadmapi.NodeConfigura return RunChecks(checks, os.Stderr, ignorePreflightErrors) } +// addCommonChecks is a helper function to deplicate checks that are common between both the +// kubeadm init and join commands +func addCommonChecks(execer utilsexec.Interface, cfg kubeadmapi.CommonConfiguration, checks []Checker) []Checker { + // check if we can use crictl to perform checks via the CRI + glog.V(1).Infoln("checking if we can use crictl to perform checks via the CRI") + criCtlChecker := InPathCheck{ + executable: "crictl", + mandatory: false, + exec: execer, + suggestion: fmt.Sprintf("go get %v", kubeadmconstants.CRICtlPackage), + } + + // Check whether or not the CRI socket defined is the default + if cfg.GetCRISocket() != kubeadmdefaults.DefaultCRISocket { + checks = append(checks, CRICheck{socket: cfg.GetCRISocket(), exec: execer}) + } else { + checks = append(checks, ServiceCheck{Service: "docker", CheckIfActive: true}) + } + + // non-windows checks + if runtime.GOOS == "linux" { + checks = append(checks, + FileContentCheck{Path: bridgenf, Content: []byte{'1'}}, + SwapCheck{}, + InPathCheck{executable: "ip", mandatory: true, exec: execer}, + InPathCheck{executable: "iptables", mandatory: true, exec: execer}, + InPathCheck{executable: "mount", mandatory: true, exec: execer}, + InPathCheck{executable: "nsenter", mandatory: true, exec: execer}, + InPathCheck{executable: "ebtables", mandatory: false, exec: execer}, + InPathCheck{executable: "ethtool", mandatory: false, exec: execer}, + InPathCheck{executable: "socat", mandatory: false, exec: execer}, + InPathCheck{executable: "tc", mandatory: false, exec: execer}, + InPathCheck{executable: "touch", mandatory: false, exec: execer}, + criCtlChecker) + } + checks = append(checks, + SystemVerificationCheck{CRISocket: cfg.GetCRISocket()}, + IsPrivilegedUserCheck{}, + HostnameCheck{nodeName: cfg.GetNodeName()}, + KubeletVersionCheck{KubernetesVersion: cfg.GetKubernetesVersion(), exec: execer}, + ServiceCheck{Service: "kubelet", CheckIfActive: false}, + PortOpenCheck{port: 10250}) + return checks +} + // RunRootCheckOnly initializes checks slice of structs and call RunChecks func RunRootCheckOnly(ignorePreflightErrors sets.String) error { checks := []Checker{