mirror of https://github.com/k3s-io/k3s
Merge pull request #47698 from fabriziopandini/kubeadm308
Automatic merge from submit-queue (batch tested with PRs 46458, 50934, 50766, 50970, 47698) kubeadm: Warn in preflight checks if KubernetesVersion is of a newer branch than kubeadm **What this PR does / why we need it**: see https://github.com/kubernetes/kubeadm/issues/307 **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes # https://github.com/kubernetes/kubeadm/issues/307 **Special notes for your reviewer**: **Release note**:pull/6/head
commit
bf00190037
|
@ -17,6 +17,8 @@ go_library(
|
||||||
"//pkg/api/validation:go_default_library",
|
"//pkg/api/validation:go_default_library",
|
||||||
"//pkg/kubeapiserver/authorizer/modes:go_default_library",
|
"//pkg/kubeapiserver/authorizer/modes:go_default_library",
|
||||||
"//pkg/util/initsystem:go_default_library",
|
"//pkg/util/initsystem:go_default_library",
|
||||||
|
"//pkg/util/version:go_default_library",
|
||||||
|
"//pkg/version:go_default_library",
|
||||||
"//plugin/cmd/kube-scheduler/app/options:go_default_library",
|
"//plugin/cmd/kube-scheduler/app/options:go_default_library",
|
||||||
"//test/e2e_node/system:go_default_library",
|
"//test/e2e_node/system:go_default_library",
|
||||||
"//vendor/github.com/PuerkitoBio/purell:go_default_library",
|
"//vendor/github.com/PuerkitoBio/purell:go_default_library",
|
||||||
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
@ -46,6 +47,8 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api/validation"
|
"k8s.io/kubernetes/pkg/api/validation"
|
||||||
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
||||||
"k8s.io/kubernetes/pkg/util/initsystem"
|
"k8s.io/kubernetes/pkg/util/initsystem"
|
||||||
|
versionutil "k8s.io/kubernetes/pkg/util/version"
|
||||||
|
kubeadmversion "k8s.io/kubernetes/pkg/version"
|
||||||
schoptions "k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/options"
|
schoptions "k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/options"
|
||||||
"k8s.io/kubernetes/test/e2e_node/system"
|
"k8s.io/kubernetes/test/e2e_node/system"
|
||||||
)
|
)
|
||||||
|
@ -394,6 +397,40 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) {
|
||||||
return warns, nil
|
return warns, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type KubernetesVersionCheck struct {
|
||||||
|
KubeadmVersion string
|
||||||
|
KubernetesVersion string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kubever KubernetesVersionCheck) Check() (warnings, errors []error) {
|
||||||
|
|
||||||
|
// Skip this check for "super-custom builds", where apimachinery/the overall codebase version is not set.
|
||||||
|
if strings.HasPrefix(kubever.KubeadmVersion, "v0.0.0") {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
kadmVersion, err := versionutil.ParseSemantic(kubever.KubeadmVersion)
|
||||||
|
if err != nil {
|
||||||
|
return nil, []error{fmt.Errorf("couldn't parse kubeadm version %q: %v", kubever.KubeadmVersion, err)}
|
||||||
|
}
|
||||||
|
|
||||||
|
k8sVersion, err := versionutil.ParseSemantic(kubever.KubernetesVersion)
|
||||||
|
if err != nil {
|
||||||
|
return nil, []error{fmt.Errorf("couldn't parse kubernetes version %q: %v", kubever.KubernetesVersion, err)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if k8sVersion greater or equal than the first unsupported versions by current version of kubeadm,
|
||||||
|
// that is major.minor+1 (all patch and pre-releases versions included)
|
||||||
|
// NB. in semver patches number is a numeric, while prerelease is a string where numeric identifiers always have lower precedence than non-numeric identifiers.
|
||||||
|
// thus setting the value to x.y.0-0 we are defining the very first patch - prereleases within x.y minor release.
|
||||||
|
firstUnsupportedVersion := versionutil.MustParseSemantic(fmt.Sprintf("%d.%d.%s", kadmVersion.Major(), kadmVersion.Minor()+1, "0-0"))
|
||||||
|
if k8sVersion.AtLeast(firstUnsupportedVersion) {
|
||||||
|
return []error{fmt.Errorf("kubernetes version is greater than kubeadm version. Please consider to upgrade kubeadm. kubernetes version: %s. Kubeadm version: %d.%d.x", k8sVersion, kadmVersion.Components()[0], kadmVersion.Components()[1])}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
type etcdVersionResponse struct {
|
type etcdVersionResponse struct {
|
||||||
Etcdserver string `json:"etcdserver"`
|
Etcdserver string `json:"etcdserver"`
|
||||||
Etcdcluster string `json:"etcdcluster"`
|
Etcdcluster string `json:"etcdcluster"`
|
||||||
|
@ -534,6 +571,7 @@ func RunInitMasterChecks(cfg *kubeadmapi.MasterConfiguration) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
checks := []Checker{
|
checks := []Checker{
|
||||||
|
KubernetesVersionCheck{KubernetesVersion: cfg.KubernetesVersion, KubeadmVersion: kubeadmversion.Get().GitVersion},
|
||||||
SystemVerificationCheck{},
|
SystemVerificationCheck{},
|
||||||
IsRootCheck{},
|
IsRootCheck{},
|
||||||
HostnameCheck{nodeName: cfg.NodeName},
|
HostnameCheck{nodeName: cfg.NodeName},
|
||||||
|
|
|
@ -26,7 +26,6 @@ import (
|
||||||
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -180,7 +179,7 @@ func TestRunInitMasterChecks(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
cfg: &kubeadmapi.MasterConfiguration{
|
cfg: &kubeadmapi.MasterConfiguration{
|
||||||
API: kubeadm.API{AdvertiseAddress: "foo"},
|
API: kubeadmapi.API{AdvertiseAddress: "foo"},
|
||||||
},
|
},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
|
@ -347,3 +346,66 @@ func TestConfigCertAndKey(t *testing.T) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKubernetesVersionCheck(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
check KubernetesVersionCheck
|
||||||
|
expectWarnings bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
check: KubernetesVersionCheck{
|
||||||
|
KubeadmVersion: "v1.6.6", //Same version
|
||||||
|
KubernetesVersion: "v1.6.6",
|
||||||
|
},
|
||||||
|
expectWarnings: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
check: KubernetesVersionCheck{
|
||||||
|
KubeadmVersion: "v1.6.6", //KubernetesVersion version older than KubeadmVersion
|
||||||
|
KubernetesVersion: "v1.5.5",
|
||||||
|
},
|
||||||
|
expectWarnings: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
check: KubernetesVersionCheck{
|
||||||
|
KubeadmVersion: "v1.6.6", //KubernetesVersion newer than KubeadmVersion, within the same minor release (new patch)
|
||||||
|
KubernetesVersion: "v1.6.7",
|
||||||
|
},
|
||||||
|
expectWarnings: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
check: KubernetesVersionCheck{
|
||||||
|
KubeadmVersion: "v1.6.6", //KubernetesVersion newer than KubeadmVersion, in a different minor/in pre-release
|
||||||
|
KubernetesVersion: "v1.7.0-alpha.0",
|
||||||
|
},
|
||||||
|
expectWarnings: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
check: KubernetesVersionCheck{
|
||||||
|
KubeadmVersion: "v1.6.6", //KubernetesVersion newer than KubeadmVersion, in a different minor/stable
|
||||||
|
KubernetesVersion: "v1.7.0",
|
||||||
|
},
|
||||||
|
expectWarnings: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
check: KubernetesVersionCheck{
|
||||||
|
KubeadmVersion: "v0.0.0", //"super-custom" builds - Skip this check
|
||||||
|
KubernetesVersion: "v1.7.0",
|
||||||
|
},
|
||||||
|
expectWarnings: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rt := range tests {
|
||||||
|
warning, _ := rt.check.Check()
|
||||||
|
if (warning != nil) != rt.expectWarnings {
|
||||||
|
t.Errorf(
|
||||||
|
"failed KubernetesVersionCheck:\n\texpected: %t\n\t actual: %t (KubeadmVersion:%s, KubernetesVersion: %s)",
|
||||||
|
rt.expectWarnings,
|
||||||
|
(warning != nil),
|
||||||
|
rt.check.KubeadmVersion,
|
||||||
|
rt.check.KubernetesVersion,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -121,11 +121,39 @@ func MustParseSemantic(str string) *Version {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Major returns the major release number
|
||||||
|
func (v *Version) Major() uint {
|
||||||
|
return v.components[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor returns the minor release number
|
||||||
|
func (v *Version) Minor() uint {
|
||||||
|
return v.components[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Patch returns the patch release number if v is a Semantic Version, or 0
|
||||||
|
func (v *Version) Patch() uint {
|
||||||
|
if len(v.components) < 3 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return v.components[2]
|
||||||
|
}
|
||||||
|
|
||||||
// BuildMetadata returns the build metadata, if v is a Semantic Version, or ""
|
// BuildMetadata returns the build metadata, if v is a Semantic Version, or ""
|
||||||
func (v *Version) BuildMetadata() string {
|
func (v *Version) BuildMetadata() string {
|
||||||
return v.buildMetadata
|
return v.buildMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PreRelease returns the prerelease metadata, if v is a Semantic Version, or ""
|
||||||
|
func (v *Version) PreRelease() string {
|
||||||
|
return v.preRelease
|
||||||
|
}
|
||||||
|
|
||||||
|
// Components returns the version number components
|
||||||
|
func (v *Version) Components() []uint {
|
||||||
|
return v.components
|
||||||
|
}
|
||||||
|
|
||||||
// String converts a Version back to a string; note that for versions parsed with
|
// String converts a Version back to a string; note that for versions parsed with
|
||||||
// ParseGeneric, this will not include the trailing uninterpreted portion of the version
|
// ParseGeneric, this will not include the trailing uninterpreted portion of the version
|
||||||
// number.
|
// number.
|
||||||
|
|
|
@ -18,6 +18,7 @@ package version
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -257,3 +258,75 @@ func TestBadGenericVersions(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestComponents(t *testing.T) {
|
||||||
|
|
||||||
|
var tests = []struct {
|
||||||
|
version string
|
||||||
|
semver bool
|
||||||
|
expectedComponents []uint
|
||||||
|
expectedMajor uint
|
||||||
|
expectedMinor uint
|
||||||
|
expectedPatch uint
|
||||||
|
expectedPreRelease string
|
||||||
|
expectedBuildMetadata string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
version: "1.0.2",
|
||||||
|
semver: true,
|
||||||
|
expectedComponents: []uint{1, 0, 2},
|
||||||
|
expectedMajor: 1,
|
||||||
|
expectedMinor: 0,
|
||||||
|
expectedPatch: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.0.2-alpha+001",
|
||||||
|
semver: true,
|
||||||
|
expectedComponents: []uint{1, 0, 2},
|
||||||
|
expectedMajor: 1,
|
||||||
|
expectedMinor: 0,
|
||||||
|
expectedPatch: 2,
|
||||||
|
expectedPreRelease: "alpha",
|
||||||
|
expectedBuildMetadata: "001",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.2",
|
||||||
|
semver: false,
|
||||||
|
expectedComponents: []uint{1, 2},
|
||||||
|
expectedMajor: 1,
|
||||||
|
expectedMinor: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.0.2-beta+exp.sha.5114f85",
|
||||||
|
semver: true,
|
||||||
|
expectedComponents: []uint{1, 0, 2},
|
||||||
|
expectedMajor: 1,
|
||||||
|
expectedMinor: 0,
|
||||||
|
expectedPatch: 2,
|
||||||
|
expectedPreRelease: "beta",
|
||||||
|
expectedBuildMetadata: "exp.sha.5114f85",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
version, _ := parse(test.version, test.semver)
|
||||||
|
if !reflect.DeepEqual(test.expectedComponents, version.Components()) {
|
||||||
|
t.Error("parse returned un'expected components")
|
||||||
|
}
|
||||||
|
if test.expectedMajor != version.Major() {
|
||||||
|
t.Errorf("parse returned version.Major %d, expected %d", test.expectedMajor, version.Major())
|
||||||
|
}
|
||||||
|
if test.expectedMinor != version.Minor() {
|
||||||
|
t.Errorf("parse returned version.Minor %d, expected %d", test.expectedMinor, version.Minor())
|
||||||
|
}
|
||||||
|
if test.expectedPatch != version.Patch() {
|
||||||
|
t.Errorf("parse returned version.Patch %d, expected %d", test.expectedPatch, version.Patch())
|
||||||
|
}
|
||||||
|
if test.expectedPreRelease != version.PreRelease() {
|
||||||
|
t.Errorf("parse returned version.PreRelease %s, expected %s", test.expectedPreRelease, version.PreRelease())
|
||||||
|
}
|
||||||
|
if test.expectedBuildMetadata != version.BuildMetadata() {
|
||||||
|
t.Errorf("parse returned version.BuildMetadata %s, expected %s", test.expectedBuildMetadata, version.BuildMetadata())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue