From 27aa8f4d0e8b25e7982736f09e8ba8e482f1d23c Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Thu, 25 Oct 2018 15:57:24 +0100 Subject: [PATCH] Add `--node-private-networking` flag - ensure control plane uses private subnets - add NAT Gateway --- pkg/cfn/builder/api.go | 7 +++++++ pkg/cfn/builder/cluster.go | 18 +++++++++++------- pkg/cfn/builder/nodegroup.go | 6 ------ pkg/cfn/builder/vpc.go | 32 +++++++++++++++++++++++++------- pkg/ctl/create/cluster.go | 4 ++++ 5 files changed, 47 insertions(+), 20 deletions(-) diff --git a/pkg/cfn/builder/api.go b/pkg/cfn/builder/api.go index 83578fa75b..495b14829c 100644 --- a/pkg/cfn/builder/api.go +++ b/pkg/cfn/builder/api.go @@ -18,6 +18,13 @@ const ( templateDescriptionSuffix = " [created and managed by eksctl]" ) +type awsCloudFormationResource struct { + Type string + Properties map[string]interface{} + UpdatePolicy map[string]map[string]string `json:",omitempty"` + DependsOn []string `json:",omitempty"` +} + // ResourceSet is an interface which cluster and nodegroup builders // must implement type ResourceSet interface { diff --git a/pkg/cfn/builder/cluster.go b/pkg/cfn/builder/cluster.go index dc1555fc75..0e1ca1c65e 100644 --- a/pkg/cfn/builder/cluster.go +++ b/pkg/cfn/builder/cluster.go @@ -78,14 +78,18 @@ func (c *ClusterResourceSet) newResource(name string, resource interface{}) *gfn } func (c *ClusterResourceSet) addResourcesForControlPlane(version string) { + clusterVPC := &gfn.AWSEKSCluster_ResourcesVpcConfig{ + SecurityGroupIds: c.securityGroups, + } + for topology := range c.spec.VPC.Subnets { + clusterVPC.SubnetIds = append(clusterVPC.SubnetIds, c.subnets[topology]...) + } + c.newResource("ControlPlane", &gfn.AWSEKSCluster{ - Name: gfn.NewString(c.spec.ClusterName), - RoleArn: gfn.MakeFnGetAttString("ServiceRole.Arn"), - Version: gfn.NewString(version), - ResourcesVpcConfig: &gfn.AWSEKSCluster_ResourcesVpcConfig{ - SubnetIds: c.subnets[api.SubnetTopologyPublic], - SecurityGroupIds: c.securityGroups, - }, + Name: gfn.NewString(c.spec.ClusterName), + RoleArn: gfn.MakeFnGetAttString("ServiceRole.Arn"), + Version: gfn.NewString(version), + ResourcesVpcConfig: clusterVPC, }) c.rs.newOutputFromAtt(cfnOutputClusterCertificateAuthorityData, "ControlPlane.CertificateAuthorityData", false) diff --git a/pkg/cfn/builder/nodegroup.go b/pkg/cfn/builder/nodegroup.go index b1fc38552b..0ef6a1b01a 100644 --- a/pkg/cfn/builder/nodegroup.go +++ b/pkg/cfn/builder/nodegroup.go @@ -25,12 +25,6 @@ type NodeGroupResourceSet struct { userData *gfn.Value } -type awsCloudFormationResource struct { - Type string - Properties map[string]interface{} - UpdatePolicy map[string]map[string]string -} - // NewNodeGroupResourceSet returns a resource set for the new node group func NewNodeGroupResourceSet(spec *api.ClusterConfig, clusterStackName string, id int) *NodeGroupResourceSet { return &NodeGroupResourceSet{ diff --git a/pkg/cfn/builder/vpc.go b/pkg/cfn/builder/vpc.go index d8f02c0381..82bfe112b1 100644 --- a/pkg/cfn/builder/vpc.go +++ b/pkg/cfn/builder/vpc.go @@ -25,6 +25,8 @@ func (c *ClusterResourceSet) addSubnets(refRT *gfn.Value, topology api.SubnetTop //nolint:interfacer func (c *ClusterResourceSet) addResourcesForVPC() { + internetCIDR := gfn.NewString("0.0.0.0/0") + c.vpc = c.newResource("VPC", &gfn.AWSEC2VPC{ CidrBlock: gfn.NewString(c.spec.VPC.CIDR.String()), EnableDnsSupport: gfn.True(), @@ -39,23 +41,39 @@ func (c *ClusterResourceSet) addResourcesForVPC() { VpcId: c.vpc, }) - refPrivateRT := c.newResource("PrivateRouteTable", &gfn.AWSEC2RouteTable{ - VpcId: c.vpc, - }) - - c.addSubnets(refPrivateRT, api.SubnetTopologyPrivate) - refPublicRT := c.newResource("PublicRouteTable", &gfn.AWSEC2RouteTable{ VpcId: c.vpc, }) c.newResource("PublicSubnetRoute", &gfn.AWSEC2Route{ RouteTableId: refPublicRT, - DestinationCidrBlock: gfn.NewString("0.0.0.0/0"), + DestinationCidrBlock: internetCIDR, GatewayId: refIG, }) c.addSubnets(refPublicRT, api.SubnetTopologyPublic) + + c.newResource("NATIP", &gfn.AWSEC2EIP{ + Domain: gfn.NewString("vpc"), + }) + refNG := c.newResource("NATGateway", &gfn.AWSEC2NatGateway{ + AllocationId: gfn.MakeFnGetAttString("NATIP.AllocationId"), + // A multi-AZ NAT Gateway is possible, but it's not very + // clear from the docs how to achieve it + SubnetId: c.subnets[api.SubnetTopologyPublic][0], + }) + + refPrivateRT := c.newResource("PrivateRouteTable", &gfn.AWSEC2RouteTable{ + VpcId: c.vpc, + }) + + c.newResource("PrivateSubnetRoute", &gfn.AWSEC2Route{ + RouteTableId: refPrivateRT, + DestinationCidrBlock: internetCIDR, + NatGatewayId: refNG, + }) + + c.addSubnets(refPrivateRT, api.SubnetTopologyPrivate) } func (c *ClusterResourceSet) importResourcesForVPC() { diff --git a/pkg/ctl/create/cluster.go b/pkg/ctl/create/cluster.go index b0a929c253..4a774a3330 100644 --- a/pkg/ctl/create/cluster.go +++ b/pkg/ctl/create/cluster.go @@ -92,6 +92,10 @@ func createClusterCmd() *cobra.Command { fs.IPNetVar(cfg.VPC.CIDR, "vpc-cidr", api.DefaultCIDR(), "global CIDR to use for VPC") + if p := fs.Bool("node-private-networking", false, "whether to make initial nodegroup networking private"); *p { + ng.SubnetTopology = api.SubnetTopologyPrivate + } + return cmd }