mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 11:21:47 +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 = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm: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"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||
@ -435,21 +436,45 @@ var (
|
||||
)
|
||||
|
||||
// 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
|
||||
func EtcdSupportedVersion(versionString string) (*version.Version, error) {
|
||||
// If passed version is not in the given list, the function returns the nearest version with a warning
|
||||
func EtcdSupportedVersion(supportedEtcdVersion map[uint8]string, versionString string) (etcdVersion *version.Version, warning, err error) {
|
||||
kubernetesVersion, err := version.ParseSemantic(versionString)
|
||||
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 {
|
||||
etcdVersion, err := version.ParseSemantic(etcdStringVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if len(etcdStringVersion) == 0 {
|
||||
if desiredVersion < min {
|
||||
etcdStringVersion = supportedEtcdVersion[min]
|
||||
}
|
||||
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
|
||||
|
@ -18,11 +18,8 @@ package constants
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
@ -149,50 +146,62 @@ func TestAddSelfHostedPrefix(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 {
|
||||
kubernetesVersion string
|
||||
expectedVersion *version.Version
|
||||
expectedError error
|
||||
expectedWarning bool
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
kubernetesVersion: "1.99.0",
|
||||
kubernetesVersion: "1.x.1",
|
||||
expectedVersion: nil,
|
||||
expectedError: errors.New("unsupported or unknown Kubernetes version(1.99.0)"),
|
||||
expectedWarning: false,
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
kubernetesVersion: MinimumControlPlaneVersion.WithPatch(1).String(),
|
||||
expectedVersion: version.MustParseSemantic(SupportedEtcdVersion[uint8(MinimumControlPlaneVersion.Minor())]),
|
||||
expectedError: nil,
|
||||
kubernetesVersion: "1.10.1",
|
||||
expectedVersion: version.MustParseSemantic("3.2.24"),
|
||||
expectedWarning: true,
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
kubernetesVersion: CurrentKubernetesVersion.String(),
|
||||
expectedVersion: version.MustParseSemantic(SupportedEtcdVersion[uint8(CurrentKubernetesVersion.Minor())]),
|
||||
expectedError: nil,
|
||||
kubernetesVersion: "1.99.0",
|
||||
expectedVersion: version.MustParseSemantic("3.4.3-0"),
|
||||
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 {
|
||||
t.Run(rt.kubernetesVersion, func(t *testing.T) {
|
||||
actualVersion, actualError := EtcdSupportedVersion(rt.kubernetesVersion)
|
||||
if actualError != nil {
|
||||
if rt.expectedError == nil {
|
||||
t.Errorf("failed EtcdSupportedVersion:\n\texpected no error, but got: %v", actualError)
|
||||
} else if actualError.Error() != rt.expectedError.Error() {
|
||||
t.Errorf(
|
||||
"failed EtcdSupportedVersion:\n\texpected error: %v\n\t actual error: %v",
|
||||
rt.expectedError,
|
||||
actualError,
|
||||
)
|
||||
}
|
||||
} 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(),
|
||||
)
|
||||
}
|
||||
actualVersion, actualWarning, actualError := EtcdSupportedVersion(supportedEtcdVersion, rt.kubernetesVersion)
|
||||
if (actualError != nil) != rt.expectedError {
|
||||
t.Fatalf("expected error %v, got %v", rt.expectedError, actualError != nil)
|
||||
}
|
||||
if (actualWarning != nil) != rt.expectedWarning {
|
||||
t.Fatalf("expected warning %v, got %v", rt.expectedWarning, actualWarning != nil)
|
||||
}
|
||||
if actualError == nil && actualVersion.String() != rt.expectedVersion.String() {
|
||||
t.Errorf("expected version %s, got %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
|
||||
etcdImageTag := constants.DefaultEtcdVersion
|
||||
etcdVersion, err := constants.EtcdSupportedVersion(cfg.KubernetesVersion)
|
||||
etcdVersion, warning, err := constants.EtcdSupportedVersion(constants.SupportedEtcdVersion, cfg.KubernetesVersion)
|
||||
if err == nil {
|
||||
etcdImageTag = etcdVersion.String()
|
||||
}
|
||||
if warning != nil {
|
||||
klog.Warningln(warning)
|
||||
}
|
||||
// unless an override is specified
|
||||
if cfg.Etcd.Local != nil && cfg.Etcd.Local.ImageTag != "" {
|
||||
etcdImageTag = cfg.Etcd.Local.ImageTag
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
|
||||
versionutil "k8s.io/apimachinery/pkg/util/version"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
|
||||
@ -300,10 +301,13 @@ func minorUpgradePossibleWithPatchRelease(stableVersion, patchVersion *versionut
|
||||
}
|
||||
|
||||
func getSuggestedEtcdVersion(kubernetesVersion string) string {
|
||||
etcdVersion, err := kubeadmconstants.EtcdSupportedVersion(kubernetesVersion)
|
||||
etcdVersion, warning, err := kubeadmconstants.EtcdSupportedVersion(kubeadmconstants.SupportedEtcdVersion, kubernetesVersion)
|
||||
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"
|
||||
}
|
||||
if warning != nil {
|
||||
klog.Warningf("[upgrade/versions] %v", warning)
|
||||
}
|
||||
return etcdVersion.String()
|
||||
}
|
||||
|
@ -24,9 +24,11 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
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
|
||||
desiredEtcdVersion, err := constants.EtcdSupportedVersion(cfg.KubernetesVersion)
|
||||
desiredEtcdVersion, warning, err := constants.EtcdSupportedVersion(constants.SupportedEtcdVersion, cfg.KubernetesVersion)
|
||||
if err != nil {
|
||||
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
|
||||
currentEtcdVersions, err := oldEtcdClient.GetClusterVersions()
|
||||
|
Loading…
Reference in New Issue
Block a user