mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
kubeadm: fallback to a known etcd version if an unknown k8s version is passed
This commit is contained in:
parent
acd97b42f3
commit
2e23f84745
@ -44,6 +44,5 @@ go_test(
|
|||||||
deps = [
|
deps = [
|
||||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
|
||||||
"//vendor/github.com/pkg/errors:go_default_library",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||||
@ -435,21 +436,45 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// EtcdSupportedVersion returns officially supported version of etcd for a specific Kubernetes release
|
// EtcdSupportedVersion returns officially supported version of etcd for a specific Kubernetes release
|
||||||
// if passed version is not listed, the function returns nil and an error
|
// If passed version is not in the given list, the function returns the nearest version with a warning
|
||||||
func EtcdSupportedVersion(versionString string) (*version.Version, error) {
|
func EtcdSupportedVersion(supportedEtcdVersion map[uint8]string, versionString string) (etcdVersion *version.Version, warning, err error) {
|
||||||
kubernetesVersion, err := version.ParseSemantic(versionString)
|
kubernetesVersion, err := version.ParseSemantic(versionString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
desiredVersion, etcdStringVersion := uint8(kubernetesVersion.Minor()), ""
|
||||||
|
|
||||||
|
min, max := ^uint8(0), uint8(0)
|
||||||
|
for k, v := range supportedEtcdVersion {
|
||||||
|
if desiredVersion == k {
|
||||||
|
etcdStringVersion = v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if k < min {
|
||||||
|
min = k
|
||||||
|
}
|
||||||
|
if k > max {
|
||||||
|
max = k
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if etcdStringVersion, ok := SupportedEtcdVersion[uint8(kubernetesVersion.Minor())]; ok {
|
if len(etcdStringVersion) == 0 {
|
||||||
etcdVersion, err := version.ParseSemantic(etcdStringVersion)
|
if desiredVersion < min {
|
||||||
if err != nil {
|
etcdStringVersion = supportedEtcdVersion[min]
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
return etcdVersion, nil
|
if desiredVersion > max {
|
||||||
|
etcdStringVersion = supportedEtcdVersion[max]
|
||||||
|
}
|
||||||
|
warning = fmt.Errorf("could not find officially supported version of etcd for Kubernetes %s, falling back to the nearest etcd version (%s)",
|
||||||
|
versionString, etcdStringVersion)
|
||||||
}
|
}
|
||||||
return nil, errors.Errorf("unsupported or unknown Kubernetes version(%v)", kubernetesVersion)
|
|
||||||
|
etcdVersion, err = version.ParseSemantic(etcdStringVersion)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return etcdVersion, warning, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStaticPodDirectory returns the location on the disk where the Static Pod should be present
|
// GetStaticPodDirectory returns the location on the disk where the Static Pod should be present
|
||||||
|
@ -18,11 +18,8 @@ package constants
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
)
|
)
|
||||||
@ -149,50 +146,62 @@ func TestAddSelfHostedPrefix(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEtcdSupportedVersion(t *testing.T) {
|
func TestEtcdSupportedVersion(t *testing.T) {
|
||||||
|
var supportedEtcdVersion = map[uint8]string{
|
||||||
|
13: "3.2.24",
|
||||||
|
14: "3.3.10",
|
||||||
|
15: "3.3.10",
|
||||||
|
16: "3.3.17-0",
|
||||||
|
17: "3.4.3-0",
|
||||||
|
18: "3.4.3-0",
|
||||||
|
}
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
kubernetesVersion string
|
kubernetesVersion string
|
||||||
expectedVersion *version.Version
|
expectedVersion *version.Version
|
||||||
expectedError error
|
expectedWarning bool
|
||||||
|
expectedError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
kubernetesVersion: "1.99.0",
|
kubernetesVersion: "1.x.1",
|
||||||
expectedVersion: nil,
|
expectedVersion: nil,
|
||||||
expectedError: errors.New("unsupported or unknown Kubernetes version(1.99.0)"),
|
expectedWarning: false,
|
||||||
|
expectedError: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
kubernetesVersion: MinimumControlPlaneVersion.WithPatch(1).String(),
|
kubernetesVersion: "1.10.1",
|
||||||
expectedVersion: version.MustParseSemantic(SupportedEtcdVersion[uint8(MinimumControlPlaneVersion.Minor())]),
|
expectedVersion: version.MustParseSemantic("3.2.24"),
|
||||||
expectedError: nil,
|
expectedWarning: true,
|
||||||
|
expectedError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
kubernetesVersion: CurrentKubernetesVersion.String(),
|
kubernetesVersion: "1.99.0",
|
||||||
expectedVersion: version.MustParseSemantic(SupportedEtcdVersion[uint8(CurrentKubernetesVersion.Minor())]),
|
expectedVersion: version.MustParseSemantic("3.4.3-0"),
|
||||||
expectedError: nil,
|
expectedWarning: true,
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kubernetesVersion: "v1.16.0",
|
||||||
|
expectedVersion: version.MustParseSemantic("3.3.17-0"),
|
||||||
|
expectedWarning: false,
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kubernetesVersion: "1.17.2",
|
||||||
|
expectedVersion: version.MustParseSemantic("3.4.3-0"),
|
||||||
|
expectedWarning: false,
|
||||||
|
expectedError: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
t.Run(rt.kubernetesVersion, func(t *testing.T) {
|
t.Run(rt.kubernetesVersion, func(t *testing.T) {
|
||||||
actualVersion, actualError := EtcdSupportedVersion(rt.kubernetesVersion)
|
actualVersion, actualWarning, actualError := EtcdSupportedVersion(supportedEtcdVersion, rt.kubernetesVersion)
|
||||||
if actualError != nil {
|
if (actualError != nil) != rt.expectedError {
|
||||||
if rt.expectedError == nil {
|
t.Fatalf("expected error %v, got %v", rt.expectedError, actualError != nil)
|
||||||
t.Errorf("failed EtcdSupportedVersion:\n\texpected no error, but got: %v", actualError)
|
}
|
||||||
} else if actualError.Error() != rt.expectedError.Error() {
|
if (actualWarning != nil) != rt.expectedWarning {
|
||||||
t.Errorf(
|
t.Fatalf("expected warning %v, got %v", rt.expectedWarning, actualWarning != nil)
|
||||||
"failed EtcdSupportedVersion:\n\texpected error: %v\n\t actual error: %v",
|
}
|
||||||
rt.expectedError,
|
if actualError == nil && actualVersion.String() != rt.expectedVersion.String() {
|
||||||
actualError,
|
t.Errorf("expected version %s, got %s", rt.expectedVersion.String(), actualVersion.String())
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if rt.expectedError != nil {
|
|
||||||
t.Errorf("failed EtcdSupportedVersion:\n\texpected error: %v, but got no error", rt.expectedError)
|
|
||||||
} else if strings.Compare(actualVersion.String(), rt.expectedVersion.String()) != 0 {
|
|
||||||
t.Errorf(
|
|
||||||
"failed EtcdSupportedVersion:\n\texpected version: %s\n\t actual version: %s",
|
|
||||||
rt.expectedVersion.String(),
|
|
||||||
actualVersion.String(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -73,10 +73,13 @@ func GetEtcdImage(cfg *kubeadmapi.ClusterConfiguration) string {
|
|||||||
}
|
}
|
||||||
// Etcd uses an imageTag that corresponds to the etcd version matching the Kubernetes version
|
// Etcd uses an imageTag that corresponds to the etcd version matching the Kubernetes version
|
||||||
etcdImageTag := constants.DefaultEtcdVersion
|
etcdImageTag := constants.DefaultEtcdVersion
|
||||||
etcdVersion, err := constants.EtcdSupportedVersion(cfg.KubernetesVersion)
|
etcdVersion, warning, err := constants.EtcdSupportedVersion(constants.SupportedEtcdVersion, cfg.KubernetesVersion)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
etcdImageTag = etcdVersion.String()
|
etcdImageTag = etcdVersion.String()
|
||||||
}
|
}
|
||||||
|
if warning != nil {
|
||||||
|
klog.Warningln(warning)
|
||||||
|
}
|
||||||
// unless an override is specified
|
// unless an override is specified
|
||||||
if cfg.Etcd.Local != nil && cfg.Etcd.Local.ImageTag != "" {
|
if cfg.Etcd.Local != nil && cfg.Etcd.Local.ImageTag != "" {
|
||||||
etcdImageTag = cfg.Etcd.Local.ImageTag
|
etcdImageTag = cfg.Etcd.Local.ImageTag
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
versionutil "k8s.io/apimachinery/pkg/util/version"
|
versionutil "k8s.io/apimachinery/pkg/util/version"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
|
||||||
@ -300,10 +301,13 @@ func minorUpgradePossibleWithPatchRelease(stableVersion, patchVersion *versionut
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getSuggestedEtcdVersion(kubernetesVersion string) string {
|
func getSuggestedEtcdVersion(kubernetesVersion string) string {
|
||||||
etcdVersion, err := kubeadmconstants.EtcdSupportedVersion(kubernetesVersion)
|
etcdVersion, warning, err := kubeadmconstants.EtcdSupportedVersion(kubeadmconstants.SupportedEtcdVersion, kubernetesVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("[upgrade/versions] WARNING: No recommended etcd for requested Kubernetes version (%s)\n", kubernetesVersion)
|
klog.Warningf("[upgrade/versions] could not retrieve an etcd version for the target Kubernetes version: %v", err)
|
||||||
return "N/A"
|
return "N/A"
|
||||||
}
|
}
|
||||||
|
if warning != nil {
|
||||||
|
klog.Warningf("[upgrade/versions] %v", warning)
|
||||||
|
}
|
||||||
return etcdVersion.String()
|
return etcdVersion.String()
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,11 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||||
@ -281,10 +283,13 @@ func performEtcdStaticPodUpgrade(certsRenewMgr *renewal.Manager, client clientse
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Need to check currently used version and version from constants, if differs then upgrade
|
// Need to check currently used version and version from constants, if differs then upgrade
|
||||||
desiredEtcdVersion, err := constants.EtcdSupportedVersion(cfg.KubernetesVersion)
|
desiredEtcdVersion, warning, err := constants.EtcdSupportedVersion(constants.SupportedEtcdVersion, cfg.KubernetesVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, errors.Wrap(err, "failed to retrieve an etcd version for the target Kubernetes version")
|
return true, errors.Wrap(err, "failed to retrieve an etcd version for the target Kubernetes version")
|
||||||
}
|
}
|
||||||
|
if warning != nil {
|
||||||
|
klog.Warningf("[upgrade/etcd] %v", warning)
|
||||||
|
}
|
||||||
|
|
||||||
// gets the etcd version of the local/stacked etcd member running on the current machine
|
// gets the etcd version of the local/stacked etcd member running on the current machine
|
||||||
currentEtcdVersions, err := oldEtcdClient.GetClusterVersions()
|
currentEtcdVersions, err := oldEtcdClient.GetClusterVersions()
|
||||||
|
Loading…
Reference in New Issue
Block a user