From a9ea1b881bd53d377ef7158291fd8d9731c18f17 Mon Sep 17 00:00:00 2001 From: Serguei Bezverkhi Date: Tue, 21 Nov 2017 12:30:36 -0500 Subject: [PATCH] Adding etcd version for kubeadm upgrade plan --- cmd/kubeadm/app/cmd/upgrade/plan.go | 5 +- cmd/kubeadm/app/cmd/upgrade/plan_test.go | 182 ++++++----- cmd/kubeadm/app/constants/constants.go | 5 +- cmd/kubeadm/app/constants/constants_test.go | 4 +- cmd/kubeadm/app/phases/upgrade/BUILD | 1 + cmd/kubeadm/app/phases/upgrade/compute.go | 26 +- .../app/phases/upgrade/compute_test.go | 305 ++++++++++-------- cmd/kubeadm/app/phases/upgrade/staticpods.go | 5 +- cmd/kubeadm/app/util/etcd.go | 10 +- 9 files changed, 315 insertions(+), 228 deletions(-) diff --git a/cmd/kubeadm/app/cmd/upgrade/plan.go b/cmd/kubeadm/app/cmd/upgrade/plan.go index 43b74d5174..1d412a47af 100644 --- a/cmd/kubeadm/app/cmd/upgrade/plan.go +++ b/cmd/kubeadm/app/cmd/upgrade/plan.go @@ -56,8 +56,10 @@ func RunPlan(parentFlags *cmdUpgradeFlags) error { return err } + // Define Local Etcd cluster to be able to retrieve information + etcdCluster := kubeadmutil.LocalEtcdCluster{} // Compute which upgrade possibilities there are - availUpgrades, err := upgrade.GetAvailableUpgrades(upgradeVars.versionGetter, parentFlags.allowExperimentalUpgrades, parentFlags.allowRCUpgrades) + availUpgrades, err := upgrade.GetAvailableUpgrades(upgradeVars.versionGetter, parentFlags.allowExperimentalUpgrades, parentFlags.allowRCUpgrades, etcdCluster) if err != nil { return fmt.Errorf("[upgrade/versions] FATAL: %v", err) } @@ -112,6 +114,7 @@ func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer) { fmt.Fprintf(tabw, "Scheduler\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion) fmt.Fprintf(tabw, "Kube Proxy\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion) fmt.Fprintf(tabw, "Kube DNS\t%s\t%s\n", upgrade.Before.DNSVersion, upgrade.After.DNSVersion) + fmt.Fprintf(tabw, "Etcd\t%s\t%s\n", upgrade.Before.EtcdVersion, upgrade.After.EtcdVersion) // The tabwriter should be flushed at this stage as we have now put in all the required content for this time. This is required for the tabs' size to be correct. tabw.Flush() diff --git a/cmd/kubeadm/app/cmd/upgrade/plan_test.go b/cmd/kubeadm/app/cmd/upgrade/plan_test.go index 4ad5b75ed3..95fbcc2505 100644 --- a/cmd/kubeadm/app/cmd/upgrade/plan_test.go +++ b/cmd/kubeadm/app/cmd/upgrade/plan_test.go @@ -73,40 +73,43 @@ func TestPrintAvailableUpgrades(t *testing.T) { { upgrades: []upgrade.Upgrade{ { - Description: "version in the v1.7 series", + Description: "version in the v1.8 series", Before: upgrade.ClusterState{ - KubeVersion: "v1.7.1", + KubeVersion: "v1.8.1", KubeletVersions: map[string]uint16{ - "v1.7.1": 1, + "v1.8.1": 1, }, - KubeadmVersion: "v1.7.2", + KubeadmVersion: "v1.8.2", DNSVersion: "1.14.5", + EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ - KubeVersion: "v1.7.3", - KubeadmVersion: "v1.7.3", + KubeVersion: "v1.8.3", + KubeadmVersion: "v1.8.3", DNSVersion: "1.14.5", + EtcdVersion: "3.0.17", }, }, }, expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': COMPONENT CURRENT AVAILABLE -Kubelet 1 x v1.7.1 v1.7.3 +Kubelet 1 x v1.8.1 v1.8.3 -Upgrade to the latest version in the v1.7 series: +Upgrade to the latest version in the v1.8 series: COMPONENT CURRENT AVAILABLE -API Server v1.7.1 v1.7.3 -Controller Manager v1.7.1 v1.7.3 -Scheduler v1.7.1 v1.7.3 -Kube Proxy v1.7.1 v1.7.3 +API Server v1.8.1 v1.8.3 +Controller Manager v1.8.1 v1.8.3 +Scheduler v1.8.1 v1.8.3 +Kube Proxy v1.8.1 v1.8.3 Kube DNS 1.14.5 1.14.5 +Etcd 3.0.17 3.0.17 You can now apply the upgrade by executing the following command: - kubeadm upgrade apply v1.7.3 + kubeadm upgrade apply v1.8.3 -Note: Before you can perform this upgrade, you have to update kubeadm to v1.7.3. +Note: Before you can perform this upgrade, you have to update kubeadm to v1.8.3. _____________________________________________________________________ @@ -117,36 +120,39 @@ _____________________________________________________________________ { Description: "stable version", Before: upgrade.ClusterState{ - KubeVersion: "v1.7.3", + KubeVersion: "v1.8.3", KubeletVersions: map[string]uint16{ - "v1.7.3": 1, + "v1.8.3": 1, }, - KubeadmVersion: "v1.8.0", + KubeadmVersion: "v1.9.0", DNSVersion: "1.14.5", + EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ - KubeVersion: "v1.8.0", - KubeadmVersion: "v1.8.0", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.0", + KubeadmVersion: "v1.9.0", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, }, expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': COMPONENT CURRENT AVAILABLE -Kubelet 1 x v1.7.3 v1.8.0 +Kubelet 1 x v1.8.3 v1.9.0 Upgrade to the latest stable version: COMPONENT CURRENT AVAILABLE -API Server v1.7.3 v1.8.0 -Controller Manager v1.7.3 v1.8.0 -Scheduler v1.7.3 v1.8.0 -Kube Proxy v1.7.3 v1.8.0 -Kube DNS 1.14.5 1.14.5 +API Server v1.8.3 v1.9.0 +Controller Manager v1.8.3 v1.9.0 +Scheduler v1.8.3 v1.9.0 +Kube Proxy v1.8.3 v1.9.0 +Kube DNS 1.14.5 1.14.7 +Etcd 3.0.17 3.1.10 You can now apply the upgrade by executing the following command: - kubeadm upgrade apply v1.8.0 + kubeadm upgrade apply v1.9.0 _____________________________________________________________________ @@ -155,75 +161,81 @@ _____________________________________________________________________ { upgrades: []upgrade.Upgrade{ { - Description: "version in the v1.7 series", + Description: "version in the v1.8 series", Before: upgrade.ClusterState{ - KubeVersion: "v1.7.3", + KubeVersion: "v1.8.3", KubeletVersions: map[string]uint16{ - "v1.7.3": 1, + "v1.8.3": 1, }, - KubeadmVersion: "v1.8.1", + KubeadmVersion: "v1.8.3", DNSVersion: "1.14.5", + EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ - KubeVersion: "v1.7.5", - KubeadmVersion: "v1.8.1", + KubeVersion: "v1.8.5", + KubeadmVersion: "v1.8.3", DNSVersion: "1.14.5", + EtcdVersion: "3.0.17", }, }, { Description: "stable version", Before: upgrade.ClusterState{ - KubeVersion: "v1.7.3", + KubeVersion: "v1.8.3", KubeletVersions: map[string]uint16{ - "v1.7.3": 1, + "v1.8.3": 1, }, - KubeadmVersion: "v1.8.1", + KubeadmVersion: "v1.8.3", DNSVersion: "1.14.5", + EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ - KubeVersion: "v1.8.2", - KubeadmVersion: "v1.8.2", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.0", + KubeadmVersion: "v1.9.0", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, }, expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': COMPONENT CURRENT AVAILABLE -Kubelet 1 x v1.7.3 v1.7.5 +Kubelet 1 x v1.8.3 v1.8.5 -Upgrade to the latest version in the v1.7 series: +Upgrade to the latest version in the v1.8 series: COMPONENT CURRENT AVAILABLE -API Server v1.7.3 v1.7.5 -Controller Manager v1.7.3 v1.7.5 -Scheduler v1.7.3 v1.7.5 -Kube Proxy v1.7.3 v1.7.5 +API Server v1.8.3 v1.8.5 +Controller Manager v1.8.3 v1.8.5 +Scheduler v1.8.3 v1.8.5 +Kube Proxy v1.8.3 v1.8.5 Kube DNS 1.14.5 1.14.5 +Etcd 3.0.17 3.0.17 You can now apply the upgrade by executing the following command: - kubeadm upgrade apply v1.7.5 + kubeadm upgrade apply v1.8.5 _____________________________________________________________________ Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': COMPONENT CURRENT AVAILABLE -Kubelet 1 x v1.7.3 v1.8.2 +Kubelet 1 x v1.8.3 v1.9.0 Upgrade to the latest stable version: COMPONENT CURRENT AVAILABLE -API Server v1.7.3 v1.8.2 -Controller Manager v1.7.3 v1.8.2 -Scheduler v1.7.3 v1.8.2 -Kube Proxy v1.7.3 v1.8.2 -Kube DNS 1.14.5 1.14.5 +API Server v1.8.3 v1.9.0 +Controller Manager v1.8.3 v1.9.0 +Scheduler v1.8.3 v1.9.0 +Kube Proxy v1.8.3 v1.9.0 +Kube DNS 1.14.5 1.14.7 +Etcd 3.0.17 3.1.10 You can now apply the upgrade by executing the following command: - kubeadm upgrade apply v1.8.2 + kubeadm upgrade apply v1.9.0 -Note: Before you can perform this upgrade, you have to update kubeadm to v1.8.2. +Note: Before you can perform this upgrade, you have to update kubeadm to v1.9.0. _____________________________________________________________________ @@ -234,38 +246,41 @@ _____________________________________________________________________ { Description: "experimental version", Before: upgrade.ClusterState{ - KubeVersion: "v1.7.5", + KubeVersion: "v1.8.5", KubeletVersions: map[string]uint16{ - "v1.7.5": 1, + "v1.8.5": 1, }, - KubeadmVersion: "v1.7.5", + KubeadmVersion: "v1.8.5", DNSVersion: "1.14.5", + EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ - KubeVersion: "v1.8.0-beta.1", - KubeadmVersion: "v1.8.0-beta.1", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.0-beta.1", + KubeadmVersion: "v1.9.0-beta.1", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, }, expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': COMPONENT CURRENT AVAILABLE -Kubelet 1 x v1.7.5 v1.8.0-beta.1 +Kubelet 1 x v1.8.5 v1.9.0-beta.1 Upgrade to the latest experimental version: COMPONENT CURRENT AVAILABLE -API Server v1.7.5 v1.8.0-beta.1 -Controller Manager v1.7.5 v1.8.0-beta.1 -Scheduler v1.7.5 v1.8.0-beta.1 -Kube Proxy v1.7.5 v1.8.0-beta.1 -Kube DNS 1.14.5 1.14.5 +API Server v1.8.5 v1.9.0-beta.1 +Controller Manager v1.8.5 v1.9.0-beta.1 +Scheduler v1.8.5 v1.9.0-beta.1 +Kube Proxy v1.8.5 v1.9.0-beta.1 +Kube DNS 1.14.5 1.14.7 +Etcd 3.0.17 3.1.10 You can now apply the upgrade by executing the following command: - kubeadm upgrade apply v1.8.0-beta.1 + kubeadm upgrade apply v1.9.0-beta.1 -Note: Before you can perform this upgrade, you have to update kubeadm to v1.8.0-beta.1. +Note: Before you can perform this upgrade, you have to update kubeadm to v1.9.0-beta.1. _____________________________________________________________________ @@ -276,38 +291,41 @@ _____________________________________________________________________ { Description: "release candidate version", Before: upgrade.ClusterState{ - KubeVersion: "v1.7.5", + KubeVersion: "v1.8.5", KubeletVersions: map[string]uint16{ - "v1.7.5": 1, + "v1.8.5": 1, }, - KubeadmVersion: "v1.7.5", + KubeadmVersion: "v1.8.5", DNSVersion: "1.14.5", + EtcdVersion: "3.0.17", }, After: upgrade.ClusterState{ - KubeVersion: "v1.8.0-rc.1", - KubeadmVersion: "v1.8.0-rc.1", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.0-rc.1", + KubeadmVersion: "v1.9.0-rc.1", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, }, expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply': COMPONENT CURRENT AVAILABLE -Kubelet 1 x v1.7.5 v1.8.0-rc.1 +Kubelet 1 x v1.8.5 v1.9.0-rc.1 Upgrade to the latest release candidate version: COMPONENT CURRENT AVAILABLE -API Server v1.7.5 v1.8.0-rc.1 -Controller Manager v1.7.5 v1.8.0-rc.1 -Scheduler v1.7.5 v1.8.0-rc.1 -Kube Proxy v1.7.5 v1.8.0-rc.1 -Kube DNS 1.14.5 1.14.5 +API Server v1.8.5 v1.9.0-rc.1 +Controller Manager v1.8.5 v1.9.0-rc.1 +Scheduler v1.8.5 v1.9.0-rc.1 +Kube Proxy v1.8.5 v1.9.0-rc.1 +Kube DNS 1.14.5 1.14.7 +Etcd 3.0.17 3.1.10 You can now apply the upgrade by executing the following command: - kubeadm upgrade apply v1.8.0-rc.1 + kubeadm upgrade apply v1.9.0-rc.1 -Note: Before you can perform this upgrade, you have to update kubeadm to v1.8.0-rc.1. +Note: Before you can perform this upgrade, you have to update kubeadm to v1.9.0-rc.1. _____________________________________________________________________ diff --git a/cmd/kubeadm/app/constants/constants.go b/cmd/kubeadm/app/constants/constants.go index 0139adaea2..bc84458cfa 100644 --- a/cmd/kubeadm/app/constants/constants.go +++ b/cmd/kubeadm/app/constants/constants.go @@ -226,8 +226,9 @@ var ( // SupportedEtcdVersion lists officially supported etcd versions with corresponding kubernetes releases SupportedEtcdVersion = map[uint8]string{ - 8: "3.0.17", - 9: "3.1.10", + 8: "3.0.17", + 9: "3.1.10", + 10: "3.1.11", } ) diff --git a/cmd/kubeadm/app/constants/constants_test.go b/cmd/kubeadm/app/constants/constants_test.go index c513f8c6da..4a7e14fe2f 100644 --- a/cmd/kubeadm/app/constants/constants_test.go +++ b/cmd/kubeadm/app/constants/constants_test.go @@ -137,8 +137,8 @@ func TestEtcdSupportedVersion(t *testing.T) { }, { kubernetesVersion: "1.10.0", - expectedVersion: nil, - expectedError: fmt.Errorf("Unsupported or unknown kubernetes version"), + expectedVersion: version.MustParseSemantic("3.1.11"), + expectedError: nil, }, { kubernetesVersion: "1.8.6", diff --git a/cmd/kubeadm/app/phases/upgrade/BUILD b/cmd/kubeadm/app/phases/upgrade/BUILD index de06c565e0..6b19e62347 100644 --- a/cmd/kubeadm/app/phases/upgrade/BUILD +++ b/cmd/kubeadm/app/phases/upgrade/BUILD @@ -78,6 +78,7 @@ go_test( "//cmd/kubeadm/app/util/apiclient:go_default_library", "//pkg/api/legacyscheme:go_default_library", "//pkg/util/version:go_default_library", + "//vendor/github.com/coreos/etcd/clientv3:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", ], ) diff --git a/cmd/kubeadm/app/phases/upgrade/compute.go b/cmd/kubeadm/app/phases/upgrade/compute.go index f0c66a2d26..814eefc3ef 100644 --- a/cmd/kubeadm/app/phases/upgrade/compute.go +++ b/cmd/kubeadm/app/phases/upgrade/compute.go @@ -22,6 +22,7 @@ import ( kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns" + "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/pkg/util/version" ) @@ -58,11 +59,13 @@ type ClusterState struct { KubeadmVersion string // KubeletVersions is a map with a version number linked to the amount of kubelets running that version in the cluster KubeletVersions map[string]uint16 + // EtcdVersion represents the version of etcd used in the cluster + EtcdVersion string } // GetAvailableUpgrades fetches all versions from the specified VersionGetter and computes which // kinds of upgrades can be performed -func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesAllowed, rcUpgradesAllowed bool) ([]Upgrade, error) { +func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesAllowed, rcUpgradesAllowed bool, cluster util.EtcdCluster) ([]Upgrade, error) { fmt.Println("[upgrade] Fetching available versions to upgrade to") // Collect the upgrades kubeadm can do in this list @@ -94,6 +97,12 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA return nil, err } + // Get current etcd version + etcdStatus, err := cluster.GetEtcdClusterStatus() + if err != nil { + return nil, err + } + // Construct a descriptor for the current state of the world // TODO: Make CoreDNS available here. beforeState := ClusterState{ @@ -101,6 +110,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA DNSVersion: dns.GetDNSVersion(clusterVersion, kubeadmconstants.KubeDNS), KubeadmVersion: kubeadmVersionStr, KubeletVersions: kubeletVersions, + EtcdVersion: etcdStatus.Version, } // Do a "dumb guess" that a new minor upgrade is available just because the latest stable version is higher than the cluster version @@ -111,7 +121,6 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA // in the case that a user is trying to upgrade from, let's say, v1.8.0-beta.2 to v1.8.0-rc.1 (given we support such upgrades experimentally) // a stable-1.8 branch doesn't exist yet. Hence this check. if patchVersionBranchExists(clusterVersion, stableVersion) { - currentBranch := getBranchFromVersion(clusterVersionStr) versionLabel := fmt.Sprintf("stable-%s", currentBranch) description := fmt.Sprintf("version in the v%s series", currentBranch) @@ -143,6 +152,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA KubeVersion: patchVersionStr, DNSVersion: dns.GetDNSVersion(patchVersion, kubeadmconstants.KubeDNS), KubeadmVersion: newKubeadmVer, + EtcdVersion: getSuggestedEtcdVersion(patchVersionStr), // KubeletVersions is unset here as it is not used anywhere in .After }, }) @@ -158,6 +168,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA KubeVersion: stableVersionStr, DNSVersion: dns.GetDNSVersion(stableVersion, kubeadmconstants.KubeDNS), KubeadmVersion: stableVersionStr, + EtcdVersion: getSuggestedEtcdVersion(stableVersionStr), // KubeletVersions is unset here as it is not used anywhere in .After }, }) @@ -202,6 +213,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA KubeVersion: previousBranchLatestVersionStr, DNSVersion: dns.GetDNSVersion(previousBranchLatestVersion, kubeadmconstants.KubeDNS), KubeadmVersion: previousBranchLatestVersionStr, + EtcdVersion: getSuggestedEtcdVersion(previousBranchLatestVersionStr), // KubeletVersions is unset here as it is not used anywhere in .After }, }) @@ -227,6 +239,7 @@ func GetAvailableUpgrades(versionGetterImpl VersionGetter, experimentalUpgradesA KubeVersion: unstableKubeVersion, DNSVersion: unstableKubeDNSVersion, KubeadmVersion: unstableKubeVersion, + EtcdVersion: getSuggestedEtcdVersion(unstableKubeVersion), // KubeletVersions is unset here as it is not used anywhere in .After }, }) @@ -258,3 +271,12 @@ func rcUpgradePossible(clusterVersion, previousBranchLatestVersion *version.Vers func minorUpgradePossibleWithPatchRelease(stableVersion, patchVersion *version.Version) bool { return patchVersion.LessThan(stableVersion) } + +func getSuggestedEtcdVersion(kubernetesVersion string) string { + etcdVersion, err := kubeadmconstants.EtcdSupportedVersion(kubernetesVersion) + if err != nil { + fmt.Printf("[upgrade/versions] WARNING: No recommended etcd for requested kubernetes version (%s)\n", kubernetesVersion) + return "N/A" + } + return etcdVersion.String() +} diff --git a/cmd/kubeadm/app/phases/upgrade/compute_test.go b/cmd/kubeadm/app/phases/upgrade/compute_test.go index 45f1d781dc..6c356b7684 100644 --- a/cmd/kubeadm/app/phases/upgrade/compute_test.go +++ b/cmd/kubeadm/app/phases/upgrade/compute_test.go @@ -17,10 +17,10 @@ limitations under the License. package upgrade import ( + "github.com/coreos/etcd/clientv3" + versionutil "k8s.io/kubernetes/pkg/util/version" "reflect" "testing" - - versionutil "k8s.io/kubernetes/pkg/util/version" ) type fakeVersionGetter struct { @@ -47,7 +47,7 @@ func (f *fakeVersionGetter) VersionFromCILabel(ciVersionLabel, _ string) (string if ciVersionLabel == "latest" { return f.latestVersion, versionutil.MustParseSemantic(f.latestVersion), nil } - if ciVersionLabel == "latest-1.8" { + if ciVersionLabel == "latest-1.9" { return f.latestDevBranchVersion, versionutil.MustParseSemantic(f.latestDevBranchVersion), nil } return f.stablePatchVersion, versionutil.MustParseSemantic(f.stablePatchVersion), nil @@ -60,6 +60,14 @@ func (f *fakeVersionGetter) KubeletVersions() (map[string]uint16, error) { }, nil } +type fakeEtcdCluster struct{} + +func (f fakeEtcdCluster) GetEtcdClusterStatus() (*clientv3.StatusResponse, error) { + client := &clientv3.StatusResponse{} + client.Version = "3.0.14" + return client, nil +} + func TestGetAvailableUpgrades(t *testing.T) { tests := []struct { vg *fakeVersionGetter @@ -69,12 +77,12 @@ func TestGetAvailableUpgrades(t *testing.T) { }{ { // no action needed, already up-to-date vg: &fakeVersionGetter{ - clusterVersion: "v1.7.3", - kubeletVersion: "v1.7.3", - kubeadmVersion: "v1.7.3", + clusterVersion: "v1.8.3", + kubeletVersion: "v1.8.3", + kubeadmVersion: "v1.8.3", - stablePatchVersion: "v1.7.3", - stableVersion: "v1.7.3", + stablePatchVersion: "v1.8.3", + stableVersion: "v1.8.3", }, expectedUpgrades: []Upgrade{}, allowExperimental: false, @@ -82,28 +90,30 @@ func TestGetAvailableUpgrades(t *testing.T) { }, { // simple patch version upgrade vg: &fakeVersionGetter{ - clusterVersion: "v1.7.1", - kubeletVersion: "v1.7.1", // the kubelet are on the same version as the control plane - kubeadmVersion: "v1.7.2", + clusterVersion: "v1.8.1", + kubeletVersion: "v1.8.1", // the kubelet are on the same version as the control plane + kubeadmVersion: "v1.8.2", - stablePatchVersion: "v1.7.3", - stableVersion: "v1.7.3", + stablePatchVersion: "v1.8.3", + stableVersion: "v1.8.3", }, expectedUpgrades: []Upgrade{ { - Description: "version in the v1.7 series", + Description: "version in the v1.8 series", Before: ClusterState{ - KubeVersion: "v1.7.1", + KubeVersion: "v1.8.1", KubeletVersions: map[string]uint16{ - "v1.7.1": 1, + "v1.8.1": 1, }, - KubeadmVersion: "v1.7.2", + KubeadmVersion: "v1.8.2", DNSVersion: "1.14.5", + EtcdVersion: "3.0.14", }, After: ClusterState{ - KubeVersion: "v1.7.3", - KubeadmVersion: "v1.7.3", + KubeVersion: "v1.8.3", + KubeadmVersion: "v1.8.3", DNSVersion: "1.14.5", + EtcdVersion: "3.0.17", }, }, }, @@ -112,28 +122,30 @@ func TestGetAvailableUpgrades(t *testing.T) { }, { // minor version upgrade only vg: &fakeVersionGetter{ - clusterVersion: "v1.7.3", - kubeletVersion: "v1.7.3", // the kubelet are on the same version as the control plane - kubeadmVersion: "v1.8.0", + clusterVersion: "v1.8.1", + kubeletVersion: "v1.8.1", // the kubelet are on the same version as the control plane + kubeadmVersion: "v1.9.0", - stablePatchVersion: "v1.7.3", - stableVersion: "v1.8.0", + stablePatchVersion: "v1.8.1", + stableVersion: "v1.9.0", }, expectedUpgrades: []Upgrade{ { Description: "stable version", Before: ClusterState{ - KubeVersion: "v1.7.3", + KubeVersion: "v1.8.1", KubeletVersions: map[string]uint16{ - "v1.7.3": 1, + "v1.8.1": 1, }, - KubeadmVersion: "v1.8.0", + KubeadmVersion: "v1.9.0", DNSVersion: "1.14.5", + EtcdVersion: "3.0.14", }, After: ClusterState{ - KubeVersion: "v1.8.0", - KubeadmVersion: "v1.8.0", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.0", + KubeadmVersion: "v1.9.0", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, }, @@ -142,44 +154,48 @@ func TestGetAvailableUpgrades(t *testing.T) { }, { // both minor version upgrade and patch version upgrade available vg: &fakeVersionGetter{ - clusterVersion: "v1.7.3", - kubeletVersion: "v1.7.3", // the kubelet are on the same version as the control plane - kubeadmVersion: "v1.8.1", + clusterVersion: "v1.8.3", + kubeletVersion: "v1.8.3", // the kubelet are on the same version as the control plane + kubeadmVersion: "v1.8.5", - stablePatchVersion: "v1.7.5", - stableVersion: "v1.8.2", + stablePatchVersion: "v1.8.5", + stableVersion: "v1.9.1", }, expectedUpgrades: []Upgrade{ { - Description: "version in the v1.7 series", + Description: "version in the v1.8 series", Before: ClusterState{ - KubeVersion: "v1.7.3", + KubeVersion: "v1.8.3", KubeletVersions: map[string]uint16{ - "v1.7.3": 1, + "v1.8.3": 1, }, - KubeadmVersion: "v1.8.1", + KubeadmVersion: "v1.8.5", DNSVersion: "1.14.5", + EtcdVersion: "3.0.14", }, After: ClusterState{ - KubeVersion: "v1.7.5", - KubeadmVersion: "v1.8.1", // Note: The kubeadm version mustn't be "downgraded" here + KubeVersion: "v1.8.5", + KubeadmVersion: "v1.8.5", // Note: The kubeadm version mustn't be "downgraded" here DNSVersion: "1.14.5", + EtcdVersion: "3.0.17", }, }, { Description: "stable version", Before: ClusterState{ - KubeVersion: "v1.7.3", + KubeVersion: "v1.8.3", KubeletVersions: map[string]uint16{ - "v1.7.3": 1, + "v1.8.3": 1, }, - KubeadmVersion: "v1.8.1", + KubeadmVersion: "v1.8.5", DNSVersion: "1.14.5", + EtcdVersion: "3.0.14", }, After: ClusterState{ - KubeVersion: "v1.8.2", - KubeadmVersion: "v1.8.2", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.1", + KubeadmVersion: "v1.9.1", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, }, @@ -188,13 +204,13 @@ func TestGetAvailableUpgrades(t *testing.T) { }, { // allow experimental upgrades, but no upgrade available vg: &fakeVersionGetter{ - clusterVersion: "v1.8.0-alpha.2", - kubeletVersion: "v1.7.5", - kubeadmVersion: "v1.7.5", + clusterVersion: "v1.9.0-alpha.2", + kubeletVersion: "v1.8.5", + kubeadmVersion: "v1.8.5", - stablePatchVersion: "v1.7.5", - stableVersion: "v1.7.5", - latestVersion: "v1.8.0-alpha.2", + stablePatchVersion: "v1.8.5", + stableVersion: "v1.8.5", + latestVersion: "v1.9.0-alpha.2", }, expectedUpgrades: []Upgrade{}, allowExperimental: true, @@ -202,29 +218,31 @@ func TestGetAvailableUpgrades(t *testing.T) { }, { // upgrade to an unstable version should be supported vg: &fakeVersionGetter{ - clusterVersion: "v1.7.5", - kubeletVersion: "v1.7.5", - kubeadmVersion: "v1.7.5", + clusterVersion: "v1.8.5", + kubeletVersion: "v1.8.5", + kubeadmVersion: "v1.8.5", - stablePatchVersion: "v1.7.5", - stableVersion: "v1.7.5", - latestVersion: "v1.8.0-alpha.2", + stablePatchVersion: "v1.8.5", + stableVersion: "v1.8.5", + latestVersion: "v1.9.0-alpha.2", }, expectedUpgrades: []Upgrade{ { Description: "experimental version", Before: ClusterState{ - KubeVersion: "v1.7.5", + KubeVersion: "v1.8.5", KubeletVersions: map[string]uint16{ - "v1.7.5": 1, + "v1.8.5": 1, }, - KubeadmVersion: "v1.7.5", + KubeadmVersion: "v1.8.5", DNSVersion: "1.14.5", + EtcdVersion: "3.0.14", }, After: ClusterState{ - KubeVersion: "v1.8.0-alpha.2", - KubeadmVersion: "v1.8.0-alpha.2", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.0-alpha.2", + KubeadmVersion: "v1.9.0-alpha.2", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, }, @@ -233,29 +251,31 @@ func TestGetAvailableUpgrades(t *testing.T) { }, { // upgrade from an unstable version to an unstable version should be supported vg: &fakeVersionGetter{ - clusterVersion: "v1.8.0-alpha.1", - kubeletVersion: "v1.7.5", - kubeadmVersion: "v1.7.5", + clusterVersion: "v1.9.0-alpha.1", + kubeletVersion: "v1.8.5", + kubeadmVersion: "v1.8.5", - stablePatchVersion: "v1.7.5", - stableVersion: "v1.7.5", - latestVersion: "v1.8.0-alpha.2", + stablePatchVersion: "v1.8.5", + stableVersion: "v1.8.5", + latestVersion: "v1.9.0-alpha.2", }, expectedUpgrades: []Upgrade{ { Description: "experimental version", Before: ClusterState{ - KubeVersion: "v1.8.0-alpha.1", + KubeVersion: "v1.9.0-alpha.1", KubeletVersions: map[string]uint16{ - "v1.7.5": 1, + "v1.8.5": 1, }, - KubeadmVersion: "v1.7.5", - DNSVersion: "1.14.5", + KubeadmVersion: "v1.8.5", + DNSVersion: "1.14.7", + EtcdVersion: "3.0.14", }, After: ClusterState{ - KubeVersion: "v1.8.0-alpha.2", - KubeadmVersion: "v1.8.0-alpha.2", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.0-alpha.2", + KubeadmVersion: "v1.9.0-alpha.2", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, }, @@ -264,30 +284,32 @@ func TestGetAvailableUpgrades(t *testing.T) { }, { // v1.X.0-alpha.0 should be ignored vg: &fakeVersionGetter{ - clusterVersion: "v1.7.5", - kubeletVersion: "v1.7.5", - kubeadmVersion: "v1.7.5", + clusterVersion: "v1.8.5", + kubeletVersion: "v1.8.5", + kubeadmVersion: "v1.8.5", - stablePatchVersion: "v1.7.5", - stableVersion: "v1.7.5", - latestDevBranchVersion: "v1.8.0-beta.1", - latestVersion: "v1.9.0-alpha.0", + stablePatchVersion: "v1.8.5", + stableVersion: "v1.8.5", + latestDevBranchVersion: "v1.9.0-beta.1", + latestVersion: "v1.10.0-alpha.0", }, expectedUpgrades: []Upgrade{ { Description: "experimental version", Before: ClusterState{ - KubeVersion: "v1.7.5", + KubeVersion: "v1.8.5", KubeletVersions: map[string]uint16{ - "v1.7.5": 1, + "v1.8.5": 1, }, - KubeadmVersion: "v1.7.5", + KubeadmVersion: "v1.8.5", DNSVersion: "1.14.5", + EtcdVersion: "3.0.14", }, After: ClusterState{ - KubeVersion: "v1.8.0-beta.1", - KubeadmVersion: "v1.8.0-beta.1", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.0-beta.1", + KubeadmVersion: "v1.9.0-beta.1", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, }, @@ -296,30 +318,32 @@ func TestGetAvailableUpgrades(t *testing.T) { }, { // upgrade to an RC version should be supported vg: &fakeVersionGetter{ - clusterVersion: "v1.7.5", - kubeletVersion: "v1.7.5", - kubeadmVersion: "v1.7.5", + clusterVersion: "v1.8.5", + kubeletVersion: "v1.8.5", + kubeadmVersion: "v1.8.5", - stablePatchVersion: "v1.7.5", - stableVersion: "v1.7.5", - latestDevBranchVersion: "v1.8.0-rc.1", - latestVersion: "v1.9.0-alpha.1", + stablePatchVersion: "v1.8.5", + stableVersion: "v1.8.5", + latestDevBranchVersion: "v1.9.0-rc.1", + latestVersion: "v1.10.0-alpha.1", }, expectedUpgrades: []Upgrade{ { Description: "release candidate version", Before: ClusterState{ - KubeVersion: "v1.7.5", + KubeVersion: "v1.8.5", KubeletVersions: map[string]uint16{ - "v1.7.5": 1, + "v1.8.5": 1, }, - KubeadmVersion: "v1.7.5", + KubeadmVersion: "v1.8.5", DNSVersion: "1.14.5", + EtcdVersion: "3.0.14", }, After: ClusterState{ - KubeVersion: "v1.8.0-rc.1", - KubeadmVersion: "v1.8.0-rc.1", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.0-rc.1", + KubeadmVersion: "v1.9.0-rc.1", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, }, @@ -328,30 +352,32 @@ func TestGetAvailableUpgrades(t *testing.T) { }, { // it is possible (but very uncommon) that the latest version from the previous branch is an rc and the current latest version is alpha.0. In that case, show the RC vg: &fakeVersionGetter{ - clusterVersion: "v1.7.5", - kubeletVersion: "v1.7.5", - kubeadmVersion: "v1.7.5", + clusterVersion: "v1.8.5", + kubeletVersion: "v1.8.5", + kubeadmVersion: "v1.8.5", - stablePatchVersion: "v1.7.5", - stableVersion: "v1.7.5", - latestDevBranchVersion: "v1.8.0-rc.1", - latestVersion: "v1.9.0-alpha.0", + stablePatchVersion: "v1.8.5", + stableVersion: "v1.8.5", + latestDevBranchVersion: "v1.9.6-rc.1", + latestVersion: "v1.10.1-alpha.0", }, expectedUpgrades: []Upgrade{ { Description: "experimental version", // Note that this is considered an experimental version in this uncommon scenario Before: ClusterState{ - KubeVersion: "v1.7.5", + KubeVersion: "v1.8.5", KubeletVersions: map[string]uint16{ - "v1.7.5": 1, + "v1.8.5": 1, }, - KubeadmVersion: "v1.7.5", + KubeadmVersion: "v1.8.5", DNSVersion: "1.14.5", + EtcdVersion: "3.0.14", }, After: ClusterState{ - KubeVersion: "v1.8.0-rc.1", - KubeadmVersion: "v1.8.0-rc.1", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.6-rc.1", + KubeadmVersion: "v1.9.6-rc.1", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, }, @@ -360,46 +386,50 @@ func TestGetAvailableUpgrades(t *testing.T) { }, { // upgrade to an RC version should be supported. There may also be an even newer unstable version. vg: &fakeVersionGetter{ - clusterVersion: "v1.7.5", - kubeletVersion: "v1.7.5", - kubeadmVersion: "v1.7.5", + clusterVersion: "v1.8.5", + kubeletVersion: "v1.8.5", + kubeadmVersion: "v1.8.5", - stablePatchVersion: "v1.7.5", - stableVersion: "v1.7.5", - latestDevBranchVersion: "v1.8.0-rc.1", - latestVersion: "v1.9.0-alpha.1", + stablePatchVersion: "v1.8.5", + stableVersion: "v1.8.5", + latestDevBranchVersion: "v1.9.0-rc.1", + latestVersion: "v1.10.0-alpha.2", }, expectedUpgrades: []Upgrade{ { Description: "release candidate version", Before: ClusterState{ - KubeVersion: "v1.7.5", + KubeVersion: "v1.8.5", KubeletVersions: map[string]uint16{ - "v1.7.5": 1, + "v1.8.5": 1, }, - KubeadmVersion: "v1.7.5", + KubeadmVersion: "v1.8.5", DNSVersion: "1.14.5", + EtcdVersion: "3.0.14", }, After: ClusterState{ - KubeVersion: "v1.8.0-rc.1", - KubeadmVersion: "v1.8.0-rc.1", - DNSVersion: "1.14.5", + KubeVersion: "v1.9.0-rc.1", + KubeadmVersion: "v1.9.0-rc.1", + DNSVersion: "1.14.7", + EtcdVersion: "3.1.10", }, }, { Description: "experimental version", Before: ClusterState{ - KubeVersion: "v1.7.5", + KubeVersion: "v1.8.5", KubeletVersions: map[string]uint16{ - "v1.7.5": 1, + "v1.8.5": 1, }, - KubeadmVersion: "v1.7.5", + KubeadmVersion: "v1.8.5", DNSVersion: "1.14.5", + EtcdVersion: "3.0.14", }, After: ClusterState{ - KubeVersion: "v1.9.0-alpha.1", - KubeadmVersion: "v1.9.0-alpha.1", + KubeVersion: "v1.10.0-alpha.2", + KubeadmVersion: "v1.10.0-alpha.2", DNSVersion: "1.14.7", + EtcdVersion: "3.1.11", }, }, }, @@ -409,9 +439,12 @@ func TestGetAvailableUpgrades(t *testing.T) { }, } + // Instantiating a fake etcd cluster for being able to get etcd version for a corresponding + // kubernetes release. + testCluster := fakeEtcdCluster{} for _, rt := range tests { - actualUpgrades, actualErr := GetAvailableUpgrades(rt.vg, rt.allowExperimental, rt.allowRCs) + actualUpgrades, actualErr := GetAvailableUpgrades(rt.vg, rt.allowExperimental, rt.allowRCs, testCluster) if !reflect.DeepEqual(actualUpgrades, rt.expectedUpgrades) { t.Errorf("failed TestGetAvailableUpgrades\n\texpected upgrades: %v\n\tgot: %v", rt.expectedUpgrades, actualUpgrades) } diff --git a/cmd/kubeadm/app/phases/upgrade/staticpods.go b/cmd/kubeadm/app/phases/upgrade/staticpods.go index 52375432bf..716b39e7a3 100644 --- a/cmd/kubeadm/app/phases/upgrade/staticpods.go +++ b/cmd/kubeadm/app/phases/upgrade/staticpods.go @@ -175,7 +175,8 @@ func performEtcdStaticPodUpgrade(waiter apiclient.Waiter, pathMgr StaticPodPathM return false, fmt.Errorf("external etcd cannot be upgraded with kubeadm") } // Checking health state of etcd before proceeding with the upgrtade - etcdStatus, err := util.GetEtcdClusterStatus() + etcdCluster := util.LocalEtcdCluster{} + etcdStatus, err := etcdCluster.GetEtcdClusterStatus() if err != nil { return true, fmt.Errorf("etcd cluster is not healthy: %v", err) } @@ -222,7 +223,7 @@ func performEtcdStaticPodUpgrade(waiter apiclient.Waiter, pathMgr StaticPodPathM } // Checking health state of etcd after the upgrade - etcdStatus, err = util.GetEtcdClusterStatus() + etcdStatus, err = etcdCluster.GetEtcdClusterStatus() if err != nil { return true, rollbackEtcdData(cfg, fmt.Errorf("etcd cluster is not healthy after upgrade: %v rolling back", err), pathMgr) } diff --git a/cmd/kubeadm/app/util/etcd.go b/cmd/kubeadm/app/util/etcd.go index 2c82d99b2c..45d8033907 100644 --- a/cmd/kubeadm/app/util/etcd.go +++ b/cmd/kubeadm/app/util/etcd.go @@ -22,8 +22,16 @@ import ( "time" ) +// EtcdCluster is an interface to get etcd cluster related information +type EtcdCluster interface { + GetEtcdClusterStatus() (*clientv3.StatusResponse, error) +} + +// LocalEtcdCluster represents an instance of a local etcd cluster +type LocalEtcdCluster struct{} + // GetEtcdClusterStatus returns nil for status Up or error for status Down -func GetEtcdClusterStatus() (*clientv3.StatusResponse, error) { +func (cluster LocalEtcdCluster) GetEtcdClusterStatus() (*clientv3.StatusResponse, error) { ep := []string{"localhost:2379"} cli, err := clientv3.New(clientv3.Config{ Endpoints: ep,