mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-09 12:07:47 +00:00
Merge pull request #62481 from taharah/master
Automatic merge from submit-queue (batch tested with PRs 62481, 62643, 61877, 62515). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. kubeadm preflight: check CRI socket path if defined or docker service otherwise **What this PR does / why we need it**: Currently, running `kubeadm init` without Docker installed will cause the `Service-Docker` preflight check to fail even when another CRI is installed and the CRI socket specified. This changes the preflight checks to check the CRI socket if specified, and falling back to checking the Docker service otherwise. Additionally, this deduplicates common checks between `kubeadm init` and `kubeadm join` to ensure that similar preflight checks stay in-sync going forward. **Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: Fixes # https://github.com/kubernetes/kubeadm/issues/657 - it still has the same behavior on joins Fixes # https://github.com/kubernetes/kubeadm/issues/749 - will check the CRI socket if specified and skip the Docker service check **Special notes for your reviewer**: **Release note**: ```release-note kubeadm preflight: check CRI socket path if defined, otherwise check for Docker ```
This commit is contained in:
commit
36bdcfc08c
@ -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 ""
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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{
|
||||
|
Loading…
Reference in New Issue
Block a user