From 55f8c707790ad51921dd69221d6e406f146846c6 Mon Sep 17 00:00:00 2001 From: Ciprian Hacman Date: Sun, 14 Mar 2021 12:26:26 +0200 Subject: [PATCH] Add channels entries for image architecture --- channels/alpha | 34 ++++++++++--- channels/stable | 48 +++++++++++++----- cmd/kops/upgrade_cluster.go | 49 ++++++++++--------- docs/operations/cluster_template.md | 4 +- docs/releases/1.20-NOTES.md | 2 + pkg/apis/kops/BUILD.bazel | 1 + pkg/apis/kops/channel.go | 10 +++- pkg/util/templater/BUILD.bazel | 1 + pkg/util/templater/template_functions.go | 5 +- pkg/util/templater/templater_test.go | 9 +++- tests/integration/channel/BUILD.bazel | 1 + tests/integration/channel/integration_test.go | 25 ++++++++-- tests/integration/channel/simple/channel.yaml | 43 +++++++++++++--- .../fi/cloudup/populate_instancegroup_spec.go | 37 ++++++++++++-- 14 files changed, 204 insertions(+), 65 deletions(-) diff --git a/channels/alpha b/channels/alpha index 429e7d6d14..9f4b8eda7a 100644 --- a/channels/alpha +++ b/channels/alpha @@ -3,59 +3,81 @@ spec: # We put the "legacy" version first, for kops versions that don't support versions ( < 1.5.0 ) - name: kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2017-07-28 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.4.0 <1.5.0" - name: kope.io/k8s-1.5-debian-jessie-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.5.0 <1.6.0" - name: kope.io/k8s-1.6-debian-jessie-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.6.0 <1.7.0" - name: kope.io/k8s-1.7-debian-jessie-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.7.0 <1.8.0" - name: kope.io/k8s-1.8-debian-stretch-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.8.0 <1.9.0" - name: kope.io/k8s-1.9-debian-stretch-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.9.0 <1.10.0" - name: kope.io/k8s-1.10-debian-stretch-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.10.0 <1.11.0" # Stretch is the default for 1.11 (for nvme) - name: kope.io/k8s-1.11-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.11.0 <1.12.0" - name: kope.io/k8s-1.12-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.12.0 <1.13.0" - name: kope.io/k8s-1.13-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.13.0 <1.14.0" - name: kope.io/k8s-1.14-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.14.0 <1.15.0" - name: kope.io/k8s-1.15-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.15.0 <1.16.0" - name: kope.io/k8s-1.16-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.16.0 <1.17.0" - name: kope.io/k8s-1.17-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.17.0 <1.18.0" - name: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20210119.1 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.18.0" - - providerID: gce + - name: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-arm64-server-20210119.1 + providerID: aws + architectureID: arm64 + kubernetesVersion: ">=1.20.0" + - name: "cos-cloud/cos-stable-65-10323-99-0" + providerID: gce + architectureID: amd64 kubernetesVersion: "<1.16.0-alpha.1" - name: "cos-cloud/cos-stable-65-10323-99-0" - - providerID: gce + - name: "cos-cloud/cos-stable-77-12371-114-0" + providerID: gce + architectureID: amd64 kubernetesVersion: ">=1.16.0-alpha.1" - name: "cos-cloud/cos-stable-77-12371-114-0" - - providerID: gce + - name: "ubuntu-os-cloud/ubuntu-2004-focal-v20210119a" + providerID: gce + architectureID: amd64 kubernetesVersion: ">=1.17.0" - name: "ubuntu-os-cloud/ubuntu-2004-focal-v20210119a" cluster: kubernetesVersion: v1.5.8 networking: diff --git a/channels/stable b/channels/stable index fa15bebe69..9f4b8eda7a 100644 --- a/channels/stable +++ b/channels/stable @@ -3,72 +3,94 @@ spec: # We put the "legacy" version first, for kops versions that don't support versions ( < 1.5.0 ) - name: kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2017-07-28 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.4.0 <1.5.0" - name: kope.io/k8s-1.5-debian-jessie-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.5.0 <1.6.0" - name: kope.io/k8s-1.6-debian-jessie-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.6.0 <1.7.0" - name: kope.io/k8s-1.7-debian-jessie-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.7.0 <1.8.0" - name: kope.io/k8s-1.8-debian-stretch-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.8.0 <1.9.0" - name: kope.io/k8s-1.9-debian-stretch-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.9.0 <1.10.0" - name: kope.io/k8s-1.10-debian-stretch-amd64-hvm-ebs-2018-08-17 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.10.0 <1.11.0" # Stretch is the default for 1.11 (for nvme) - name: kope.io/k8s-1.11-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.11.0 <1.12.0" - name: kope.io/k8s-1.12-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.12.0 <1.13.0" - name: kope.io/k8s-1.13-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.13.0 <1.14.0" - name: kope.io/k8s-1.14-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.14.0 <1.15.0" - name: kope.io/k8s-1.15-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.15.0 <1.16.0" - name: kope.io/k8s-1.16-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.16.0 <1.17.0" - name: kope.io/k8s-1.17-debian-stretch-amd64-hvm-ebs-2021-02-05 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.17.0 <1.18.0" - name: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20210119.1 providerID: aws + architectureID: amd64 kubernetesVersion: ">=1.18.0" - - providerID: gce + - name: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-arm64-server-20210119.1 + providerID: aws + architectureID: arm64 + kubernetesVersion: ">=1.20.0" + - name: "cos-cloud/cos-stable-65-10323-99-0" + providerID: gce + architectureID: amd64 kubernetesVersion: "<1.16.0-alpha.1" - name: "cos-cloud/cos-stable-65-10323-99-0" - - providerID: gce + - name: "cos-cloud/cos-stable-77-12371-114-0" + providerID: gce + architectureID: amd64 kubernetesVersion: ">=1.16.0-alpha.1" - name: "cos-cloud/cos-stable-77-12371-114-0" - - providerID: gce + - name: "ubuntu-os-cloud/ubuntu-2004-focal-v20210119a" + providerID: gce + architectureID: amd64 kubernetesVersion: ">=1.17.0" - name: "ubuntu-os-cloud/ubuntu-2004-focal-v20210119a" cluster: kubernetesVersion: v1.5.8 networking: kubenet: {} kubernetesVersions: - range: ">=1.20.0" - recommendedVersion: 1.20.2 + recommendedVersion: 1.20.4 requiredVersion: 1.20.0 - range: ">=1.19.0" - recommendedVersion: 1.19.7 + recommendedVersion: 1.19.8 requiredVersion: 1.19.0 - range: ">=1.18.0" - recommendedVersion: 1.18.15 + recommendedVersion: 1.18.16 requiredVersion: 1.18.0 - range: ">=1.17.0" recommendedVersion: 1.17.17 @@ -97,16 +119,16 @@ spec: kopsVersions: - range: ">=1.20.0-alpha.1" #recommendedVersion: "1.19.0-beta.3" - #requiredVersion: 1.19.0 - kubernetesVersion: 1.20.2 + #requiredVersion: 1.20.0 + kubernetesVersion: 1.20.4 - range: ">=1.19.0-beta.3" #recommendedVersion: "1.19.0-beta.3" #requiredVersion: 1.19.0 - kubernetesVersion: 1.19.7 + kubernetesVersion: 1.19.8 - range: ">=1.18.0-alpha.1" recommendedVersion: "1.18.2" #requiredVersion: 1.18.0 - kubernetesVersion: 1.18.15 + kubernetesVersion: 1.18.16 - range: ">=1.17.0-alpha.1" recommendedVersion: "1.18.2" #requiredVersion: 1.17.0 diff --git a/cmd/kops/upgrade_cluster.go b/cmd/kops/upgrade_cluster.go index c18349e0c8..1e6db53e40 100644 --- a/cmd/kops/upgrade_cluster.go +++ b/cmd/kops/upgrade_cluster.go @@ -23,9 +23,8 @@ import ( "github.com/blang/semver/v4" "github.com/spf13/cobra" - "k8s.io/klog/v2" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog/v2" "k8s.io/kops" kopsapi "k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/apis/kops/util" @@ -174,28 +173,32 @@ func (c *UpgradeClusterCmd) Run(ctx context.Context, args []string) error { // Prompt to upgrade image if proposedKubernetesVersion != nil { - image := channel.FindImage(cloud.ProviderID(), *proposedKubernetesVersion) - - if image == nil { - klog.Warningf("No matching images specified in channel; cannot prompt for upgrade") - } else { - for _, ig := range instanceGroups { - if channel.HasUpstreamImagePrefix(ig.Spec.Image) { - if ig.Spec.Image != image.Name { - target := ig - actions = append(actions, &upgradeAction{ - Item: "InstanceGroup/" + target.ObjectMeta.Name, - Property: "Image", - Old: target.Spec.Image, - New: image.Name, - apply: func() { - target.Spec.Image = image.Name - }, - }) - } - } else { - klog.Infof("Custom image (%s) has been provided for Instance Group %q; not updating image", ig.Spec.Image, ig.GetName()) + for _, ig := range instanceGroups { + architecture, err := cloudup.MachineArchitecture(cloud, ig.Spec.MachineType) + if err != nil { + klog.Warningf("Error finding architecture for machine type %q: %v", ig.Spec.MachineType, err) + continue + } + image := channel.FindImage(cloud.ProviderID(), *proposedKubernetesVersion, architecture) + if image == nil { + klog.Warningf("No matching images specified in channel; cannot prompt for upgrade") + continue + } + if channel.HasUpstreamImagePrefix(ig.Spec.Image) { + if ig.Spec.Image != image.Name { + target := ig + actions = append(actions, &upgradeAction{ + Item: "InstanceGroup/" + target.ObjectMeta.Name, + Property: "Image", + Old: target.Spec.Image, + New: image.Name, + apply: func() { + target.Spec.Image = image.Name + }, + }) } + } else { + klog.Infof("Custom image (%s) has been provided for Instance Group %q; not updating image", ig.Spec.Image, ig.GetName()) } } } diff --git a/docs/operations/cluster_template.md b/docs/operations/cluster_template.md index 99506b40f3..1f10b6dfc1 100644 --- a/docs/operations/cluster_template.md +++ b/docs/operations/cluster_template.md @@ -16,7 +16,7 @@ metadata: kops.k8s.io/cluster: {{ '{{.clusterName}}.{{.dnsZone}}' }} name: nodes spec: - image: {{ '{{ ChannelRecommendedImage .cloud .kubernetesVersion }}' }} + image: {{ '{{ ChannelRecommendedImage .cloud .kubernetesVersion .architecture }}' }} kubernetesVersion: {{ '{{ ChannelRecommendedKubernetesUpgradeVersion .kubernetesVersion }}' }} machineType: m4.large maxPrice: "0.5" @@ -131,7 +131,7 @@ This function returns the kubernetes version recommended for the running kops ve This function returns the recommended kubernetes version given that you currently run ``. Typically this is the latest patch version supported by the given channel. -##### ChannelRecommendedImage +##### ChannelRecommendedImage This function returns the recommended image for the given cloud provider and kubernetes version. diff --git a/docs/releases/1.20-NOTES.md b/docs/releases/1.20-NOTES.md index 2a4cff67e7..93238222cd 100644 --- a/docs/releases/1.20-NOTES.md +++ b/docs/releases/1.20-NOTES.md @@ -34,6 +34,8 @@ * If you are using the Calico network plugin in a cross-subnet setup, you may have to manually remove the AWS Source/Dest Check controller (`k8s-ec2-srcdst`) deployment that was previously deprecated and replaced with the new [awsSrcDstCheck](https://docs.projectcalico.org/reference/resources/felixconfig#spec) feature. +* If you are using self-hosted channels files, you have to add the new `architectureID` field, with one of the `amd64` or `arm64` values. + * If you are running `kops toolbox template` in an airgapped environment, you have to set `--channel` to point to a local channel file. * If your workload targets control plane nodes, you need to change them to select the `node-role.kubernetes.io/control-plane=""` label. You should also add the `node-role.kubernetes.io/control-plane:NoSchedule` toleration to these workloads. This taint will not be added to control plane nodes before kOps 1.22. diff --git a/pkg/apis/kops/BUILD.bazel b/pkg/apis/kops/BUILD.bazel index 9cbb0a3647..50de428036 100644 --- a/pkg/apis/kops/BUILD.bazel +++ b/pkg/apis/kops/BUILD.bazel @@ -26,6 +26,7 @@ go_library( deps = [ "//pkg/apis/kops/util:go_default_library", "//upup/pkg/fi/utils:go_default_library", + "//util/pkg/architectures:go_default_library", "//util/pkg/vfs:go_default_library", "//vendor/github.com/blang/semver/v4:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", diff --git a/pkg/apis/kops/channel.go b/pkg/apis/kops/channel.go index 976ea949e6..fa4846e4eb 100644 --- a/pkg/apis/kops/channel.go +++ b/pkg/apis/kops/channel.go @@ -25,6 +25,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/klog/v2" "k8s.io/kops/pkg/apis/kops/util" + "k8s.io/kops/util/pkg/architectures" "k8s.io/kops/util/pkg/vfs" ) @@ -78,6 +79,8 @@ type ChannelImageSpec struct { ProviderID string `json:"providerID,omitempty"` + ArchitectureID string `json:"architectureID,omitempty"` + Name string `json:"name,omitempty"` KubernetesVersion string `json:"kubernetesVersion,omitempty"` @@ -259,13 +262,16 @@ const ( ) // FindImage returns the image for the cloudprovider, or nil if none found -func (c *Channel) FindImage(provider CloudProviderID, kubernetesVersion semver.Version) *ChannelImageSpec { +func (c *Channel) FindImage(provider CloudProviderID, kubernetesVersion semver.Version, architecture architectures.Architecture) *ChannelImageSpec { var matches []*ChannelImageSpec for _, image := range c.Spec.Images { if image.ProviderID != string(provider) { continue } + if image.ArchitectureID != "" && image.ArchitectureID != string(architecture) { + continue + } if image.KubernetesVersion != "" { versionRange, err := semver.ParseRange(image.KubernetesVersion) if err != nil { @@ -327,7 +333,7 @@ func RecommendedKubernetesVersion(c *Channel, kopsVersionString string) *semver. // Returns true if the given image name has the stable or alpha channel images prefix. Otherwise false. func (c *Channel) HasUpstreamImagePrefix(image string) bool { return strings.HasPrefix(image, "kope.io/k8s-") || - strings.HasPrefix(image, "099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-") || + strings.HasPrefix(image, "099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-") || strings.HasPrefix(image, "cos-cloud/cos-stable-") || strings.HasPrefix(image, "ubuntu-os-cloud/ubuntu-") } diff --git a/pkg/util/templater/BUILD.bazel b/pkg/util/templater/BUILD.bazel index 58de4dd77c..962c8e4b98 100644 --- a/pkg/util/templater/BUILD.bazel +++ b/pkg/util/templater/BUILD.bazel @@ -12,6 +12,7 @@ go_library( "//:go_default_library", "//pkg/apis/kops:go_default_library", "//pkg/apis/kops/util:go_default_library", + "//util/pkg/architectures:go_default_library", "//vendor/github.com/Masterminds/sprig/v3:go_default_library", "//vendor/github.com/blang/semver/v4:go_default_library", ], diff --git a/pkg/util/templater/template_functions.go b/pkg/util/templater/template_functions.go index 2f9e2010e4..557658fe23 100644 --- a/pkg/util/templater/template_functions.go +++ b/pkg/util/templater/template_functions.go @@ -24,6 +24,7 @@ import ( "k8s.io/kops" kopsapi "k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/apis/kops/util" + "k8s.io/kops/util/pkg/architectures" ) // templateFuncsMap returns a map if the template functions for this template @@ -63,9 +64,9 @@ func (r *Templater) templateFuncsMap(tm *template.Template) template.FuncMap { } - funcs["ChannelRecommendedImage"] = func(cloud, k8sVersion string) string { + funcs["ChannelRecommendedImage"] = func(cloud, k8sVersion string, architecture architectures.Architecture) string { ver, _ := semver.ParseTolerant(k8sVersion) - imageSpec := r.channel.FindImage(kopsapi.CloudProviderID(cloud), ver) + imageSpec := r.channel.FindImage(kopsapi.CloudProviderID(cloud), ver, architecture) return imageSpec.Name } diff --git a/pkg/util/templater/templater_test.go b/pkg/util/templater/templater_test.go index 38663a3b6b..8156b148d7 100644 --- a/pkg/util/templater/templater_test.go +++ b/pkg/util/templater/templater_test.go @@ -97,8 +97,13 @@ func TestRenderChannelFunctions(t *testing.T) { }, { Context: map[string]interface{}{}, - Template: `{{ ChannelRecommendedImage "aws" "1.4.2" }}`, - Expected: "kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2016-10-21", + Template: `{{ ChannelRecommendedImage "aws" "1.19.2" "amd64" }}`, + Expected: "099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20210119.1", + }, + { + Context: map[string]interface{}{}, + Template: `{{ ChannelRecommendedImage "aws" "1.19.2" "arm64" }}`, + Expected: "099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-arm64-server-20210119.1", }, } makeRenderTests(t, cases) diff --git a/tests/integration/channel/BUILD.bazel b/tests/integration/channel/BUILD.bazel index 708419a41f..db5077be17 100644 --- a/tests/integration/channel/BUILD.bazel +++ b/tests/integration/channel/BUILD.bazel @@ -9,6 +9,7 @@ go_test( deps = [ "//pkg/apis/kops:go_default_library", "//tests/integration/channel/simple:go_default_library", + "//util/pkg/architectures:go_default_library", "//vendor/github.com/blang/semver/v4:go_default_library", ], ) diff --git a/tests/integration/channel/integration_test.go b/tests/integration/channel/integration_test.go index 436d972616..a8a14ec78d 100644 --- a/tests/integration/channel/integration_test.go +++ b/tests/integration/channel/integration_test.go @@ -24,6 +24,7 @@ import ( "github.com/blang/semver/v4" "k8s.io/kops/pkg/apis/kops" "k8s.io/kops/tests/integration/channel/simple" + "k8s.io/kops/util/pkg/architectures" ) // TestKopsUpgrades tests the version logic for kops versions @@ -221,21 +222,35 @@ func TestFindImage(t *testing.T) { grid := []struct { KubernetesVersion string + Architecture string ExpectedImage string }{ { - KubernetesVersion: "1.4.4", - ExpectedImage: "kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2016-10-21", + KubernetesVersion: "1.1.0", + Architecture: "amd64", + ExpectedImage: "kope.io/k8s-1.11-debian-stretch-amd64-hvm-ebs-2021-02-05", }, { - KubernetesVersion: "1.5.1", - ExpectedImage: "kope.io/k8s-1.5-debian-jessie-amd64-hvm-ebs-2017-01-09", + KubernetesVersion: "1.17.2", + Architecture: "amd64", + ExpectedImage: "kope.io/k8s-1.17-debian-stretch-amd64-hvm-ebs-2021-02-05", + }, + { + KubernetesVersion: "1.19.1", + Architecture: "amd64", + ExpectedImage: "099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20210119.1", + }, + { + KubernetesVersion: "1.19.1", + Architecture: "arm64", + ExpectedImage: "099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-arm64-server-20210119.1", }, } for _, g := range grid { kubernetesVersion := semver.MustParse(g.KubernetesVersion) + architecture := architectures.Architecture(g.Architecture) - image := channel.FindImage(kops.CloudProviderAWS, kubernetesVersion) + image := channel.FindImage(kops.CloudProviderAWS, kubernetesVersion, architecture) name := "" if image != nil { name = image.Name diff --git a/tests/integration/channel/simple/channel.yaml b/tests/integration/channel/simple/channel.yaml index d7b35c034b..0ede5f7a4c 100644 --- a/tests/integration/channel/simple/channel.yaml +++ b/tests/integration/channel/simple/channel.yaml @@ -1,12 +1,41 @@ spec: images: - # We put the "legacy" version first, for kops versions that don't support versions ( < 1.5.0 ) - - name: kope.io/k8s-1.4-debian-jessie-amd64-hvm-ebs-2016-10-21 - providerID: aws - kubernetesVersion: ">=1.4.0 <1.5.0" - - name: kope.io/k8s-1.5-debian-jessie-amd64-hvm-ebs-2017-01-09 - providerID: aws - kubernetesVersion: ">=1.5.0" + - name: kope.io/k8s-1.11-debian-stretch-amd64-hvm-ebs-2021-02-05 + providerID: aws + architectureID: amd64 + kubernetesVersion: "<1.12.0" + - name: kope.io/k8s-1.12-debian-stretch-amd64-hvm-ebs-2021-02-05 + providerID: aws + architectureID: amd64 + kubernetesVersion: ">=1.12.0 <1.13.0" + - name: kope.io/k8s-1.13-debian-stretch-amd64-hvm-ebs-2021-02-05 + providerID: aws + architectureID: amd64 + kubernetesVersion: ">=1.13.0 <1.14.0" + - name: kope.io/k8s-1.14-debian-stretch-amd64-hvm-ebs-2021-02-05 + providerID: aws + architectureID: amd64 + kubernetesVersion: ">=1.14.0 <1.15.0" + - name: kope.io/k8s-1.15-debian-stretch-amd64-hvm-ebs-2021-02-05 + providerID: aws + architectureID: amd64 + kubernetesVersion: ">=1.15.0 <1.16.0" + - name: kope.io/k8s-1.16-debian-stretch-amd64-hvm-ebs-2021-02-05 + providerID: aws + architectureID: amd64 + kubernetesVersion: ">=1.16.0 <1.17.0" + - name: kope.io/k8s-1.17-debian-stretch-amd64-hvm-ebs-2021-02-05 + providerID: aws + architectureID: amd64 + kubernetesVersion: ">=1.17.0 <1.18.0" + - name: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20210119.1 + providerID: aws + architectureID: amd64 + kubernetesVersion: ">=1.18.0" + - name: 099720109477/ubuntu/images/hvm-ssd/ubuntu-focal-20.04-arm64-server-20210119.1 + providerID: aws + architectureID: arm64 + kubernetesVersion: ">=1.18.0" cluster: kubernetesVersion: v1.4.7 networking: diff --git a/upup/pkg/fi/cloudup/populate_instancegroup_spec.go b/upup/pkg/fi/cloudup/populate_instancegroup_spec.go index 0a949a1fd7..f9985d1b7f 100644 --- a/upup/pkg/fi/cloudup/populate_instancegroup_spec.go +++ b/upup/pkg/fi/cloudup/populate_instancegroup_spec.go @@ -19,6 +19,7 @@ package cloudup import ( "fmt" + "github.com/aws/aws-sdk-go/service/ec2" "github.com/blang/semver/v4" "k8s.io/klog/v2" "k8s.io/kops/pkg/apis/kops" @@ -27,6 +28,7 @@ import ( "k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi/cloudup/awsup" "k8s.io/kops/upup/pkg/fi/cloudup/openstack" + "k8s.io/kops/util/pkg/architectures" "k8s.io/kops/util/pkg/reflectutils" ) @@ -117,7 +119,11 @@ func PopulateInstanceGroupSpec(cluster *kops.Cluster, input *kops.InstanceGroup, } if ig.Spec.Image == "" { - ig.Spec.Image = defaultImage(cluster, channel) + architecture, err := MachineArchitecture(cloud, ig.Spec.MachineType) + if err != nil { + return nil, fmt.Errorf("unable to determine machine architecture for InstanceGroup %q: %v", ig.ObjectMeta.Name, err) + } + ig.Spec.Image = defaultImage(cluster, channel, architecture) if ig.Spec.Image == "" { return nil, fmt.Errorf("unable to determine default image for InstanceGroup %s", ig.ObjectMeta.Name) } @@ -225,7 +231,7 @@ func defaultMachineType(cloud fi.Cloud, cluster *kops.Cluster, ig *kops.Instance } // defaultImage returns the default Image, based on the cloudprovider -func defaultImage(cluster *kops.Cluster, channel *kops.Channel) string { +func defaultImage(cluster *kops.Cluster, channel *kops.Channel, architecture architectures.Architecture) string { if channel != nil { var kubernetesVersion *semver.Version if cluster.Spec.KubernetesVersion != "" { @@ -236,7 +242,7 @@ func defaultImage(cluster *kops.Cluster, channel *kops.Channel) string { } } if kubernetesVersion != nil { - image := channel.FindImage(kops.CloudProviderID(cluster.Spec.CloudProvider), *kubernetesVersion) + image := channel.FindImage(kops.CloudProviderID(cluster.Spec.CloudProvider), *kubernetesVersion, architecture) if image != nil { return image.Name } @@ -254,3 +260,28 @@ func defaultImage(cluster *kops.Cluster, channel *kops.Channel) string { klog.Infof("Cannot set default Image for CloudProvider=%q", cluster.Spec.CloudProvider) return "" } + +func MachineArchitecture(cloud fi.Cloud, machineType string) (architectures.Architecture, error) { + switch cloud.ProviderID() { + case kops.CloudProviderAWS: + info, err := cloud.(awsup.AWSCloud).DescribeInstanceType(machineType) + if err != nil { + return "", fmt.Errorf("error finding instance info for instance type %q: %v", machineType, err) + } + if info.ProcessorInfo == nil || len(info.ProcessorInfo.SupportedArchitectures) == 0 { + return "", fmt.Errorf("error finding architecture info for instance type %q", machineType) + } + arch := fi.StringValue(info.ProcessorInfo.SupportedArchitectures[0]) + switch arch { + case ec2.ArchitectureTypeX8664: + return architectures.ArchitectureAmd64, nil + case ec2.ArchitectureTypeArm64: + return architectures.ArchitectureArm64, nil + default: + return "", fmt.Errorf("unsupported architecture for instance type %q: %s", machineType, arch) + } + default: + // No other clouds are known to support any other architectures at this time + return architectures.ArchitectureAmd64, nil + } +}