From b34463234d5ad13801985b97b641f9f4021bd0b4 Mon Sep 17 00:00:00 2001 From: Marcos Singermann <107124858+msingermann-domino@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:09:06 -0300 Subject: [PATCH] [DOM-62207] VPC Endpint for ECR and s3 endpoint prefix list to outputs (#290) --- examples/tfvars/ecr_endpoint.tfvars | 19 +++++++ modules/eks/README.md | 3 +- modules/eks/node-group.tf | 11 ++++ modules/eks/variables.tf | 6 +++ modules/infra/README.md | 2 +- modules/infra/submodules/network/README.md | 6 ++- modules/infra/submodules/network/main.tf | 5 +- modules/infra/submodules/network/outputs.tf | 5 ++ modules/infra/submodules/network/variables.tf | 6 ++- modules/infra/submodules/network/vpc.tf | 52 +++++++++++++++++++ modules/infra/variables.tf | 6 ++- tests/plan/terraform/README.md | 2 +- tests/plan/terraform/variables.tf | 6 ++- 13 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 examples/tfvars/ecr_endpoint.tfvars diff --git a/examples/tfvars/ecr_endpoint.tfvars b/examples/tfvars/ecr_endpoint.tfvars new file mode 100644 index 00000000..d921a904 --- /dev/null +++ b/examples/tfvars/ecr_endpoint.tfvars @@ -0,0 +1,19 @@ +deploy_id = "plantest0016" +region = "us-west-2" +ssh_pvt_key_path = "domino.pem" + +default_node_groups = { + compute = { + availability_zone_ids = ["usw2-az1", "usw2-az2"] + } + gpu = { + availability_zone_ids = ["usw2-az1", "usw2-az2"] + } + platform = { + "availability_zone_ids" = ["usw2-az1", "usw2-az2"] + } +} + +network = { + create_ecr_endpoint = true +} diff --git a/modules/eks/README.md b/modules/eks/README.md index e9349c8b..a9f4fd64 100644 --- a/modules/eks/README.md +++ b/modules/eks/README.md @@ -44,6 +44,7 @@ | [aws_security_group.eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | | [aws_security_group.eks_nodes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | | [aws_security_group_rule.bastion_eks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.ecr_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | | [aws_security_group_rule.efs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | | [aws_security_group_rule.eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | | [aws_security_group_rule.netapp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | @@ -76,7 +77,7 @@ | [eks](#input\_eks) | service\_ipv4\_cidr = CIDR for EKS cluster kubernetes\_network\_config.
creation\_role\_name = Name of the role to import.
k8s\_version = EKS cluster k8s version.
nodes\_master Grants the nodes role system:master access. NOT recomended
kubeconfig = {
extra\_args = Optional extra args when generating kubeconfig.
path = Fully qualified path name to write the kubeconfig file.
}
public\_access = {
enabled = Enable EKS API public endpoint.
cidrs = List of CIDR ranges permitted for accessing the EKS public endpoint.
}
Custom role maps for aws auth configmap
custom\_role\_maps = {
rolearn = string
username = string
groups = list(string)
}
master\_role\_names = IAM role names to be added as masters in eks.
cluster\_addons = EKS cluster addons. vpc-cni is installed separately.
vpc\_cni = Configuration for AWS VPC CNI
ssm\_log\_group\_name = CloudWatch log group to send the SSM session logs to.
identity\_providers = Configuration for IDP(Identity Provider).
} |
object({
service_ipv4_cidr = optional(string, "172.20.0.0/16")
creation_role_name = optional(string, null)
k8s_version = optional(string, "1.27")
nodes_master = optional(bool, false)
kubeconfig = optional(object({
extra_args = optional(string, "")
path = optional(string, null)
}), {})
public_access = optional(object({
enabled = optional(bool, false)
cidrs = optional(list(string), [])
}), {})
custom_role_maps = optional(list(object({
rolearn = string
username = string
groups = list(string)
})), [])
master_role_names = optional(list(string), [])
cluster_addons = optional(list(string), ["kube-proxy", "coredns", "vpc-cni"])
ssm_log_group_name = optional(string, "session-manager")
vpc_cni = optional(object({
prefix_delegation = optional(bool, false)
annotate_pod_ip = optional(bool, true)
}))
identity_providers = optional(list(object({
client_id = string
groups_claim = optional(string, null)
groups_prefix = optional(string, null)
identity_provider_config_name = string
issuer_url = optional(string, null)
required_claims = optional(map(string), null)
username_claim = optional(string, null)
username_prefix = optional(string, null)
})), []),
})
| `{}` | no | | [ignore\_tags](#input\_ignore\_tags) | Tag keys to be ignored by the aws provider. | `list(string)` | `[]` | no | | [kms\_info](#input\_kms\_info) | key\_id = KMS key id.
key\_arn = KMS key arn.
enabled = KMS key is enabled |
object({
key_id = string
key_arn = string
enabled = bool
})
| n/a | yes | -| [network\_info](#input\_network\_info) | id = VPC ID.
subnets = {
public = List of public Subnets.
[{
name = Subnet name.
subnet\_id = Subnet ud
az = Subnet availability\_zone
az\_id = Subnet availability\_zone\_id
}]
private = List of private Subnets.
[{
name = Subnet name.
subnet\_id = Subnet ud
az = Subnet availability\_zone
az\_id = Subnet availability\_zone\_id
}]
pod = List of pod Subnets.
[{
name = Subnet name.
subnet\_id = Subnet ud
az = Subnet availability\_zone
az\_id = Subnet availability\_zone\_id
}]
} |
object({
vpc_id = string
subnets = object({
public = list(object({
name = string
subnet_id = string
az = string
az_id = string
}))
private = list(object({
name = string
subnet_id = string
az = string
az_id = string
}))
pod = list(object({
name = string
subnet_id = string
az = string
az_id = string
}))
})
vpc_cidrs = optional(string, "10.0.0.0/16")
})
| n/a | yes | +| [network\_info](#input\_network\_info) | id = VPC ID.
ecr\_endpoint = {
security\_group\_id = ECR Endpoint security group id.
}
subnets = {
public = List of public Subnets.
[{
name = Subnet name.
subnet\_id = Subnet ud
az = Subnet availability\_zone
az\_id = Subnet availability\_zone\_id
}]
private = List of private Subnets.
[{
name = Subnet name.
subnet\_id = Subnet ud
az = Subnet availability\_zone
az\_id = Subnet availability\_zone\_id
}]
pod = List of pod Subnets.
[{
name = Subnet name.
subnet\_id = Subnet ud
az = Subnet availability\_zone
az\_id = Subnet availability\_zone\_id
}]
} |
object({
vpc_id = string
ecr_endpoint = optional(object({
security_group_id = optional(string, null)
}), null)
subnets = object({
public = list(object({
name = string
subnet_id = string
az = string
az_id = string
}))
private = list(object({
name = string
subnet_id = string
az = string
az_id = string
}))
pod = list(object({
name = string
subnet_id = string
az = string
az_id = string
}))
})
vpc_cidrs = optional(string, "10.0.0.0/16")
})
| n/a | yes | | [node\_iam\_policies](#input\_node\_iam\_policies) | Additional IAM Policy Arns for Nodes | `list(string)` | n/a | yes | | [privatelink](#input\_privatelink) | {
enabled = Enable Private Link connections.
namespace = Namespace for IAM Policy conditions.
monitoring\_bucket = Bucket for NLBs monitoring.
route53\_hosted\_zone\_name = Hosted zone for External DNS zone.
vpc\_endpoint\_services = [{
name = Name of the VPC Endpoint Service.
ports = List of ports exposing the VPC Endpoint Service. i.e [8080, 8081]
cert\_arn = Certificate ARN used by the NLB associated for the given VPC Endpoint Service.
private\_dns = Private DNS for the VPC Endpoint Service.
}]
} |
object({
enabled = optional(bool, false)
namespace = optional(string, "domino-platform")
monitoring_bucket = optional(string, null)
route53_hosted_zone_name = optional(string, null)
vpc_endpoint_services = optional(list(object({
name = optional(string)
ports = optional(list(number))
cert_arn = optional(string)
private_dns = optional(string)
})), [])
})
| `{}` | no | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | diff --git a/modules/eks/node-group.tf b/modules/eks/node-group.tf index 84f1bd6a..15e2083e 100644 --- a/modules/eks/node-group.tf +++ b/modules/eks/node-group.tf @@ -83,3 +83,14 @@ resource "aws_security_group_rule" "netapp" { description = "Netapp access from EKS nodes." source_security_group_id = aws_security_group.eks_nodes.id } + +resource "aws_security_group_rule" "ecr_endpoint" { + count = var.network_info.ecr_endpoint != null ? 1 : 0 + security_group_id = var.network_info.ecr_endpoint.security_group_id + protocol = "tcp" + from_port = 443 + to_port = 443 + type = "ingress" + description = "ECR Endpoint access from EKS nodes." + source_security_group_id = aws_security_group.eks_nodes.id +} diff --git a/modules/eks/variables.tf b/modules/eks/variables.tf index 3abdcbc6..0ebbdb04 100644 --- a/modules/eks/variables.tf +++ b/modules/eks/variables.tf @@ -21,6 +21,9 @@ variable "region" { variable "network_info" { description = < [eks](#input\_eks) | creation\_role\_name = Name of the role to import.
k8s\_version = EKS cluster k8s version.
nodes\_master Grants the nodes role system:master access. NOT recomended
kubeconfig = {
extra\_args = Optional extra args when generating kubeconfig.
path = Fully qualified path name to write the kubeconfig file.
}
public\_access = {
enabled = Enable EKS API public endpoint.
cidrs = List of CIDR ranges permitted for accessing the EKS public endpoint.
}
Custom role maps for aws auth configmap
custom\_role\_maps = {
rolearn = string
username = string
groups = list(string)
}
master\_role\_names = IAM role names to be added as masters in eks.
cluster\_addons = EKS cluster addons. vpc-cni is installed separately.
vpc\_cni = Configuration for AWS VPC CNI
ssm\_log\_group\_name = CloudWatch log group to send the SSM session logs to.
identity\_providers = Configuration for IDP(Identity Provider).
} |
object({
creation_role_name = optional(string, null)
k8s_version = optional(string, "1.27")
nodes_master = optional(bool, false)
kubeconfig = optional(object({
extra_args = optional(string, "")
path = optional(string, null)
}), {})
public_access = optional(object({
enabled = optional(bool, false)
cidrs = optional(list(string), [])
}), {})
custom_role_maps = optional(list(object({
rolearn = string
username = string
groups = list(string)
})), [])
master_role_names = optional(list(string), [])
cluster_addons = optional(list(string), ["kube-proxy", "coredns", "vpc-cni"])
ssm_log_group_name = optional(string, "session-manager")
vpc_cni = optional(object({
prefix_delegation = optional(bool)
annotate_pod_ip = optional(bool)
}))
identity_providers = optional(list(object({
client_id = string
groups_claim = optional(string, null)
groups_prefix = optional(string, null)
identity_provider_config_name = string
issuer_url = optional(string, null)
required_claims = optional(map(string), null)
username_claim = optional(string, null)
username_prefix = optional(string, null)
})), [])
})
| `{}` | no | | [ignore\_tags](#input\_ignore\_tags) | Tag keys to be ignored by the aws provider. | `list(string)` | `[]` | no | | [kms](#input\_kms) | enabled = "Toggle, if set use either the specified KMS key\_id or a Domino-generated one"
key\_id = optional(string, null)
additional\_policies = "Allows setting additional KMS key policies when using a Domino-generated key" |
object({
enabled = optional(bool, true)
key_id = optional(string, null)
additional_policies = optional(list(string), [])
})
| `{}` | no | -| [network](#input\_network) | vpc = {
id = Existing vpc id, it will bypass creation by this module.
subnets = {
private = Existing private subnets.
public = Existing public subnets.
pod = Existing pod subnets.
}), {})
}), {})
network\_bits = {
public = Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs.
private = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
pod = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
}
cidrs = {
vpc = The IPv4 CIDR block for the VPC.
pod = The IPv4 CIDR block for the Pod subnets.
}
use\_pod\_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking. |
object({
vpc = optional(object({
id = optional(string, null)
subnets = optional(object({
private = optional(list(string), [])
public = optional(list(string), [])
pod = optional(list(string), [])
}), {})
}), {})
network_bits = optional(object({
public = optional(number, 27)
private = optional(number, 19)
pod = optional(number, 19)
}
), {})
cidrs = optional(object({
vpc = optional(string, "10.0.0.0/16")
pod = optional(string, "100.64.0.0/16")
}), {})
use_pod_cidr = optional(bool, true)
})
| `{}` | no | +| [network](#input\_network) | vpc = {
id = Existing vpc id, it will bypass creation by this module.
subnets = {
private = Existing private subnets.
public = Existing public subnets.
pod = Existing pod subnets.
}), {})
}), {})
network\_bits = {
public = Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs.
private = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
pod = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
}
cidrs = {
vpc = The IPv4 CIDR block for the VPC.
pod = The IPv4 CIDR block for the Pod subnets.
}
use\_pod\_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking.
create\_ecr\_endpoint = Create the VPC Endpoint For ECR. |
object({
vpc = optional(object({
id = optional(string, null)
subnets = optional(object({
private = optional(list(string), [])
public = optional(list(string), [])
pod = optional(list(string), [])
}), {})
}), {})
network_bits = optional(object({
public = optional(number, 27)
private = optional(number, 19)
pod = optional(number, 19)
}
), {})
cidrs = optional(object({
vpc = optional(string, "10.0.0.0/16")
pod = optional(string, "100.64.0.0/16")
}), {})
use_pod_cidr = optional(bool, true)
create_ecr_endpoint = optional(bool, false)
})
| `{}` | no | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | | [ssh\_pvt\_key\_path](#input\_ssh\_pvt\_key\_path) | SSH private key filepath. | `string` | n/a | yes | | [storage](#input\_storage) | storage = {
filesystem\_type = File system type(netapp\|efs)
efs = {
access\_point\_path = Filesystem path for efs.
backup\_vault = {
create = Create backup vault for EFS toggle.
force\_destroy = Toggle to allow automatic destruction of all backups when destroying.
backup = {
schedule = Cron-style schedule for EFS backup vault (default: once a day at 12pm).
cold\_storage\_after = Move backup data to cold storage after this many days.
delete\_after = Delete backup data after this many days.
}
}
}
netapp = {
migrate\_from\_efs = {
enabled = When enabled, both EFS and NetApp resources will be provisioned simultaneously during the migration period.
datasync = {
enabled = Toggle to enable AWS DataSync for automated data transfer from EFS to NetApp FSx.
schedule = Cron-style schedule for the DataSync task, specifying how often the data transfer will occur (default: hourly).
}
}
deployment\_type = netapp ontap deployment type,('MULTI\_AZ\_1', 'MULTI\_AZ\_2', 'SINGLE\_AZ\_1', 'SINGLE\_AZ\_2')
storage\_capacity = Filesystem Storage capacity
throughput\_capacity = Filesystem throughput capacity
automatic\_backup\_retention\_days = How many days to keep backups
daily\_automatic\_backup\_start\_time = Start time in 'HH:MM' format to initiate backups

storage\_capacity\_autosizing = Options for the FXN automatic storage capacity increase, cloudformation template
enabled = Enable automatic storage capacity increase.
threshold = Used storage capacity threshold.
percent\_capacity\_increase = The percentage increase in storage capacity when used storage exceeds
LowFreeDataStorageCapacityThreshold. Minimum increase is 10 %.
notification\_email\_address = The email address for alarm notification.
}
volume = {
create = Create a volume associated with the filesystem.
name\_suffix = The suffix to name the volume
storage\_efficiency\_enabled = Toggle storage\_efficiency\_enabled
junction\_path = filesystem junction path
size\_in\_megabytes = The size of the volume
}
s3 = {
force\_destroy\_on\_deletion = Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets.
}
ecr = {
force\_destroy\_on\_deletion = Toogle to allow recursive deletion of all objects in the ECR repositories. if 'false' terraform will NOT be able to delete non-empty repositories.
}
enable\_remote\_backup = Enable tagging required for cross-account backups
costs\_enabled = Determines whether to provision domino cost related infrastructures, ie, long term storage
}
} |
object({
filesystem_type = optional(string, "efs")
efs = optional(object({
access_point_path = optional(string, "/domino")
backup_vault = optional(object({
create = optional(bool, true)
force_destroy = optional(bool, true)
backup = optional(object({
schedule = optional(string, "0 12 * * ? *")
cold_storage_after = optional(number, 35)
delete_after = optional(number, 125)
}), {})
}), {})
}), {})
netapp = optional(object({
migrate_from_efs = optional(object({
enabled = optional(bool, false)
datasync = optional(object({
enabled = optional(bool, false)
target = optional(string, "netapp")
schedule = optional(string, "cron(0 * * * ? *)")
}), {})
}), {})
deployment_type = optional(string, "SINGLE_AZ_1")
storage_capacity = optional(number, 1024)
throughput_capacity = optional(number, 128)
automatic_backup_retention_days = optional(number, 90)
daily_automatic_backup_start_time = optional(string, "00:00")
storage_capacity_autosizing = optional(object({
enabled = optional(bool, false)
threshold = optional(number, 70)
percent_capacity_increase = optional(number, 30)
notification_email_address = optional(string, "")
}), {})
volume = optional(object({
create = optional(bool, true)
name_suffix = optional(string, "domino_shared_storage")
storage_efficiency_enabled = optional(bool, true)
junction_path = optional(string, "/domino")
size_in_megabytes = optional(number, 1048576)
}), {})
}), {})
s3 = optional(object({
force_destroy_on_deletion = optional(bool, true)
}), {})
ecr = optional(object({
force_destroy_on_deletion = optional(bool, true)
}), {}),
enable_remote_backup = optional(bool, false)
costs_enabled = optional(bool, true)
})
| `{}` | no | diff --git a/modules/infra/submodules/network/README.md b/modules/infra/submodules/network/README.md index ca210b42..185e122f 100644 --- a/modules/infra/submodules/network/README.md +++ b/modules/infra/submodules/network/README.md @@ -34,14 +34,18 @@ No modules. | [aws_route_table_association.pod](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | | [aws_route_table_association.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | | [aws_route_table_association.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | +| [aws_security_group.ecr_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | | [aws_subnet.pod](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | | [aws_subnet.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | | [aws_subnet.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | | [aws_vpc.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc) | resource | +| [aws_vpc_endpoint.ecr_api](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource | +| [aws_vpc_endpoint.ecr_dkr](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource | | [aws_vpc_endpoint.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource | | [aws_vpc_ipv4_cidr_block_association.pod_cidr](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipv4_cidr_block_association) | resource | | [aws_availability_zone.zones](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zone) | data source | | [aws_network_acls.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/network_acls) | data source | +| [aws_prefix_list.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/prefix_list) | data source | | [aws_subnet.pod](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnet) | data source | | [aws_subnet.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnet) | data source | | [aws_subnet.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnet) | data source | @@ -54,7 +58,7 @@ No modules. | [add\_eks\_elb\_tags](#input\_add\_eks\_elb\_tags) | Toggle k8s cluster tag on subnet | `bool` | `true` | no | | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | | [flow\_log\_bucket\_arn](#input\_flow\_log\_bucket\_arn) | Bucket for vpc flow logging | `object({ arn = string })` | `null` | no | -| [network](#input\_network) | vpc = {
id = Existing vpc id, it will bypass creation by this module.
subnets = {
private = Existing private subnets.
public = Existing public subnets.
pod = Existing pod subnets.
}), {})
}), {})
network\_bits = {
public = Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs.
private = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
pod = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
}
cidrs = {
vpc = The IPv4 CIDR block for the VPC.
pod = The IPv4 CIDR block for the Pod subnets.
}
use\_pod\_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking. |
object({
vpc = optional(object({
id = optional(string)
subnets = optional(object({
private = optional(list(string))
public = optional(list(string))
pod = optional(list(string))
}))
}))
network_bits = optional(object({
public = optional(number)
private = optional(number)
pod = optional(number)
}
))
cidrs = optional(object({
vpc = optional(string)
pod = optional(string)
}))
use_pod_cidr = optional(bool)
})
| n/a | yes | +| [network](#input\_network) | vpc = {
id = Existing vpc id, it will bypass creation by this module.
subnets = {
private = Existing private subnets.
public = Existing public subnets.
pod = Existing pod subnets.
}), {})
}), {})
network\_bits = {
public = Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs.
private = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
pod = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
}
cidrs = {
vpc = The IPv4 CIDR block for the VPC.
pod = The IPv4 CIDR block for the Pod subnets.
}
use\_pod\_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking.
create\_ecr\_endpoint = Create the VPC Endpoint For ECR. |
object({
vpc = optional(object({
id = optional(string)
subnets = optional(object({
private = optional(list(string))
public = optional(list(string))
pod = optional(list(string))
}))
}))
network_bits = optional(object({
public = optional(number)
private = optional(number)
pod = optional(number)
}
))
cidrs = optional(object({
vpc = optional(string)
pod = optional(string)
}))
use_pod_cidr = optional(bool)
create_ecr_endpoint = optional(bool, false)
})
| n/a | yes | | [node\_groups](#input\_node\_groups) | EKS managed node groups definition. |
map(object({
ami = string
bootstrap_extra_args = string
instance_types = list(string)
spot = bool
min_per_az = number
max_per_az = number
desired_per_az = number
availability_zone_ids = list(string)
labels = map(string)
taints = list(object({
key = string
value = string
effect = string
}))
tags = map(string)
instance_tags = map(string)
gpu = bool
volume = object({
size = string
type = string
iops = optional(number)
throughput = optional(number, 500)
})
}))
| n/a | yes | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | diff --git a/modules/infra/submodules/network/main.tf b/modules/infra/submodules/network/main.tf index 02217494..3dc5f6df 100644 --- a/modules/infra/submodules/network/main.tf +++ b/modules/infra/submodules/network/main.tf @@ -1,6 +1,7 @@ locals { - create_vpc = var.network.vpc.id == null - provided_vpc = var.network.vpc.id != null + create_vpc = var.network.vpc.id == null + provided_vpc = var.network.vpc.id != null + create_ecr_endpoint = local.create_vpc && var.network.create_ecr_endpoint } data "aws_subnet" "public" { diff --git a/modules/infra/submodules/network/outputs.tf b/modules/infra/submodules/network/outputs.tf index c69acb80..b33293dd 100644 --- a/modules/infra/submodules/network/outputs.tf +++ b/modules/infra/submodules/network/outputs.tf @@ -15,5 +15,10 @@ output "info" { } eips = [for k, eip in aws_eip.public : eip.public_ip] vpc_cidrs = var.network.cidrs.vpc + pod_cidrs = var.network.cidrs.pod + s3_cidrs = data.aws_prefix_list.s3.cidr_blocks + ecr_endpoint = local.create_ecr_endpoint ? { + security_group_id = aws_security_group.ecr_endpoint[0].id + } : null } } diff --git a/modules/infra/submodules/network/variables.tf b/modules/infra/submodules/network/variables.tf index 5c5063f4..065453c8 100644 --- a/modules/infra/submodules/network/variables.tf +++ b/modules/infra/submodules/network/variables.tf @@ -50,7 +50,8 @@ variable "network" { vpc = The IPv4 CIDR block for the VPC. pod = The IPv4 CIDR block for the Pod subnets. } - use_pod_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking. + use_pod_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking. + create_ecr_endpoint = Create the VPC Endpoint For ECR. EOF type = object({ @@ -72,7 +73,8 @@ variable "network" { vpc = optional(string) pod = optional(string) })) - use_pod_cidr = optional(bool) + use_pod_cidr = optional(bool) + create_ecr_endpoint = optional(bool, false) }) validation { diff --git a/modules/infra/submodules/network/vpc.tf b/modules/infra/submodules/network/vpc.tf index fcbf0f0d..8d3fd501 100644 --- a/modules/infra/submodules/network/vpc.tf +++ b/modules/infra/submodules/network/vpc.tf @@ -49,6 +49,58 @@ resource "aws_vpc_endpoint" "s3" { } } +data "aws_prefix_list" "s3" { + prefix_list_id = aws_vpc_endpoint.s3[0].prefix_list_id +} + +resource "aws_security_group" "ecr_endpoint" { + count = local.create_ecr_endpoint ? 1 : 0 + name = "${var.deploy_id}-ecr" + description = "ECR Endpoint security group" + vpc_id = aws_vpc.this[0].id + + lifecycle { + create_before_destroy = true + } + tags = { + "Name" = "${var.deploy_id}-ecr" + } +} + +resource "aws_vpc_endpoint" "ecr_dkr" { + count = local.create_ecr_endpoint ? 1 : 0 + vpc_id = aws_vpc.this[0].id + private_dns_enabled = true + service_name = "com.amazonaws.${var.region}.ecr.dkr" + vpc_endpoint_type = "Interface" + subnet_ids = [for s in aws_subnet.pod : s.id] + + security_group_ids = [ + aws_security_group.ecr_endpoint[0].id, + ] + + tags = { + "Name" = "${var.deploy_id}-ecr-dkr" + } +} + +resource "aws_vpc_endpoint" "ecr_api" { + count = local.create_ecr_endpoint ? 1 : 0 + vpc_id = aws_vpc.this[0].id + private_dns_enabled = true + service_name = "com.amazonaws.${var.region}.ecr.api" + vpc_endpoint_type = "Interface" + subnet_ids = [for s in aws_subnet.pod : s.id] + + security_group_ids = [ + aws_security_group.ecr_endpoint[0].id, + ] + + tags = { + "Name" = "${var.deploy_id}-ecr-api" + } +} + data "aws_network_acls" "default" { count = local.create_vpc ? 1 : 0 vpc_id = aws_vpc.this[0].id diff --git a/modules/infra/variables.tf b/modules/infra/variables.tf index adf2471c..9f23664f 100644 --- a/modules/infra/variables.tf +++ b/modules/infra/variables.tf @@ -274,7 +274,8 @@ variable "network" { vpc = The IPv4 CIDR block for the VPC. pod = The IPv4 CIDR block for the Pod subnets. } - use_pod_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking. + use_pod_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking. + create_ecr_endpoint = Create the VPC Endpoint For ECR. EOF type = object({ @@ -296,7 +297,8 @@ variable "network" { vpc = optional(string, "10.0.0.0/16") pod = optional(string, "100.64.0.0/16") }), {}) - use_pod_cidr = optional(bool, true) + use_pod_cidr = optional(bool, true) + create_ecr_endpoint = optional(bool, false) }) default = {} diff --git a/tests/plan/terraform/README.md b/tests/plan/terraform/README.md index 07b0bce7..343c7d0c 100644 --- a/tests/plan/terraform/README.md +++ b/tests/plan/terraform/README.md @@ -48,7 +48,7 @@ | [external\_deployments\_operator](#input\_external\_deployments\_operator) | Config to create IRSA role for the external deployments operator. |
object({
enabled = optional(bool, false)
namespace = optional(string, "domino-compute")
operator_service_account_name = optional(string, "pham-juno-operator")
operator_role_suffix = optional(string, "external-deployments-operator")
repository_suffix = optional(string, "external-deployments")
bucket_suffix = optional(string, "external-deployments")
enable_assume_any_external_role = optional(bool, true)
enable_in_account_deployments = optional(bool, true)
})
| `{}` | no | | [ignore\_tags](#input\_ignore\_tags) | Tag keys to be ignored by the aws provider. | `list(string)` | `[]` | no | | [kms](#input\_kms) | enabled = Toggle,if set use either the specified KMS key\_id or a Domino-generated one.
key\_id = optional(string, null)
additional\_policies = "Allows setting additional KMS key policies when using a Domino-generated key" |
object({
enabled = optional(bool, true)
key_id = optional(string, null)
additional_policies = optional(list(string), [])
})
| `{}` | no | -| [network](#input\_network) | vpc = {
id = Existing vpc id, it will bypass creation by this module.
subnets = {
private = Existing private subnets.
public = Existing public subnets.
pod = Existing pod subnets.
}), {})
}), {})
network\_bits = {
public = Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs.
private = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
pod = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
}
cidrs = {
vpc = The IPv4 CIDR block for the VPC.
pod = The IPv4 CIDR block for the Pod subnets.
}
use\_pod\_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking. |
object({
vpc = optional(object({
id = optional(string, null)
subnets = optional(object({
private = optional(list(string), [])
public = optional(list(string), [])
pod = optional(list(string), [])
}), {})
}), {})
network_bits = optional(object({
public = optional(number, 27)
private = optional(number, 19)
pod = optional(number, 19)
}
), {})
cidrs = optional(object({
vpc = optional(string, "10.0.0.0/16")
pod = optional(string, "100.64.0.0/16")
}), {})
use_pod_cidr = optional(bool, true)
})
| `{}` | no | +| [network](#input\_network) | vpc = {
id = Existing vpc id, it will bypass creation by this module.
subnets = {
private = Existing private subnets.
public = Existing public subnets.
pod = Existing pod subnets.
}), {})
}), {})
network\_bits = {
public = Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs.
private = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
pod = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.
}
cidrs = {
vpc = The IPv4 CIDR block for the VPC.
pod = The IPv4 CIDR block for the Pod subnets.
}
use\_pod\_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking.
create\_ecr\_endpoint = Create the VPC Endpoint For ECR. |
object({
vpc = optional(object({
id = optional(string, null)
subnets = optional(object({
private = optional(list(string), [])
public = optional(list(string), [])
pod = optional(list(string), [])
}), {})
}), {})
network_bits = optional(object({
public = optional(number, 27)
private = optional(number, 19)
pod = optional(number, 19)
}
), {})
cidrs = optional(object({
vpc = optional(string, "10.0.0.0/16")
pod = optional(string, "100.64.0.0/16")
}), {})
use_pod_cidr = optional(bool, true)
create_ecr_endpoint = optional(bool, false)
})
| `{}` | no | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | | [route53\_hosted\_zone\_name](#input\_route53\_hosted\_zone\_name) | Optional hosted zone for External DNS zone. | `string` | `null` | no | | [single\_node](#input\_single\_node) | Additional EKS managed node groups definition. |
object({
name = optional(string, "single-node")
bootstrap_extra_args = optional(string, "")
ami = optional(object({
name_prefix = optional(string, null)
owner = optional(string, null)

}))
instance_type = optional(string, "m6i.2xlarge")
authorized_ssh_ip_ranges = optional(list(string), ["0.0.0.0/0"])
labels = optional(map(string))
taints = optional(list(object({
key = string
value = optional(string)
effect = string
})), [])
volume = optional(object({
size = optional(number, 1000)
type = optional(string, "gp3")
}), {})
})
| `null` | no | diff --git a/tests/plan/terraform/variables.tf b/tests/plan/terraform/variables.tf index 04b6a494..36798db2 100644 --- a/tests/plan/terraform/variables.tf +++ b/tests/plan/terraform/variables.tf @@ -277,7 +277,8 @@ variable "network" { vpc = The IPv4 CIDR block for the VPC. pod = The IPv4 CIDR block for the Pod subnets. } - use_pod_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking. + use_pod_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking. + create_ecr_endpoint = Create the VPC Endpoint For ECR. EOF type = object({ @@ -299,7 +300,8 @@ variable "network" { vpc = optional(string, "10.0.0.0/16") pod = optional(string, "100.64.0.0/16") }), {}) - use_pod_cidr = optional(bool, true) + use_pod_cidr = optional(bool, true) + create_ecr_endpoint = optional(bool, false) }) default = {}