Skip to content

Commit 20e3288

Browse files
authored
Merge pull request kubernetes#88373 from SataQiu/fix-kubeadm-20200220
kubeadm: fallback to a known etcd version if an unknown k8s version is passed
2 parents ca23b07 + 2e23f84 commit 20e3288

File tree

6 files changed

+92
-47
lines changed

6 files changed

+92
-47
lines changed

cmd/kubeadm/app/constants/BUILD

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,5 @@ go_test(
4545
deps = [
4646
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
4747
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
48-
"//vendor/github.com/pkg/errors:go_default_library",
4948
],
5049
)

cmd/kubeadm/app/constants/constants.go

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"time"
2828

2929
"github.com/pkg/errors"
30+
3031
v1 "k8s.io/api/core/v1"
3132
"k8s.io/apimachinery/pkg/util/version"
3233
"k8s.io/apimachinery/pkg/util/wait"
@@ -456,21 +457,45 @@ var (
456457
)
457458

458459
// EtcdSupportedVersion returns officially supported version of etcd for a specific Kubernetes release
459-
// if passed version is not listed, the function returns nil and an error
460-
func EtcdSupportedVersion(versionString string) (*version.Version, error) {
460+
// If passed version is not in the given list, the function returns the nearest version with a warning
461+
func EtcdSupportedVersion(supportedEtcdVersion map[uint8]string, versionString string) (etcdVersion *version.Version, warning, err error) {
461462
kubernetesVersion, err := version.ParseSemantic(versionString)
462463
if err != nil {
463-
return nil, err
464+
return nil, nil, err
464465
}
466+
desiredVersion, etcdStringVersion := uint8(kubernetesVersion.Minor()), ""
465467

466-
if etcdStringVersion, ok := SupportedEtcdVersion[uint8(kubernetesVersion.Minor())]; ok {
467-
etcdVersion, err := version.ParseSemantic(etcdStringVersion)
468-
if err != nil {
469-
return nil, err
468+
min, max := ^uint8(0), uint8(0)
469+
for k, v := range supportedEtcdVersion {
470+
if desiredVersion == k {
471+
etcdStringVersion = v
472+
break
473+
}
474+
if k < min {
475+
min = k
476+
}
477+
if k > max {
478+
max = k
479+
}
480+
}
481+
482+
if len(etcdStringVersion) == 0 {
483+
if desiredVersion < min {
484+
etcdStringVersion = supportedEtcdVersion[min]
485+
}
486+
if desiredVersion > max {
487+
etcdStringVersion = supportedEtcdVersion[max]
470488
}
471-
return etcdVersion, nil
489+
warning = fmt.Errorf("could not find officially supported version of etcd for Kubernetes %s, falling back to the nearest etcd version (%s)",
490+
versionString, etcdStringVersion)
491+
}
492+
493+
etcdVersion, err = version.ParseSemantic(etcdStringVersion)
494+
if err != nil {
495+
return nil, nil, err
472496
}
473-
return nil, errors.Errorf("unsupported or unknown Kubernetes version(%v)", kubernetesVersion)
497+
498+
return etcdVersion, warning, nil
474499
}
475500

476501
// GetStaticPodDirectory returns the location on the disk where the Static Pod should be present

cmd/kubeadm/app/constants/constants_test.go

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,8 @@ package constants
1818

1919
import (
2020
"path/filepath"
21-
"strings"
2221
"testing"
2322

24-
"github.com/pkg/errors"
25-
2623
"k8s.io/apimachinery/pkg/util/version"
2724
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
2825
)
@@ -149,50 +146,62 @@ func TestAddSelfHostedPrefix(t *testing.T) {
149146
}
150147

151148
func TestEtcdSupportedVersion(t *testing.T) {
149+
var supportedEtcdVersion = map[uint8]string{
150+
13: "3.2.24",
151+
14: "3.3.10",
152+
15: "3.3.10",
153+
16: "3.3.17-0",
154+
17: "3.4.3-0",
155+
18: "3.4.3-0",
156+
}
152157
var tests = []struct {
153158
kubernetesVersion string
154159
expectedVersion *version.Version
155-
expectedError error
160+
expectedWarning bool
161+
expectedError bool
156162
}{
157163
{
158-
kubernetesVersion: "1.99.0",
164+
kubernetesVersion: "1.x.1",
159165
expectedVersion: nil,
160-
expectedError: errors.New("unsupported or unknown Kubernetes version(1.99.0)"),
166+
expectedWarning: false,
167+
expectedError: true,
161168
},
162169
{
163-
kubernetesVersion: MinimumControlPlaneVersion.WithPatch(1).String(),
164-
expectedVersion: version.MustParseSemantic(SupportedEtcdVersion[uint8(MinimumControlPlaneVersion.Minor())]),
165-
expectedError: nil,
170+
kubernetesVersion: "1.10.1",
171+
expectedVersion: version.MustParseSemantic("3.2.24"),
172+
expectedWarning: true,
173+
expectedError: false,
166174
},
167175
{
168-
kubernetesVersion: CurrentKubernetesVersion.String(),
169-
expectedVersion: version.MustParseSemantic(SupportedEtcdVersion[uint8(CurrentKubernetesVersion.Minor())]),
170-
expectedError: nil,
176+
kubernetesVersion: "1.99.0",
177+
expectedVersion: version.MustParseSemantic("3.4.3-0"),
178+
expectedWarning: true,
179+
expectedError: false,
180+
},
181+
{
182+
kubernetesVersion: "v1.16.0",
183+
expectedVersion: version.MustParseSemantic("3.3.17-0"),
184+
expectedWarning: false,
185+
expectedError: false,
186+
},
187+
{
188+
kubernetesVersion: "1.17.2",
189+
expectedVersion: version.MustParseSemantic("3.4.3-0"),
190+
expectedWarning: false,
191+
expectedError: false,
171192
},
172193
}
173194
for _, rt := range tests {
174195
t.Run(rt.kubernetesVersion, func(t *testing.T) {
175-
actualVersion, actualError := EtcdSupportedVersion(rt.kubernetesVersion)
176-
if actualError != nil {
177-
if rt.expectedError == nil {
178-
t.Errorf("failed EtcdSupportedVersion:\n\texpected no error, but got: %v", actualError)
179-
} else if actualError.Error() != rt.expectedError.Error() {
180-
t.Errorf(
181-
"failed EtcdSupportedVersion:\n\texpected error: %v\n\t actual error: %v",
182-
rt.expectedError,
183-
actualError,
184-
)
185-
}
186-
} else {
187-
if rt.expectedError != nil {
188-
t.Errorf("failed EtcdSupportedVersion:\n\texpected error: %v, but got no error", rt.expectedError)
189-
} else if strings.Compare(actualVersion.String(), rt.expectedVersion.String()) != 0 {
190-
t.Errorf(
191-
"failed EtcdSupportedVersion:\n\texpected version: %s\n\t actual version: %s",
192-
rt.expectedVersion.String(),
193-
actualVersion.String(),
194-
)
195-
}
196+
actualVersion, actualWarning, actualError := EtcdSupportedVersion(supportedEtcdVersion, rt.kubernetesVersion)
197+
if (actualError != nil) != rt.expectedError {
198+
t.Fatalf("expected error %v, got %v", rt.expectedError, actualError != nil)
199+
}
200+
if (actualWarning != nil) != rt.expectedWarning {
201+
t.Fatalf("expected warning %v, got %v", rt.expectedWarning, actualWarning != nil)
202+
}
203+
if actualError == nil && actualVersion.String() != rt.expectedVersion.String() {
204+
t.Errorf("expected version %s, got %s", rt.expectedVersion.String(), actualVersion.String())
196205
}
197206
})
198207
}

cmd/kubeadm/app/images/images.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,13 @@ func GetEtcdImage(cfg *kubeadmapi.ClusterConfiguration) string {
7373
}
7474
// Etcd uses an imageTag that corresponds to the etcd version matching the Kubernetes version
7575
etcdImageTag := constants.DefaultEtcdVersion
76-
etcdVersion, err := constants.EtcdSupportedVersion(cfg.KubernetesVersion)
76+
etcdVersion, warning, err := constants.EtcdSupportedVersion(constants.SupportedEtcdVersion, cfg.KubernetesVersion)
7777
if err == nil {
7878
etcdImageTag = etcdVersion.String()
7979
}
80+
if warning != nil {
81+
klog.Warningln(warning)
82+
}
8083
// unless an override is specified
8184
if cfg.Etcd.Local != nil && cfg.Etcd.Local.ImageTag != "" {
8285
etcdImageTag = cfg.Etcd.Local.ImageTag

cmd/kubeadm/app/phases/upgrade/compute.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
versionutil "k8s.io/apimachinery/pkg/util/version"
2424
clientset "k8s.io/client-go/kubernetes"
25+
"k8s.io/klog"
2526
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
2627
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
2728
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
@@ -300,10 +301,13 @@ func minorUpgradePossibleWithPatchRelease(stableVersion, patchVersion *versionut
300301
}
301302

302303
func getSuggestedEtcdVersion(kubernetesVersion string) string {
303-
etcdVersion, err := kubeadmconstants.EtcdSupportedVersion(kubernetesVersion)
304+
etcdVersion, warning, err := kubeadmconstants.EtcdSupportedVersion(kubeadmconstants.SupportedEtcdVersion, kubernetesVersion)
304305
if err != nil {
305-
fmt.Printf("[upgrade/versions] WARNING: No recommended etcd for requested Kubernetes version (%s)\n", kubernetesVersion)
306+
klog.Warningf("[upgrade/versions] could not retrieve an etcd version for the target Kubernetes version: %v", err)
306307
return "N/A"
307308
}
309+
if warning != nil {
310+
klog.Warningf("[upgrade/versions] %v", warning)
311+
}
308312
return etcdVersion.String()
309313
}

cmd/kubeadm/app/phases/upgrade/staticpods.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ import (
2424
"time"
2525

2626
"github.com/pkg/errors"
27+
2728
utilerrors "k8s.io/apimachinery/pkg/util/errors"
2829
"k8s.io/apimachinery/pkg/util/version"
2930
clientset "k8s.io/client-go/kubernetes"
31+
"k8s.io/klog"
3032
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
3133
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
3234
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
@@ -281,10 +283,13 @@ func performEtcdStaticPodUpgrade(certsRenewMgr *renewal.Manager, client clientse
281283
}
282284

283285
// Need to check currently used version and version from constants, if differs then upgrade
284-
desiredEtcdVersion, err := constants.EtcdSupportedVersion(cfg.KubernetesVersion)
286+
desiredEtcdVersion, warning, err := constants.EtcdSupportedVersion(constants.SupportedEtcdVersion, cfg.KubernetesVersion)
285287
if err != nil {
286288
return true, errors.Wrap(err, "failed to retrieve an etcd version for the target Kubernetes version")
287289
}
290+
if warning != nil {
291+
klog.Warningf("[upgrade/etcd] %v", warning)
292+
}
288293

289294
// gets the etcd version of the local/stacked etcd member running on the current machine
290295
currentEtcdVersions, err := oldEtcdClient.GetClusterVersions()

0 commit comments

Comments
 (0)