From b0d7c2bd2c60a94be28c2f017d6c5a93a8cc4285 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Tue, 5 Oct 2021 15:05:32 +0200 Subject: [PATCH 1/8] Check if managed addons are set when ipv6 is enabled --- examples/29-vpc-with-ip-family.yaml | 5 ++++ pkg/apis/eksctl.io/v1alpha5/validation.go | 24 +++++++++++++++++++ .../eksctl.io/v1alpha5/validation_test.go | 16 +++++++++++++ userdocs/src/usage/vpc-networking.md | 7 +++++- 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/examples/29-vpc-with-ip-family.yaml b/examples/29-vpc-with-ip-family.yaml index 78792bf93a..e093d7f885 100644 --- a/examples/29-vpc-with-ip-family.yaml +++ b/examples/29-vpc-with-ip-family.yaml @@ -11,4 +11,9 @@ metadata: vpc: ipFamily: IPv6 +addons: + - name: vpc-cni + - name: coredns + - name: kube-proxy + managedNodeGroups: [] diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index d22c75ac34..03f97cf2a5 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -169,10 +169,34 @@ func (c *ClusterConfig) ValidateVPCConfig() error { if *v != string(IPV4Family) && *v != string(IPV6Family) { return fmt.Errorf("invalid value %s for ipFamily; allowed are %s and %s", *v, IPV4Family, IPV6Family) } + // This is the new vpc check, I need this check when the user sets it. + if *v == string(IPV6Family) { + if missing := c.addonContainsManagedAddons([]string{"vpc-cni", "coredns", "kube-proxy"}); len(missing) != 0 { + return fmt.Errorf("managed addons must be defined in case of IPv6; missing addon(s): %s", strings.Join(missing, ", ")) + } + } } return nil } +// addonContainsManagedAddons finds managed addons in the config and returns those it couldn't find. +func (c *ClusterConfig) addonContainsManagedAddons(addons []string) []string { + var missing []string + for _, a := range addons { + found := false + for _, add := range c.Addons { + if strings.ToLower(add.Name) == a { + found = true + break + } + } + if !found { + missing = append(missing, a) + } + } + return missing +} + // ValidateClusterEndpointConfig checks the endpoint configuration for potential issues func (c *ClusterConfig) ValidateClusterEndpointConfig() error { if !c.HasClusterEndpointAccess() { diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index 269097a8b0..d763a1df40 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -546,10 +546,26 @@ var _ = Describe("ClusterConfig validation", func() { It("accepts that setting", func() { ipv6 := string(api.IPV6Family) cfg.VPC.IPFamily = &ipv6 + cfg.Addons = append(cfg.Addons, + &api.Addon{Name: "kube-proxy"}, + &api.Addon{Name: "coredns"}, + &api.Addon{Name: "vpc-cni"}, + ) err = cfg.ValidateVPCConfig() Expect(err).ToNot(HaveOccurred()) }) }) + When("ipFamily is set ot IPv6 but no managed addons are provided", func() { + It("it returns an error including which addons are missing", func() { + ipv6 := string(api.IPV6Family) + cfg.VPC.IPFamily = &ipv6 + cfg.Addons = append(cfg.Addons, + &api.Addon{Name: "kube-proxy"}, + ) + err = cfg.ValidateVPCConfig() + Expect(err).To(MatchError(ContainSubstring("managed addons must be defined in case of IPv6; missing addon(s): vpc-cni, coredns"))) + }) + }) When("ipFamily isn't IPv4 or IPv6", func() { It("returns an error", func() { invalid := "invalid" diff --git a/userdocs/src/usage/vpc-networking.md b/userdocs/src/usage/vpc-networking.md index fe861a7462..bfb773a3d4 100644 --- a/userdocs/src/usage/vpc-networking.md +++ b/userdocs/src/usage/vpc-networking.md @@ -40,9 +40,14 @@ metadata: vpc: ipFamily: IPv6 # or IPv4 + +addons: + - name: vpc-cni + - name: coredns + - name: kube-proxy ``` -This is an in config file setting only. The default value is `IPv4`. +This is an in config file setting only and managed addons need to be defined when IPv6 is set. The default value is `IPv4`. ## Change VPC CIDR From f3e3d1a17afe67fde8895249ed94c087ae652b8b Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Tue, 5 Oct 2021 15:47:31 +0200 Subject: [PATCH 2/8] Add OIDC check for ipv6 cluster --- examples/29-vpc-with-ip-family.yaml | 3 ++ pkg/apis/eksctl.io/v1alpha5/validation.go | 3 ++ .../eksctl.io/v1alpha5/validation_test.go | 35 +++++++++++++++++++ userdocs/src/usage/vpc-networking.md | 6 +++- 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/examples/29-vpc-with-ip-family.yaml b/examples/29-vpc-with-ip-family.yaml index e093d7f885..65a07b5c2f 100644 --- a/examples/29-vpc-with-ip-family.yaml +++ b/examples/29-vpc-with-ip-family.yaml @@ -16,4 +16,7 @@ addons: - name: coredns - name: kube-proxy +iam: + withOIDC: true + managedNodeGroups: [] diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 03f97cf2a5..467c040ee8 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -174,6 +174,9 @@ func (c *ClusterConfig) ValidateVPCConfig() error { if missing := c.addonContainsManagedAddons([]string{"vpc-cni", "coredns", "kube-proxy"}); len(missing) != 0 { return fmt.Errorf("managed addons must be defined in case of IPv6; missing addon(s): %s", strings.Join(missing, ", ")) } + if c.IAM == nil || c.IAM != nil && !IsEnabled(c.IAM.WithOIDC) { + return fmt.Errorf("oidc needs to be enabled if IPv6 is set") + } } } return nil diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index d763a1df40..dfb3e30210 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -551,6 +551,9 @@ var _ = Describe("ClusterConfig validation", func() { &api.Addon{Name: "coredns"}, &api.Addon{Name: "vpc-cni"}, ) + cfg.IAM = &api.ClusterIAM{ + WithOIDC: api.Enabled(), + } err = cfg.ValidateVPCConfig() Expect(err).ToNot(HaveOccurred()) }) @@ -559,6 +562,9 @@ var _ = Describe("ClusterConfig validation", func() { It("it returns an error including which addons are missing", func() { ipv6 := string(api.IPV6Family) cfg.VPC.IPFamily = &ipv6 + cfg.IAM = &api.ClusterIAM{ + WithOIDC: api.Enabled(), + } cfg.Addons = append(cfg.Addons, &api.Addon{Name: "kube-proxy"}, ) @@ -566,6 +572,35 @@ var _ = Describe("ClusterConfig validation", func() { Expect(err).To(MatchError(ContainSubstring("managed addons must be defined in case of IPv6; missing addon(s): vpc-cni, coredns"))) }) }) + When("iam is not set", func() { + It("returns an error", func() { + ipv6 := string(api.IPV6Family) + cfg.VPC.IPFamily = &ipv6 + cfg.Addons = append(cfg.Addons, + &api.Addon{Name: "kube-proxy"}, + &api.Addon{Name: "coredns"}, + &api.Addon{Name: "vpc-cni"}, + ) + err = cfg.ValidateVPCConfig() + Expect(err).To(MatchError(ContainSubstring("oidc needs to be enabled if IPv6 is set"))) + }) + }) + When("iam is set but OIDC is disabled", func() { + It("returns an error", func() { + ipv6 := string(api.IPV6Family) + cfg.VPC.IPFamily = &ipv6 + cfg.IAM = &api.ClusterIAM{ + WithOIDC: api.Disabled(), + } + cfg.Addons = append(cfg.Addons, + &api.Addon{Name: "kube-proxy"}, + &api.Addon{Name: "coredns"}, + &api.Addon{Name: "vpc-cni"}, + ) + err = cfg.ValidateVPCConfig() + Expect(err).To(MatchError(ContainSubstring("oidc needs to be enabled if IPv6 is set"))) + }) + }) When("ipFamily isn't IPv4 or IPv6", func() { It("returns an error", func() { invalid := "invalid" diff --git a/userdocs/src/usage/vpc-networking.md b/userdocs/src/usage/vpc-networking.md index bfb773a3d4..8a3b97fcc3 100644 --- a/userdocs/src/usage/vpc-networking.md +++ b/userdocs/src/usage/vpc-networking.md @@ -45,9 +45,13 @@ addons: - name: vpc-cni - name: coredns - name: kube-proxy + +iam: + withOIDC: true ``` -This is an in config file setting only and managed addons need to be defined when IPv6 is set. The default value is `IPv4`. +This is an in config file setting only. Managed addons need to be defined when IPv6 is set along with OIDC. +The default value is `IPv4`. ## Change VPC CIDR From 46668695b8e2c746538eeea3a050dd47375a22f5 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Tue, 5 Oct 2021 16:49:31 +0200 Subject: [PATCH 3/8] Add version check if ipv6 is defined --- examples/29-vpc-with-ip-family.yaml | 1 + pkg/apis/eksctl.io/v1alpha5/validation.go | 17 ++++++++++----- .../eksctl.io/v1alpha5/validation_test.go | 21 +++++++++++++++++++ pkg/ctl/cmdutils/configfile_test.go | 2 +- pkg/utils/utils.go | 2 +- userdocs/src/usage/vpc-networking.md | 8 ++++++- 6 files changed, 43 insertions(+), 8 deletions(-) diff --git a/examples/29-vpc-with-ip-family.yaml b/examples/29-vpc-with-ip-family.yaml index 65a07b5c2f..8d2e9ba73f 100644 --- a/examples/29-vpc-with-ip-family.yaml +++ b/examples/29-vpc-with-ip-family.yaml @@ -7,6 +7,7 @@ kind: ClusterConfig metadata: name: cluster-2 region: eu-north-1 + version: "1.21" vpc: ipFamily: IPv6 diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 467c040ee8..e112d84af1 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -14,6 +14,7 @@ import ( corev1 "k8s.io/api/core/v1" + "github.com/weaveworks/eksctl/pkg/utils" "github.com/weaveworks/eksctl/pkg/utils/taints" "k8s.io/apimachinery/pkg/util/validation" @@ -138,11 +139,6 @@ func ValidateClusterConfig(cfg *ClusterConfig) error { return errors.New("field secretsEncryption.keyARN is required for enabling secrets encryption") } - // manageSharedNodeSecurityGroupRules cannot be disabled if using eksctl managed security groups - if cfg.VPC != nil && cfg.VPC.SharedNodeSecurityGroup == "" && IsDisabled(cfg.VPC.ManageSharedNodeSecurityGroupRules) { - return errors.New("vpc.manageSharedNodeSecurityGroupRules must be enabled when using ekstcl-managed security groups") - } - return nil } @@ -177,8 +173,19 @@ func (c *ClusterConfig) ValidateVPCConfig() error { if c.IAM == nil || c.IAM != nil && !IsEnabled(c.IAM.WithOIDC) { return fmt.Errorf("oidc needs to be enabled if IPv6 is set") } + + if version, err := utils.CompareVersions(c.Metadata.Version, Version1_21); err != nil { + return fmt.Errorf("failed to convert %s cluster version to semver: %w", c.Metadata.Version, err) + } else if err == nil && version == -1 { + return fmt.Errorf("cluster version must be >= %s", Version1_21) + } } } + + // manageSharedNodeSecurityGroupRules cannot be disabled if using eksctl managed security groups + if c.VPC.SharedNodeSecurityGroup == "" && IsDisabled(c.VPC.ManageSharedNodeSecurityGroupRules) { + return errors.New("vpc.manageSharedNodeSecurityGroupRules must be enabled when using ekstcl-managed security groups") + } return nil } diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index dfb3e30210..fb5eb256b7 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -554,10 +554,31 @@ var _ = Describe("ClusterConfig validation", func() { cfg.IAM = &api.ClusterIAM{ WithOIDC: api.Enabled(), } + cfg.Metadata.Version = api.Version1_21 err = cfg.ValidateVPCConfig() Expect(err).ToNot(HaveOccurred()) }) }) + When("ipFamily is set ot IPv6 but version is not or too low", func() { + It("returns an error", func() { + ipv6 := string(api.IPV6Family) + cfg.VPC.IPFamily = &ipv6 + cfg.Addons = append(cfg.Addons, + &api.Addon{Name: "kube-proxy"}, + &api.Addon{Name: "coredns"}, + &api.Addon{Name: "vpc-cni"}, + ) + cfg.IAM = &api.ClusterIAM{ + WithOIDC: api.Enabled(), + } + cfg.Metadata.Version = "" + err = cfg.ValidateVPCConfig() + Expect(err).To(MatchError(ContainSubstring("failed to convert cluster version to semver: unable to parse first version"))) + cfg.Metadata.Version = api.Version1_12 + err = cfg.ValidateVPCConfig() + Expect(err).To(MatchError(ContainSubstring("cluster version must be >= 1.21"))) + }) + }) When("ipFamily is set ot IPv6 but no managed addons are provided", func() { It("it returns an error including which addons are missing", func() { ipv6 := string(api.IPV6Family) diff --git a/pkg/ctl/cmdutils/configfile_test.go b/pkg/ctl/cmdutils/configfile_test.go index 6afd08c98c..93281c3542 100644 --- a/pkg/ctl/cmdutils/configfile_test.go +++ b/pkg/ctl/cmdutils/configfile_test.go @@ -156,9 +156,9 @@ var _ = Describe("cmdutils configfile", func() { } err := NewMetadataLoader(cmd).Load() + Expect(err).ToNot(HaveOccurred()) cfg := cmd.ClusterConfig - Expect(err).ToNot(HaveOccurred()) Expect(cfg.Metadata.Name).ToNot(BeEmpty()) Expect(cfg.Metadata.Region).ToNot(BeEmpty()) Expect(cfg.Metadata.Region).To(Equal(cmd.ProviderConfig.Region)) diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 1de713e33b..bfe395d887 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -62,7 +62,7 @@ func IsMinVersion(minimumVersion, version string) (bool, error) { // CompareVersions compares two version strings with the usual conventions: // returns 0 if a == b // returns 1 if a > b -// returns -1 if b < a +// returns -1 if a < b func CompareVersions(a, b string) (int, error) { aVersion, err := semver.ParseTolerant(a) if err != nil { diff --git a/userdocs/src/usage/vpc-networking.md b/userdocs/src/usage/vpc-networking.md index 8a3b97fcc3..dc3d415127 100644 --- a/userdocs/src/usage/vpc-networking.md +++ b/userdocs/src/usage/vpc-networking.md @@ -37,6 +37,7 @@ kind: ClusterConfig metadata: name: my-test region: us-west-2 + version: "1.21" vpc: ipFamily: IPv6 # or IPv4 @@ -50,7 +51,12 @@ iam: withOIDC: true ``` -This is an in config file setting only. Managed addons need to be defined when IPv6 is set along with OIDC. +This is an in config file setting only. When IPv6 is set, the following restriction must be followed: + +- OIDC is enabled +- managed addons are defined as shows above +- version must be => 1.21 + The default value is `IPv4`. ## Change VPC CIDR From ebe72a7ee61d62b312454b13870a1a0d6bd64a21 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Wed, 6 Oct 2021 12:50:30 +0200 Subject: [PATCH 4/8] Setting vpc.NAT is not allowed with ipv6 --- pkg/apis/eksctl.io/v1alpha5/validation.go | 4 ++++ .../eksctl.io/v1alpha5/validation_test.go | 21 +++++++++++++++++++ userdocs/src/usage/vpc-networking.md | 1 + 3 files changed, 26 insertions(+) diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index e112d84af1..237ecb07a5 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -179,6 +179,10 @@ func (c *ClusterConfig) ValidateVPCConfig() error { } else if err == nil && version == -1 { return fmt.Errorf("cluster version must be >= %s", Version1_21) } + + if c.VPC.NAT != nil { + return fmt.Errorf("setting NAT is not supported with IPv6") + } } } diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index fb5eb256b7..cb1f8ebec4 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -545,6 +545,7 @@ var _ = Describe("ClusterConfig validation", func() { When("ipFamily is set ot IPv6", func() { It("accepts that setting", func() { ipv6 := string(api.IPV6Family) + cfg.VPC.NAT = nil cfg.VPC.IPFamily = &ipv6 cfg.Addons = append(cfg.Addons, &api.Addon{Name: "kube-proxy"}, @@ -563,6 +564,7 @@ var _ = Describe("ClusterConfig validation", func() { It("returns an error", func() { ipv6 := string(api.IPV6Family) cfg.VPC.IPFamily = &ipv6 + cfg.VPC.NAT = nil cfg.Addons = append(cfg.Addons, &api.Addon{Name: "kube-proxy"}, &api.Addon{Name: "coredns"}, @@ -582,6 +584,7 @@ var _ = Describe("ClusterConfig validation", func() { When("ipFamily is set ot IPv6 but no managed addons are provided", func() { It("it returns an error including which addons are missing", func() { ipv6 := string(api.IPV6Family) + cfg.VPC.NAT = nil cfg.VPC.IPFamily = &ipv6 cfg.IAM = &api.ClusterIAM{ WithOIDC: api.Enabled(), @@ -630,6 +633,24 @@ var _ = Describe("ClusterConfig validation", func() { Expect(err).To(MatchError(ContainSubstring("invalid value invalid for ipFamily; allowed are IPv4 and IPv6"))) }) }) + When("ipFamily is set to IPv6 and vpc.NAT is defined", func() { + It("it returns an error", func() { + ipv6 := string(api.IPV6Family) + cfg.VPC.IPFamily = &ipv6 + cfg.Metadata.Version = api.Version1_22 + cfg.IAM = &api.ClusterIAM{ + WithOIDC: api.Enabled(), + } + cfg.Addons = append(cfg.Addons, + &api.Addon{Name: "kube-proxy"}, + &api.Addon{Name: "coredns"}, + &api.Addon{Name: "vpc-cni"}, + ) + cfg.VPC.NAT = &api.ClusterNAT{} + err = cfg.ValidateVPCConfig() + Expect(err).To(MatchError(ContainSubstring("setting NAT is not supported with IPv6"))) + }) + }) }) Context("CIDRs", func() { diff --git a/userdocs/src/usage/vpc-networking.md b/userdocs/src/usage/vpc-networking.md index dc3d415127..3a0a80e15c 100644 --- a/userdocs/src/usage/vpc-networking.md +++ b/userdocs/src/usage/vpc-networking.md @@ -56,6 +56,7 @@ This is an in config file setting only. When IPv6 is set, the following restrict - OIDC is enabled - managed addons are defined as shows above - version must be => 1.21 +- setting vpc.NAT is not allowed The default value is `IPv4`. From 9fdc6679bcbe21695b295ac51365854eda209ddb Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Wed, 6 Oct 2021 15:01:52 +0200 Subject: [PATCH 5/8] serviceIPv4CIDR is not supported with ipv6 --- examples/29-vpc-with-ip-family.yaml | 2 +- pkg/apis/eksctl.io/v1alpha5/validation.go | 4 ++++ .../eksctl.io/v1alpha5/validation_test.go | 21 +++++++++++++++++++ userdocs/src/usage/vpc-networking.md | 1 + 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/examples/29-vpc-with-ip-family.yaml b/examples/29-vpc-with-ip-family.yaml index 8d2e9ba73f..b1824ffa25 100644 --- a/examples/29-vpc-with-ip-family.yaml +++ b/examples/29-vpc-with-ip-family.yaml @@ -15,7 +15,7 @@ vpc: addons: - name: vpc-cni - name: coredns - - name: kube-proxy + - name: kube-proxy iam: withOIDC: true diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 237ecb07a5..cd444ee4d5 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -183,6 +183,10 @@ func (c *ClusterConfig) ValidateVPCConfig() error { if c.VPC.NAT != nil { return fmt.Errorf("setting NAT is not supported with IPv6") } + + if c.KubernetesNetworkConfig != nil && c.KubernetesNetworkConfig.ServiceIPv4CIDR != "" { + return fmt.Errorf("service ipv4 cidr is not supported with IPv6") + } } } diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index cb1f8ebec4..a085bfb1a9 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -651,6 +651,27 @@ var _ = Describe("ClusterConfig validation", func() { Expect(err).To(MatchError(ContainSubstring("setting NAT is not supported with IPv6"))) }) }) + When("ipFamily is set to IPv6 and serviceIPv4CIDR is not empty", func() { + It("it returns an error", func() { + ipv6 := string(api.IPV6Family) + cfg.VPC.IPFamily = &ipv6 + cfg.Metadata.Version = api.Version1_22 + cfg.IAM = &api.ClusterIAM{ + WithOIDC: api.Enabled(), + } + cfg.Addons = append(cfg.Addons, + &api.Addon{Name: "kube-proxy"}, + &api.Addon{Name: "coredns"}, + &api.Addon{Name: "vpc-cni"}, + ) + cfg.KubernetesNetworkConfig = &api.KubernetesNetworkConfig{ + ServiceIPv4CIDR: "192.168.0.0/24", + } + cfg.VPC.NAT = nil + err = cfg.ValidateVPCConfig() + Expect(err).To(MatchError(ContainSubstring("service ipv4 cidr is not supported with IPv6"))) + }) + }) }) Context("CIDRs", func() { diff --git a/userdocs/src/usage/vpc-networking.md b/userdocs/src/usage/vpc-networking.md index 3a0a80e15c..10fae907a8 100644 --- a/userdocs/src/usage/vpc-networking.md +++ b/userdocs/src/usage/vpc-networking.md @@ -57,6 +57,7 @@ This is an in config file setting only. When IPv6 is set, the following restrict - managed addons are defined as shows above - version must be => 1.21 - setting vpc.NAT is not allowed +- serviceIPv4CIDR is not supported together with IPv6 The default value is `IPv4`. From cbb0d74f7fb2344a2336862c18ee7786ec654893 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Wed, 6 Oct 2021 15:53:24 +0200 Subject: [PATCH 6/8] AutoAllocateIPv6 is not supported together with ipv6 --- pkg/apis/eksctl.io/v1alpha5/validation.go | 4 +++ .../eksctl.io/v1alpha5/validation_test.go | 31 +++++++++++++++---- userdocs/src/usage/vpc-networking.md | 1 + 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index de9e90893d..55fd50ab47 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -187,6 +187,10 @@ func (c *ClusterConfig) ValidateVPCConfig() error { if c.KubernetesNetworkConfig != nil && c.KubernetesNetworkConfig.ServiceIPv4CIDR != "" { return fmt.Errorf("service ipv4 cidr is not supported with IPv6") } + + if IsEnabled(c.VPC.AutoAllocateIPv6) { + return fmt.Errorf("auto allocate ipv6 is not supported with IPv6") + } } } diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index 61d4c68c13..f9e6e509d5 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -640,9 +640,9 @@ var _ = Describe("ClusterConfig validation", func() { WithOIDC: api.Enabled(), } cfg.Addons = append(cfg.Addons, - &api.Addon{Name: "kube-proxy"}, - &api.Addon{Name: "coredns"}, - &api.Addon{Name: "vpc-cni"}, + &api.Addon{Name: api.KubeProxyAddon}, + &api.Addon{Name: api.CoreDNSAddon}, + &api.Addon{Name: api.VPCCNIAddon}, ) cfg.VPC.NAT = &api.ClusterNAT{} err = cfg.ValidateVPCConfig() @@ -658,9 +658,9 @@ var _ = Describe("ClusterConfig validation", func() { WithOIDC: api.Enabled(), } cfg.Addons = append(cfg.Addons, - &api.Addon{Name: "kube-proxy"}, - &api.Addon{Name: "coredns"}, - &api.Addon{Name: "vpc-cni"}, + &api.Addon{Name: api.KubeProxyAddon}, + &api.Addon{Name: api.CoreDNSAddon}, + &api.Addon{Name: api.VPCCNIAddon}, ) cfg.KubernetesNetworkConfig = &api.KubernetesNetworkConfig{ ServiceIPv4CIDR: "192.168.0.0/24", @@ -670,6 +670,25 @@ var _ = Describe("ClusterConfig validation", func() { Expect(err).To(MatchError(ContainSubstring("service ipv4 cidr is not supported with IPv6"))) }) }) + When("ipFamily is set to IPv6 and AutoAllocateIPv6 is set", func() { + It("it returns an error", func() { + ipv6 := string(api.IPV6Family) + cfg.VPC.IPFamily = &ipv6 + cfg.VPC.AutoAllocateIPv6 = api.Enabled() + cfg.Metadata.Version = api.Version1_22 + cfg.IAM = &api.ClusterIAM{ + WithOIDC: api.Enabled(), + } + cfg.Addons = append(cfg.Addons, + &api.Addon{Name: api.KubeProxyAddon}, + &api.Addon{Name: api.CoreDNSAddon}, + &api.Addon{Name: api.VPCCNIAddon}, + ) + cfg.VPC.NAT = nil + err = cfg.ValidateVPCConfig() + Expect(err).To(MatchError(ContainSubstring("auto allocate ipv6 is not supported with IPv6"))) + }) + }) }) Context("CIDRs", func() { diff --git a/userdocs/src/usage/vpc-networking.md b/userdocs/src/usage/vpc-networking.md index 10fae907a8..cea55a23a7 100644 --- a/userdocs/src/usage/vpc-networking.md +++ b/userdocs/src/usage/vpc-networking.md @@ -58,6 +58,7 @@ This is an in config file setting only. When IPv6 is set, the following restrict - version must be => 1.21 - setting vpc.NAT is not allowed - serviceIPv4CIDR is not supported together with IPv6 +- AutoAllocateIPv6 is not supported together with IPv6 The default value is `IPv4`. From 6ccf8a3583bc4f072bbaea1785382830a59b503c Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Wed, 6 Oct 2021 17:20:39 +0200 Subject: [PATCH 7/8] Unmanaged nodegroups are not supported --- pkg/actions/nodegroup/create.go | 5 +++ pkg/actions/nodegroup/create_test.go | 50 ++++++++++++++++++++++++++++ pkg/apis/eksctl.io/v1alpha5/types.go | 4 +-- pkg/utils/strings/strings.go | 8 +++++ userdocs/src/usage/vpc-networking.md | 1 + 5 files changed, 66 insertions(+), 2 deletions(-) diff --git a/pkg/actions/nodegroup/create.go b/pkg/actions/nodegroup/create.go index 57205cc409..5924d066bd 100644 --- a/pkg/actions/nodegroup/create.go +++ b/pkg/actions/nodegroup/create.go @@ -15,6 +15,7 @@ import ( "github.com/weaveworks/eksctl/pkg/kubernetes" "github.com/weaveworks/eksctl/pkg/printers" "github.com/weaveworks/eksctl/pkg/utils" + utilsstrings "github.com/weaveworks/eksctl/pkg/utils/strings" "github.com/weaveworks/eksctl/pkg/utils/tasks" "github.com/weaveworks/eksctl/pkg/vpc" @@ -72,6 +73,10 @@ func (m *Manager) Create(options CreateOpts, nodegroupFilter filter.NodegroupFil return errors.New("Managed Nodegroups are not supported for this cluster version. Please update the cluster before adding managed nodegroups") } + if utilsstrings.Value(cfg.VPC.IPFamily) == string(api.IPV6Family) && len(cfg.NodeGroups) > 0 { + return errors.New("unmanaged nodegroups are not supported with IPv6 clusters") + } + if err := eks.ValidateBottlerocketSupport(ctl.ControlPlaneVersion(), cmdutils.ToKubeNodeGroups(cfg)); err != nil { return err } diff --git a/pkg/actions/nodegroup/create_test.go b/pkg/actions/nodegroup/create_test.go index b85de28d7a..56208502f7 100644 --- a/pkg/actions/nodegroup/create_test.go +++ b/pkg/actions/nodegroup/create_test.go @@ -4,10 +4,12 @@ import ( "fmt" "strings" + . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" "github.com/pkg/errors" + "github.com/weaveworks/eksctl/pkg/actions/nodegroup" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/manager" @@ -17,6 +19,7 @@ import ( "github.com/weaveworks/eksctl/pkg/kubernetes" "github.com/weaveworks/eksctl/pkg/testutils" "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" + utilsstrings "github.com/weaveworks/eksctl/pkg/utils/strings" ) type ngEntry struct { @@ -299,6 +302,53 @@ var _ = DescribeTable("Create", func(t ngEntry) { }), ) +var _ = Describe("create", func() { + When("creating an unmanaged nodegroup for an ipv6 cluster", func() { + It("returns an error", func() { + cfg := newClusterConfig() + cfg.Metadata.Version = api.Version1_21 + cfg.IAM = &api.ClusterIAM{ + WithOIDC: api.Enabled(), + } + cfg.Addons = []*api.Addon{ + { + Name: api.VPCCNIAddon, + }, + { + Name: api.KubeProxyAddon, + }, + { + Name: api.CoreDNSAddon, + }, + } + cfg.VPC.IPFamily = utilsstrings.Pointer(string(api.IPV6Family)) + + p := mockprovider.NewMockProvider() + ctl := &eks.ClusterProvider{ + Provider: p, + Status: &eks.ProviderStatus{ + ClusterInfo: &eks.ClusterInfo{ + Cluster: testutils.NewFakeCluster("my-cluster", ""), + }, + }, + } + m := nodegroup.New(cfg, ctl, nil) + + k := &fakes.FakeKubeProvider{} + k.SupportsManagedNodesReturns(true, nil) + m.MockKubeProvider(k) + + init := &fakes.FakeNodeGroupInitialiser{} + m.MockNodeGroupService(init) + + ngFilter := utilFakes.FakeNodegroupFilter{} + + err := m.Create(nodegroup.CreateOpts{}, &ngFilter) + Expect(err).To(MatchError(ContainSubstring("unmanaged nodegroups are not supported with IPv6 clusters"))) + }) + }) +}) + func newClusterConfig() *api.ClusterConfig { return &api.ClusterConfig{ TypeMeta: api.ClusterConfigTypeMeta(), diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 30ac35f697..5292579cba 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -26,6 +26,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + utilsstrings "github.com/weaveworks/eksctl/pkg/utils/strings" "github.com/weaveworks/eksctl/pkg/utils/taints" ) @@ -743,12 +744,11 @@ func NewClusterConfig() *ClusterConfig { // NewClusterVPC creates new VPC config for a cluster func NewClusterVPC() *ClusterVPC { cidr := DefaultCIDR() - defaultIPFamily := string(DefaultIPFamily) return &ClusterVPC{ Network: Network{ CIDR: &cidr, - IPFamily: &defaultIPFamily, + IPFamily: utilsstrings.Pointer(string(DefaultIPFamily)), }, ManageSharedNodeSecurityGroupRules: Enabled(), NAT: DefaultClusterNAT(), diff --git a/pkg/utils/strings/strings.go b/pkg/utils/strings/strings.go index ab45d8e9cd..1354bf82cb 100644 --- a/pkg/utils/strings/strings.go +++ b/pkg/utils/strings/strings.go @@ -7,6 +7,14 @@ func Pointer(s string) *string { return &s } +// Value returns the value of a pointer, empty string if it's nil. +func Value(s *string) string { + if s == nil { + return "" + } + return *s +} + // HasPrefix tests whether the string s begins with prefix. func HasPrefix(s, prefix string) bool { return strings.HasPrefix(s, prefix) diff --git a/userdocs/src/usage/vpc-networking.md b/userdocs/src/usage/vpc-networking.md index cea55a23a7..0c2ec5499b 100644 --- a/userdocs/src/usage/vpc-networking.md +++ b/userdocs/src/usage/vpc-networking.md @@ -59,6 +59,7 @@ This is an in config file setting only. When IPv6 is set, the following restrict - setting vpc.NAT is not allowed - serviceIPv4CIDR is not supported together with IPv6 - AutoAllocateIPv6 is not supported together with IPv6 +- unmanaged nodegroups are not yet supported with IPv6 clusters The default value is `IPv4`. From 7add99c1d6cd201009aabfba0d158b2325a78779 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Thu, 14 Oct 2021 13:28:41 +0200 Subject: [PATCH 8/8] Added a check to the nodegroup task as well --- pkg/cfn/builder/nodegroup.go | 6 ++++++ pkg/cfn/builder/nodegroup_test.go | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/pkg/cfn/builder/nodegroup.go b/pkg/cfn/builder/nodegroup.go index 238e163f5d..ce14d7d651 100644 --- a/pkg/cfn/builder/nodegroup.go +++ b/pkg/cfn/builder/nodegroup.go @@ -17,6 +17,7 @@ import ( api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/outputs" "github.com/weaveworks/eksctl/pkg/nodebootstrap" + utilsstrings "github.com/weaveworks/eksctl/pkg/utils/strings" "github.com/weaveworks/eksctl/pkg/vpc" ) @@ -51,6 +52,11 @@ func NewNodeGroupResourceSet(ec2API ec2iface.EC2API, iamAPI iamiface.IAMAPI, spe // AddAllResources adds all the information about the nodegroup to the resource set func (n *NodeGroupResourceSet) AddAllResources() error { + + if utilsstrings.Value(n.clusterSpec.VPC.IPFamily) == string(api.IPV6Family) { + return errors.New("unmanaged nodegroups are not supported with IPv6 clusters") + } + n.rs.template.Description = fmt.Sprintf( "%s (AMI family: %s, SSH access: %v, private networking: %v) %s", nodeGroupTemplateDescription, diff --git a/pkg/cfn/builder/nodegroup_test.go b/pkg/cfn/builder/nodegroup_test.go index 480369406f..81fedce1d3 100644 --- a/pkg/cfn/builder/nodegroup_test.go +++ b/pkg/cfn/builder/nodegroup_test.go @@ -16,6 +16,7 @@ import ( "github.com/weaveworks/eksctl/pkg/cfn/outputs" "github.com/weaveworks/eksctl/pkg/eks/mocks" bootstrapfakes "github.com/weaveworks/eksctl/pkg/nodebootstrap/fakes" + utilsstrings "github.com/weaveworks/eksctl/pkg/utils/strings" vpcfakes "github.com/weaveworks/eksctl/pkg/vpc/fakes" ) @@ -74,6 +75,21 @@ var _ = Describe("Unmanaged NodeGroup Template Builder", func() { Expect(ngTemplate.Outputs).To(HaveKey(outputs.NodeGroupFeatureLocalSecurityGroup)) }) + Context("ipv6 cluster", func() { + BeforeEach(func() { + cfg.VPC.IPFamily = utilsstrings.Pointer(string(api.IPV6Family)) + }) + AfterEach(func() { + cfg.VPC.IPFamily = utilsstrings.Pointer(string(api.IPV4Family)) + }) + + When("an unmanaged nodegroup is created", func() { + It("returns an error", func() { + Expect(addErr).To(MatchError(ContainSubstring("unmanaged nodegroups are not supported with IPv6 clusters"))) + }) + }) + }) + Context("if ng.MinSize is nil", func() { BeforeEach(func() { ng.MinSize = nil