mirror of https://github.com/k3s-io/k3s
kubeadm: Extended KubeletVersionCheck
KubeletVersionCheck now able to detect if kubelet version is higher than control plane. As this might lead to malfunctional cluster setups, kubeadm will give warning. Fixes: kubernetes/kubeadm#496pull/6/head
parent
e9f7970caa
commit
de272d0617
|
@ -498,7 +498,9 @@ func (kubever KubernetesVersionCheck) Check() (warnings, errors []error) {
|
|||
}
|
||||
|
||||
// KubeletVersionCheck validates installed kubelet version
|
||||
type KubeletVersionCheck struct{}
|
||||
type KubeletVersionCheck struct {
|
||||
KubernetesVersion string
|
||||
}
|
||||
|
||||
// Check validates kubelet version. It should be not less than minimal supported version
|
||||
func (kubever KubeletVersionCheck) Check() (warnings, errors []error) {
|
||||
|
@ -509,7 +511,17 @@ func (kubever KubeletVersionCheck) Check() (warnings, errors []error) {
|
|||
if kubeletVersion.LessThan(kubeadmconstants.MinimumKubeletVersion) {
|
||||
return nil, []error{fmt.Errorf("Kubelet version %q is lower than kubadm can support. Please upgrade kubelet", kubeletVersion)}
|
||||
}
|
||||
return nil, []error{}
|
||||
|
||||
if kubever.KubernetesVersion != "" {
|
||||
k8sVersion, err := versionutil.ParseSemantic(kubever.KubernetesVersion)
|
||||
if err != nil {
|
||||
return nil, []error{fmt.Errorf("couldn't parse kubernetes version %q: %v", kubever.KubernetesVersion, err)}
|
||||
}
|
||||
if kubeletVersion.Major() > k8sVersion.Major() || kubeletVersion.Minor() > k8sVersion.Minor() {
|
||||
return nil, []error{fmt.Errorf("the kubelet version is higher than the control plane version. This is not a supported version skew and may lead to a malfunctional cluster. Kubelet version: %q Control plane version: %q", kubeletVersion, k8sVersion)}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// SwapCheck warns if swap is enabled
|
||||
|
@ -688,7 +700,7 @@ func RunInitMasterChecks(cfg *kubeadmapi.MasterConfiguration) error {
|
|||
SystemVerificationCheck{},
|
||||
IsPrivilegedUserCheck{},
|
||||
HostnameCheck{nodeName: cfg.NodeName},
|
||||
KubeletVersionCheck{},
|
||||
KubeletVersionCheck{KubernetesVersion: cfg.KubernetesVersion},
|
||||
ServiceCheck{Service: "kubelet", CheckIfActive: false},
|
||||
ServiceCheck{Service: "docker", CheckIfActive: true},
|
||||
FirewalldCheck{ports: []int{int(cfg.API.BindPort), 10250}},
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
@ -556,3 +557,59 @@ func restoreEnv(e map[string]string) {
|
|||
os.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKubeletVersionCheck(t *testing.T) {
|
||||
type T struct {
|
||||
kubeletVersion string
|
||||
k8sVersion string
|
||||
expectErrors bool
|
||||
expectWarnings bool
|
||||
}
|
||||
|
||||
cases := []T{
|
||||
{"v1.10.2", "", false, false}, // check minimally supported version when there is no information about control plane
|
||||
{"v1.7.3", "v1.7.8", true, false}, // too old kubelet (older than kubeadmconstants.MinimumKubeletVersion), should fail.
|
||||
{"v1.9.0", "v1.9.5", false, false}, // kubelet within same major.minor as control plane
|
||||
{"v1.9.5", "v1.9.1", false, false}, // kubelet is newer, but still within same major.minor as control plane
|
||||
{"v1.9.0", "v1.10.1", false, false}, // kubelet is lower than control plane, but newer than minimally supported
|
||||
{"v1.10.0-alpha.1", "v1.9.1", true, false}, // kubelet is newer (development build) than control plane, should fail.
|
||||
{"v1.10.0", "v1.9.5", true, false}, // kubelet is newer (release) than control plane, should fail.
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir("", "test-kubelet-version-check")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create directory for testing GetKubeletVersion: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// We don't want to call real kubelet or something else in $PATH
|
||||
oldPATH := os.Getenv("PATH")
|
||||
defer os.Setenv("PATH", oldPATH)
|
||||
|
||||
os.Setenv("PATH", dir)
|
||||
|
||||
kubeletFn := filepath.Join(dir, "kubelet")
|
||||
for _, tc := range cases {
|
||||
|
||||
content := []byte(fmt.Sprintf("#!/bin/sh\necho 'Kubernetes %s'", tc.kubeletVersion))
|
||||
if err := ioutil.WriteFile(kubeletFn, content, 0755); err != nil {
|
||||
t.Errorf("Error creating test stub file %s: %v", kubeletFn, err)
|
||||
}
|
||||
|
||||
check := KubeletVersionCheck{KubernetesVersion: tc.k8sVersion}
|
||||
warnings, errors := check.Check()
|
||||
|
||||
switch {
|
||||
case warnings != nil && !tc.expectWarnings:
|
||||
t.Errorf("KubeletVersionCheck: unexpected warnings for kubelet version %q and kubernetes version %q. Warnings: %v", tc.kubeletVersion, tc.k8sVersion, warnings)
|
||||
case warnings == nil && tc.expectWarnings:
|
||||
t.Errorf("KubeletVersionCheck: expected warnings for kubelet version %q and kubernetes version %q but got nothing", tc.kubeletVersion, tc.k8sVersion)
|
||||
case errors != nil && !tc.expectErrors:
|
||||
t.Errorf("KubeletVersionCheck: unexpected errors for kubelet version %q and kubernetes version %q. errors: %v", tc.kubeletVersion, tc.k8sVersion, errors)
|
||||
case errors == nil && tc.expectErrors:
|
||||
t.Errorf("KubeletVersionCheck: expected errors for kubelet version %q and kubernetes version %q but got nothing", tc.kubeletVersion, tc.k8sVersion)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue