diff --git a/pkg/addons/default/kube_proxy.go b/pkg/addons/default/kube_proxy.go index c53a2faed1..37135d06b3 100644 --- a/pkg/addons/default/kube_proxy.go +++ b/pkg/addons/default/kube_proxy.go @@ -6,22 +6,19 @@ import ( "sort" "strings" - v1 "k8s.io/api/apps/v1" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/eks" "github.com/aws/aws-sdk-go/service/eks/eksiface" + "github.com/hashicorp/go-version" "github.com/kris-nova/logger" "github.com/pkg/errors" - - "github.com/hashicorp/go-version" - "github.com/weaveworks/eksctl/pkg/addons" - "github.com/weaveworks/eksctl/pkg/printers" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + v1 "k8s.io/api/apps/v1" apierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/weaveworks/eksctl/pkg/addons" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/printers" "github.com/weaveworks/eksctl/pkg/utils" ) @@ -127,7 +124,9 @@ func UpdateKubeProxy(input AddonInput, plan bool) (bool, error) { } if !hasArm64NodeSelector { - addArm64NodeSelector(d, archLabel) + if err := addArm64NodeSelector(d, archLabel); err != nil { + return false, err + } } if _, err := input.RawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Update(context.TODO(), d, metav1.UpdateOptions{}); err != nil { @@ -157,16 +156,20 @@ func daemeonSetHasArm64NodeSelector(daemonSet *v1.DaemonSet, archLabel string) b return false } -func addArm64NodeSelector(daemonSet *v1.DaemonSet, archLabel string) { - for nodeSelectorTermsIndex, nodeSelectorTerms := range daemonSet.Spec.Template.Spec.Affinity.NodeAffinity. - RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { - for nodeSelectorIndex, nodeSelector := range nodeSelectorTerms.MatchExpressions { - if nodeSelector.Key == archLabel { - daemonSet.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution. - NodeSelectorTerms[nodeSelectorTermsIndex].MatchExpressions[nodeSelectorIndex].Values = append(nodeSelector.Values, "arm64") +func addArm64NodeSelector(daemonSet *v1.DaemonSet, archLabel string) error { + if daemonSet.Spec.Template.Spec.Affinity != nil && daemonSet.Spec.Template.Spec.Affinity.NodeAffinity != nil { + for nodeSelectorTermsIndex, nodeSelectorTerms := range daemonSet.Spec.Template.Spec.Affinity.NodeAffinity. + RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { + for nodeSelectorIndex, nodeSelector := range nodeSelectorTerms.MatchExpressions { + if nodeSelector.Key == archLabel { + daemonSet.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution. + NodeSelectorTerms[nodeSelectorTermsIndex].MatchExpressions[nodeSelectorIndex].Values = append(nodeSelector.Values, "arm64") + } } } + return nil } + return fmt.Errorf("NodeAffinity not configured on kube-proxy. Either manually update the proxy deployment, or switch to Managed Addons") } func getLatestKubeProxyImage(input AddonInput, greaterThanOrEqualTo1_18 bool) (string, error) { diff --git a/pkg/addons/default/kube_proxy_test.go b/pkg/addons/default/kube_proxy_test.go index 131cbb0a85..06b3de9b51 100644 --- a/pkg/addons/default/kube_proxy_test.go +++ b/pkg/addons/default/kube_proxy_test.go @@ -5,16 +5,15 @@ import ( "fmt" "github.com/aws/aws-sdk-go/aws" + awseks "github.com/aws/aws-sdk-go/service/eks" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - awseks "github.com/aws/aws-sdk-go/service/eks" da "github.com/weaveworks/eksctl/pkg/addons/default" "github.com/weaveworks/eksctl/pkg/kubernetes" "github.com/weaveworks/eksctl/pkg/testutils" "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) var _ = Describe("KubeProxy", func() { @@ -118,6 +117,24 @@ var _ = Describe("KubeProxy", func() { Expect(kubeProxyImage(clientSet)).To(Equal("602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxy:v1.15.11")) }) + When("nodeaffinity is not set on kube-proxy", func() { + BeforeEach(func() { + rawClient := testutils.NewFakeRawClientWithSamples("testdata/sample-old-kube-proxy-amd.json") + clientSet = rawClient.ClientSet() + mockProvider = mockprovider.NewMockProvider() + input = da.AddonInput{ + RawClient: rawClient, + ControlPlaneVersion: "1.16.0", + Region: "eu-west-1", + EKSAPI: mockProvider.EKS(), + } + }) + It("errors", func() { + _, err := da.UpdateKubeProxy(input, false) + Expect(err).To(MatchError(ContainSubstring("NodeAffinity not configured on kube-proxy. Either manually update the proxy deployment, or switch to Managed Addons"))) + }) + }) + When("the cluster version is 1.18 or newer", func() { BeforeEach(func() { input.ControlPlaneVersion = "1.18.1" diff --git a/pkg/addons/default/testdata/sample-old-kube-proxy-amd.json b/pkg/addons/default/testdata/sample-old-kube-proxy-amd.json new file mode 100644 index 0000000000..e93035c9e8 --- /dev/null +++ b/pkg/addons/default/testdata/sample-old-kube-proxy-amd.json @@ -0,0 +1,141 @@ +{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "apps/v1", + "kind": "DaemonSet", + "metadata": { + "annotations": { + "deprecated.daemonset.template.generation": "10", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"extensions/v1beta1\",\"kind\":\"DaemonSet\",\"metadata\":{\"annotations\":{},\"labels\":{\"eks.amazonaws.com/component\":\"kube-proxy\",\"k8s-app\":\"kube-proxy\"},\"name\":\"kube-proxy\",\"namespace\":\"kube-system\"},\"spec\":{\"selector\":{\"matchLabels\":{\"k8s-app\":\"kube-proxy\"}},\"template\":{\"metadata\":{\"annotations\":{\"scheduler.alpha.kubernetes.io/critical-pod\":\"\"},\"labels\":{\"k8s-app\":\"kube-proxy\"}},\"spec\":{\"containers\":[{\"command\":[\"/bin/sh\",\"-c\",\"kube-proxy --resource-container=\\\"\\\" --oom-score-adj=-998 --master=https://59eba41dbb3e69921e4d0af76b2814ee.yl4.us-east-1.eks.amazonaws.com --kubeconfig=/var/lib/kube-proxy/kubeconfig --proxy-mode=iptables --v=2 1\\u003e\\u003e/var/log/kube-proxy.log 2\\u003e\\u00261\"],\"image\":\"602401143452.dkr.ecr.us-east-1.amazonaws.com/eks/kube-proxy:v1.10.3\",\"name\":\"kube-proxy\",\"resources\":{\"requests\":{\"cpu\":\"100m\"}},\"securityContext\":{\"privileged\":true},\"volumeMounts\":[{\"mountPath\":\"/var/log\",\"name\":\"varlog\",\"readOnly\":false},{\"mountPath\":\"/run/xtables.lock\",\"name\":\"xtables-lock\",\"readOnly\":false},{\"mountPath\":\"/var/lib/kube-proxy/\",\"name\":\"kubeconfig\"}]}],\"hostNetwork\":true,\"serviceAccountName\":\"kube-proxy\",\"tolerations\":[{\"effect\":\"NoExecute\",\"operator\":\"Exists\"},{\"effect\":\"NoSchedule\",\"operator\":\"Exists\"}],\"volumes\":[{\"hostPath\":{\"path\":\"/var/log\"},\"name\":\"varlog\"},{\"hostPath\":{\"path\":\"/run/xtables.lock\",\"type\":\"FileOrCreate\"},\"name\":\"xtables-lock\"},{\"configMap\":{\"name\":\"kube-proxy\"},\"name\":\"kubeconfig\"}]}},\"updateStrategy\":{\"rollingUpdate\":{\"maxUnavailable\":\"10%\"},\"type\":\"RollingUpdate\"}}}\n" + }, + "creationTimestamp": "2018-08-29T12:55:10Z", + "generation": 10, + "labels": { + "eks.amazonaws.com/component": "kube-proxy", + "k8s-app": "kube-proxy" + }, + "name": "kube-proxy", + "namespace": "kube-system", + "resourceVersion": "196859403", + "selfLink": "/apis/apps/v1/namespaces/kube-system/daemonsets/kube-proxy", + "uid": "c339a828-ab8a-11e8-a044-12c352781cb6" + }, + "spec": { + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "k8s-app": "kube-proxy" + } + }, + "template": { + "metadata": { + "annotations": { + "scheduler.alpha.kubernetes.io/critical-pod": "" + }, + "creationTimestamp": null, + "labels": { + "k8s-app": "kube-proxy" + } + }, + "spec": { + "containers": [ + { + "command": [ + "/bin/sh", + "-c", + "kube-proxy --resource-container=\"\" --oom-score-adj=-998 --master=https://59eba41dbb3e69921e4d0af76b2814ee.yl4.us-east-1.eks.amazonaws.com --kubeconfig=/var/lib/kube-proxy/kubeconfig --proxy-mode=iptables --v=2 1>>/var/log/kube-proxy.log 2>&1" + ], + "image": "602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/kube-proxy:v1.15.11", + "imagePullPolicy": "IfNotPresent", + "name": "kube-proxy", + "resources": { + "requests": { + "cpu": "100m" + } + }, + "securityContext": { + "privileged": true, + "procMount": "Default" + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/log", + "name": "varlog" + }, + { + "mountPath": "/run/xtables.lock", + "name": "xtables-lock" + }, + { + "mountPath": "/var/lib/kube-proxy/", + "name": "kubeconfig" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": true, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "kube-proxy", + "serviceAccountName": "kube-proxy", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "operator": "Exists" + }, + { + "effect": "NoSchedule", + "operator": "Exists" + } + ], + "volumes": [ + { + "hostPath": { + "path": "/var/log", + "type": "" + }, + "name": "varlog" + }, + { + "hostPath": { + "path": "/run/xtables.lock", + "type": "FileOrCreate" + }, + "name": "xtables-lock" + }, + { + "configMap": { + "defaultMode": 420, + "name": "kube-proxy" + }, + "name": "kubeconfig" + } + ] + } + }, + "updateStrategy": { + "rollingUpdate": { + "maxUnavailable": "10%" + }, + "type": "RollingUpdate" + } + }, + "status": { + "currentNumberScheduled": 3, + "desiredNumberScheduled": 3, + "numberAvailable": 3, + "numberMisscheduled": 0, + "numberReady": 3, + "observedGeneration": 10, + "updatedNumberScheduled": 3 + } + } + ], + "kind": "List" +}