From 96e044d3b9d72b084efd7cefb0949fbe0135555a Mon Sep 17 00:00:00 2001 From: John Gardiner Myers Date: Sat, 22 Feb 2020 15:54:24 -0800 Subject: [PATCH] Remove support for Canal and the vxlan Flannel backend for k8s 1.17+ --- docs/releases/1.17-NOTES.md | 3 ++ pkg/apis/kops/validation/BUILD.bazel | 1 + pkg/apis/kops/validation/legacy.go | 2 +- pkg/apis/kops/validation/validation.go | 31 +++++++++++++++------ pkg/apis/kops/validation/validation_test.go | 5 ++-- 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/docs/releases/1.17-NOTES.md b/docs/releases/1.17-NOTES.md index 324b1dcd7bcff..3f6b0548b6685 100644 --- a/docs/releases/1.17-NOTES.md +++ b/docs/releases/1.17-NOTES.md @@ -13,6 +13,9 @@ the notes prior to the release). * Since 1.16, a controller is now used to apply labels to nodes. If you are not using AWS, GCE or OpenStack your (non-master) nodes may not have labels applied correctly. + +* As of Kubernetes 1.17 the Canal CNI and the "vxlan" backend of the Flannel CNI + are no longer supported due to [a bug in Flannel](https://github.com/coreos/flannel/issues/1243). # Significant changes diff --git a/pkg/apis/kops/validation/BUILD.bazel b/pkg/apis/kops/validation/BUILD.bazel index 13c1dccd5e899..3d209415f4077 100644 --- a/pkg/apis/kops/validation/BUILD.bazel +++ b/pkg/apis/kops/validation/BUILD.bazel @@ -46,6 +46,7 @@ go_test( deps = [ "//pkg/apis/kops:go_default_library", "//upup/pkg/fi:go_default_library", + "//vendor/github.com/blang/semver:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", diff --git a/pkg/apis/kops/validation/legacy.go b/pkg/apis/kops/validation/legacy.go index ef1a86e994571..050f82c654e95 100644 --- a/pkg/apis/kops/validation/legacy.go +++ b/pkg/apis/kops/validation/legacy.go @@ -607,7 +607,7 @@ func ValidateCluster(c *kops.Cluster, strict bool) field.ErrorList { allErrs = append(allErrs, field.Forbidden(fieldSpec.Child("networking"), "amazon-vpc-routed-eni networking is supported only in AWS")) } - allErrs = append(allErrs, newValidateCluster(c)...) + allErrs = append(allErrs, newValidateCluster(c, kubernetesRelease)...) if c.Spec.Networking != nil && c.Spec.Networking.Cilium != nil { ciliumSpec := c.Spec.Networking.Cilium diff --git a/pkg/apis/kops/validation/validation.go b/pkg/apis/kops/validation/validation.go index 7a72fac30625a..cab3433fd9f1d 100644 --- a/pkg/apis/kops/validation/validation.go +++ b/pkg/apis/kops/validation/validation.go @@ -41,9 +41,9 @@ func ValidateDockerConfig(config *kops.DockerConfig, fldPath *field.Path) field. return allErrs } -func newValidateCluster(cluster *kops.Cluster) field.ErrorList { +func newValidateCluster(cluster *kops.Cluster, kubernetesRelease semver.Version) field.ErrorList { allErrs := validation.ValidateObjectMeta(&cluster.ObjectMeta, false, validation.NameIsDNSSubdomain, field.NewPath("metadata")) - allErrs = append(allErrs, validateClusterSpec(&cluster.Spec, field.NewPath("spec"))...) + allErrs = append(allErrs, validateClusterSpec(&cluster.Spec, kubernetesRelease, field.NewPath("spec"))...) // Additional cloud-specific validation rules switch kops.CloudProviderID(cluster.Spec.CloudProvider) { @@ -56,7 +56,7 @@ func newValidateCluster(cluster *kops.Cluster) field.ErrorList { return allErrs } -func validateClusterSpec(spec *kops.ClusterSpec, fieldPath *field.Path) field.ErrorList { +func validateClusterSpec(spec *kops.ClusterSpec, kubernetesRelease semver.Version, fieldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, validateSubnets(spec.Subnets, fieldPath.Child("subnets"))...) @@ -97,7 +97,7 @@ func validateClusterSpec(spec *kops.ClusterSpec, fieldPath *field.Path) field.Er } if spec.Networking != nil { - allErrs = append(allErrs, validateNetworking(spec, spec.Networking, fieldPath.Child("networking"))...) + allErrs = append(allErrs, validateNetworking(spec, kubernetesRelease, fieldPath.Child("networking"))...) if spec.Networking.Calico != nil { allErrs = append(allErrs, validateNetworkingCalico(spec.Networking.Calico, spec.EtcdClusters[0], fieldPath.Child("networking", "calico"))...) } @@ -290,11 +290,16 @@ func validateKubeAPIServer(v *kops.KubeAPIServerConfig, fldPath *field.Path) fie return allErrs } -func validateNetworking(c *kops.ClusterSpec, v *kops.NetworkingSpec, fldPath *field.Path) field.ErrorList { +func validateNetworking(c *kops.ClusterSpec, kubernetesRelease semver.Version, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} + v := c.Networking + + if v.Canal != nil && kubernetesRelease.GTE(semver.MustParse("1.17.0")) { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("canal"), "Canal CNI is not supported as of Kubernetes 1.17")) + } if v.Flannel != nil { - allErrs = append(allErrs, validateNetworkingFlannel(v.Flannel, fldPath.Child("flannel"))...) + allErrs = append(allErrs, validateNetworkingFlannel(v.Flannel, kubernetesRelease, fldPath.Child("flannel"))...) } if v.GCE != nil { @@ -304,16 +309,24 @@ func validateNetworking(c *kops.ClusterSpec, v *kops.NetworkingSpec, fldPath *fi return allErrs } -func validateNetworkingFlannel(v *kops.FlannelNetworkingSpec, fldPath *field.Path) field.ErrorList { +func validateNetworkingFlannel(v *kops.FlannelNetworkingSpec, kubernetesRelease semver.Version, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} switch v.Backend { case "": allErrs = append(allErrs, field.Required(fldPath.Child("backend"), "Flannel backend must be specified")) - case "udp", "vxlan": + case "udp": // OK + case "vxlan": + if kubernetesRelease.GTE(semver.MustParse("1.17.0")) { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("backend"), "vxlan backend is not supported as of Kubernetes 1.17")) + } default: - allErrs = append(allErrs, field.NotSupported(fldPath.Child("backend"), v.Backend, []string{"udp", "vxlan"})) + supported := []string{"udp"} + if kubernetesRelease.LT(semver.MustParse("1.17.0")) { + supported = append(supported, "vxlan") + } + allErrs = append(allErrs, field.NotSupported(fldPath.Child("backend"), v.Backend, supported)) } return allErrs diff --git a/pkg/apis/kops/validation/validation_test.go b/pkg/apis/kops/validation/validation_test.go index 14926805a79e1..2ef1d3052aa63 100644 --- a/pkg/apis/kops/validation/validation_test.go +++ b/pkg/apis/kops/validation/validation_test.go @@ -19,6 +19,7 @@ package validation import ( "testing" + "github.com/blang/semver" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation" @@ -286,7 +287,7 @@ func Test_Validate_Networking_Flannel(t *testing.T) { cluster := &kops.Cluster{} cluster.Spec.Networking = networking - errs := validateNetworking(&cluster.Spec, networking, field.NewPath("networking")) + errs := validateNetworking(&cluster.Spec, semver.MustParse("1.16.0"), field.NewPath("networking")) testErrors(t, g.Input, errs, g.ExpectedErrors) } } @@ -336,7 +337,7 @@ func Test_Validate_AdditionalPolicies(t *testing.T) { {Name: "subnet1"}, }, } - errs := validateClusterSpec(clusterSpec, field.NewPath("spec")) + errs := validateClusterSpec(clusterSpec, semver.MustParse("1.16.0"), field.NewPath("spec")) testErrors(t, g.Input, errs, g.ExpectedErrors) } }