From 6d90881022db47c1f8a49693dd8cb127fc927139 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 | 27 ++++++++++++++------- pkg/apis/kops/validation/validation_test.go | 5 ++-- 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/docs/releases/1.17-NOTES.md b/docs/releases/1.17-NOTES.md index 22899b055c8a7..2565cd604a705 100644 --- a/docs/releases/1.17-NOTES.md +++ b/docs/releases/1.17-NOTES.md @@ -17,6 +17,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). # Required Actions diff --git a/pkg/apis/kops/validation/BUILD.bazel b/pkg/apis/kops/validation/BUILD.bazel index fd4795343a8a5..084d03b9b15ea 100644 --- a/pkg/apis/kops/validation/BUILD.bazel +++ b/pkg/apis/kops/validation/BUILD.bazel @@ -45,6 +45,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 9715bf385c549..dba6e05982a32 100644 --- a/pkg/apis/kops/validation/legacy.go +++ b/pkg/apis/kops/validation/legacy.go @@ -567,7 +567,7 @@ func ValidateCluster(c *kops.Cluster, strict bool) field.ErrorList { } } - allErrs = append(allErrs, newValidateCluster(c)...) + allErrs = append(allErrs, newValidateCluster(c, kubernetesRelease)...) return allErrs } diff --git a/pkg/apis/kops/validation/validation.go b/pkg/apis/kops/validation/validation.go index c1ac0433a5690..b6b3ac6d65015 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, spec.Networking, kubernetesRelease, fieldPath.Child("networking"))...) if spec.Networking.Calico != nil { allErrs = append(allErrs, validateNetworkingCalico(spec.Networking.Calico, spec.EtcdClusters[0], fieldPath.Child("networking", "calico"))...) } @@ -290,7 +290,7 @@ 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, v *kops.NetworkingSpec, kubernetesRelease semver.Version, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} optionTaken := false @@ -336,7 +336,7 @@ func validateNetworking(c *kops.ClusterSpec, v *kops.NetworkingSpec, fldPath *fi } optionTaken = true - allErrs = append(allErrs, validateNetworkingFlannel(v.Flannel, fldPath.Child("flannel"))...) + allErrs = append(allErrs, validateNetworkingFlannel(v.Flannel, kubernetesRelease, fldPath.Child("flannel"))...) } if v.Calico != nil { @@ -352,7 +352,11 @@ func validateNetworking(c *kops.ClusterSpec, v *kops.NetworkingSpec, fldPath *fi } optionTaken = true - allErrs = append(allErrs, validateNetworkingCanal(v.Canal, fldPath.Child("canal"))...) + if 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")) + } else { + allErrs = append(allErrs, validateNetworkingCanal(v.Canal, fldPath.Child("canal"))...) + } } if v.Kuberouter != nil { @@ -412,13 +416,18 @@ 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{} + supported := []string{"udp"} + if kubernetesRelease.LT(semver.MustParse("1.17.0")) { + supported = append(supported, "vxlan") + } + if v.Backend == "" { allErrs = append(allErrs, field.Required(fldPath.Child("backend"), "Flannel backend must be specified")) } else { - allErrs = append(allErrs, IsValidValue(fldPath.Child("backend"), &v.Backend, []string{"udp", "vxlan"})...) + allErrs = append(allErrs, IsValidValue(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 7b525a8fd7c67..f4b918e66542f 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, networking, 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) } }