Skip to content

Commit

Permalink
feat: support disable nat gateway and use public subnet (#132)
Browse files Browse the repository at this point in the history
### Motivation

For save nat gateway costs

### Modifications

- Add `disable_nat_gateway` variable to vpc tf module for support
disable NAT Gateway when provisioning VPC.
- this will disable create the EIP, NAT Gateway, RouteTable and Route
for private subnet (it will use the main default rtb)
   - this will enable auto assign public ip for public subnet
- Add `enable_nodes_use_public_subnet` variable to terraform-aws-cloud
module for support use public ip nodes when provisioning EKS
- Update tf docs

### Verifying this change

- [x] Make sure that the change passes the CI checks.

This change has been verified by provisioning an AWS env.

### Documentation

- [x] `doc` 
  
  (If this PR contains doc changes)
  • Loading branch information
maxsxu authored May 21, 2024
1 parent 6f7739e commit 4c1b508
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 11 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ _Note: Since this module manages all of the Kubernetes addon dependencies requir
| <a name="input_enable_istio"></a> [enable\_istio](#input\_enable\_istio) | Allows for enabling the bootstrap of Istio explicity in scenarios where the input "var.enable\_bootstrap" is set to "false". | `bool` | `true` | no |
| <a name="input_enable_node_group_private_networking"></a> [enable\_node\_group\_private\_networking](#input\_enable\_node\_group\_private\_networking) | Enables private networking for the EKS node groups (not the EKS cluster endpoint, which remains public), meaning Kubernetes API requests that originate within the cluster's VPC use a private VPC endpoint for EKS. Defaults to "true". | `bool` | `true` | no |
| <a name="input_enable_node_pool_monitoring"></a> [enable\_node\_pool\_monitoring](#input\_enable\_node\_pool\_monitoring) | Enable CloudWatch monitoring for the default pool(s). | `bool` | `false` | no |
| <a name="input_enable_nodes_use_public_subnet"></a> [enable\_nodes\_use\_public\_subnet](#input\_enable\_nodes\_use\_public\_subnet) | When set to true, the node groups will use public subnet rather private subnet, and the public subnet must enable auto-assing public ip so that nodes can have public ip to access internet. Default is false. | `bool` | `false` | no |
| <a name="input_enable_resource_creation"></a> [enable\_resource\_creation](#input\_enable\_resource\_creation) | When enabled, all dependencies, like roles, buckets, etc will be created. When disabled, they will note. Use in combination with `enable_bootstrap` to manage these outside this module | `bool` | `true` | no |
| <a name="input_enable_sncloud_control_plane_access"></a> [enable\_sncloud\_control\_plane\_access](#input\_enable\_sncloud\_control\_plane\_access) | Whether to enable access to the EKS control plane endpoint. If set to "false", additional configuration is required in order for the cluster to function properly, such as AWS PrivateLink for EC2, ECR, and S3, along with a VPN to access the EKS control plane. It is recommended to keep this setting to "true" unless you are familiar with this type of configuration. | `bool` | `true` | no |
| <a name="input_enable_v3_node_groups"></a> [enable\_v3\_node\_groups](#input\_enable\_v3\_node\_groups) | Enable v3 node groups, which uses a single ASG and all other node groups enabled elsewhere | `bool` | `false` | no |
Expand Down
3 changes: 2 additions & 1 deletion main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ locals {
default_service_policy_arn = "arn:${local.aws_partition}:iam::${local.account_id}:policy/StreamNative/StreamNativeCloudRuntimePolicy"
ebs_kms_key = var.disk_encryption_kms_key_arn == "" ? data.aws_kms_key.ebs_default.arn : var.disk_encryption_kms_key_arn
oidc_issuer = trimprefix(module.eks.cluster_oidc_issuer_url, "https://")
nodes_subnet_ids = var.enable_nodes_use_public_subnet ? var.public_subnet_ids : var.private_subnet_ids

tags = merge(
{
Expand Down Expand Up @@ -133,7 +134,7 @@ locals {

v3_node_groups = tomap({
"snc-core" = {
subnet_ids = var.private_subnet_ids
subnet_ids = local.nodes_subnet_ids
instance_types = [var.v3_node_group_core_instance_type]
name = "snc-core"
taints = local.v3_node_taints
Expand Down
5 changes: 3 additions & 2 deletions modules/vpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,13 @@ No modules.

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_disable_nat_gateway"></a> [disable\_nat\_gateway](#input\_disable\_nat\_gateway) | If set to true, will not create NAT Gateway and EC2 Nodes should put in public subnets. This could be useful when wanna save costs from nat gateway. | `bool` | `false` | no |
| <a name="input_num_azs"></a> [num\_azs](#input\_num\_azs) | The number of availability zones to provision | `number` | `2` | no |
| <a name="input_private_subnet_newbits"></a> [private\_subnet\_newbits](#input\_private\_subnet\_newbits) | The number of bits to added to the VPC CIDR prefix. For instance, if your VPC CIDR is a /16 and you set this number to 4, the subnets will be /20s. | `number` | `4` | no |
| <a name="input_private_subnet_start"></a> [private\_subnet\_start](#input\_private\_subnet\_start) | The starting octet for the private subnet CIDR blocks generated by this module. | `number` | `8` | no |
| <a name="input_private_subnet_start"></a> [private\_subnet\_start](#input\_private\_subnet\_start) | The starting octet for the private subnet CIDR blocks generated by this module. | `number` | `0` | no |
| <a name="input_public_subnet_auto_ip"></a> [public\_subnet\_auto\_ip](#input\_public\_subnet\_auto\_ip) | n/a | `bool` | `false` | no |
| <a name="input_public_subnet_newbits"></a> [public\_subnet\_newbits](#input\_public\_subnet\_newbits) | The number of bits to added to the VPC CIDR prefix. For instance, if your VPC CIDR is a /16 and you set this number to 4, the subnets will be /20s. | `number` | `4` | no |
| <a name="input_public_subnet_start"></a> [public\_subnet\_start](#input\_public\_subnet\_start) | The starting octet for the public subnet CIDR blocks generated by this module. | `number` | `0` | no |
| <a name="input_public_subnet_start"></a> [public\_subnet\_start](#input\_public\_subnet\_start) | The starting octet for the public subnet CIDR blocks generated by this module. | `number` | `8` | no |
| <a name="input_region"></a> [region](#input\_region) | n/a | `string` | n/a | yes |
| <a name="input_tags"></a> [tags](#input\_tags) | Additional to apply to the resources. Note that this module sets the tags Name, Type, and Vendor by default. They can be overwritten, but it is not recommended. | `map(string)` | `{}` | no |
| <a name="input_vpc_cidr"></a> [vpc\_cidr](#input\_vpc\_cidr) | The CIDR range to be used by the AWS VPC. We recommend using a /16 prefix to automatically generate /20 subnets. If you are using a smaller or larger prefix, refer to the subnet\_newbits variable to ensure that the generated subnet ranges are a valid for EKS (minimum /20 is recommended). | `string` | n/a | yes |
Expand Down
12 changes: 6 additions & 6 deletions modules/vpc/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ resource "aws_subnet" "public" {
vpc_id = aws_vpc.vpc.id
cidr_block = cidrsubnet(var.vpc_cidr, var.public_subnet_newbits, var.public_subnet_start + count.index)
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = var.public_subnet_auto_ip
map_public_ip_on_launch = var.disable_nat_gateway ? true : var.public_subnet_auto_ip
tags = merge({ "Vendor" = "StreamNative", "Type" = "public", "kubernetes.io/role/elb" = "1", Name = format("%s-public-sbn-%s", var.vpc_name, count.index) }, var.tags)

lifecycle {
Expand Down Expand Up @@ -64,7 +64,7 @@ resource "aws_internet_gateway" "gw" {
}

resource "aws_eip" "eip" {
count = var.num_azs
count = var.disable_nat_gateway ? 0 : var.num_azs

domain = "vpc"
tags = merge({ "Vendor" = "StreamNative", Name = format("%s-eip-%s", var.vpc_name, count.index) }, var.tags)
Expand All @@ -76,7 +76,7 @@ resource "aws_eip" "eip" {
}

resource "aws_nat_gateway" "nat_gw" {
count = var.num_azs
count = var.disable_nat_gateway ? 0 : var.num_azs

allocation_id = aws_eip.eip[count.index].id
subnet_id = aws_subnet.public[count.index].id
Expand Down Expand Up @@ -114,7 +114,7 @@ resource "aws_route_table_association" "public_assoc" {
}

resource "aws_route_table" "private_route_table" {
count = var.num_azs
count = var.disable_nat_gateway ? 0 : var.num_azs

vpc_id = aws_vpc.vpc.id
tags = merge({ "Vendor" = "StreamNative", Name = format("%s-private-rtb-%s", var.vpc_name, count.index) }, var.tags)
Expand All @@ -125,15 +125,15 @@ resource "aws_route_table" "private_route_table" {
}

resource "aws_route" "private_route" {
count = var.num_azs
count = var.disable_nat_gateway ? 0 : var.num_azs

route_table_id = aws_route_table.private_route_table[count.index].id
nat_gateway_id = aws_nat_gateway.nat_gw[count.index].id
destination_cidr_block = "0.0.0.0/0"
}

resource "aws_route_table_association" "private_assoc" {
count = var.num_azs
count = var.disable_nat_gateway ? 0 : var.num_azs

subnet_id = aws_subnet.private[count.index].id
route_table_id = aws_route_table.private_route_table[count.index].id
Expand Down
10 changes: 8 additions & 2 deletions modules/vpc/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ variable "num_azs" {
}

variable "private_subnet_start" {
default = 8
default = 0
description = "The starting octet for the private subnet CIDR blocks generated by this module."
type = number
}

variable "public_subnet_start" {
default = 0
default = 8
description = "The starting octet for the public subnet CIDR blocks generated by this module."
type = number
}
Expand All @@ -70,3 +70,9 @@ variable "tags" {
description = "Additional to apply to the resources. Note that this module sets the tags Name, Type, and Vendor by default. They can be overwritten, but it is not recommended."
type = map(string)
}

variable "disable_nat_gateway" {
type = bool
default = false
description = "If set to true, will not create NAT Gateway and EC2 Nodes should put in public subnets. This could be useful when wanna save costs from nat gateway."
}
6 changes: 6 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,12 @@ variable "public_subnet_ids" {
type = list(string)
}

variable "enable_nodes_use_public_subnet" {
default = false
type = bool
description = "When set to true, the node groups will use public subnet rather private subnet, and the public subnet must enable auto-assing public ip so that nodes can have public ip to access internet. Default is false."
}

variable "region" {
default = null
description = "The AWS region."
Expand Down

0 comments on commit 4c1b508

Please sign in to comment.