Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conditionally create EFS for ECS cluster #26

Merged
merged 1 commit into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ This project creates and manages resources within an AWS account for infrastruct
| [aws_cloudwatch_log_group.infrastructure_vpc_flow_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |
| [aws_default_network_acl.infrastructure](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/default_network_acl) | resource |
| [aws_ecs_cluster.infrastructure](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_cluster) | resource |
| [aws_efs_file_system.infrastructure_ecs_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_file_system) | resource |
| [aws_efs_mount_target.infrastructure_ecs_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_mount_target) | resource |
| [aws_eip.infrastructure_nat](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource |
| [aws_flow_log.infrastructure_vpc_flow_logs_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/flow_log) | resource |
| [aws_flow_log.infrastructure_vpc_flow_logs_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/flow_log) | resource |
Expand Down Expand Up @@ -96,12 +98,15 @@ This project creates and manages resources within an AWS account for infrastruct
| [aws_s3_bucket_server_side_encryption_configuration.infrastructure_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource |
| [aws_s3_bucket_versioning.infrastructure_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource |
| [aws_security_group.infrastructure_ecs_cluster_container_instances](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_security_group.infrastructure_ecs_cluster_efs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_security_group_rule.infrastructure_ecs_cluster_container_instances_egress_dns_tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.infrastructure_ecs_cluster_container_instances_egress_dns_udp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.infrastructure_ecs_cluster_container_instances_egress_https_tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.infrastructure_ecs_cluster_container_instances_egress_https_udp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.infrastructure_ecs_cluster_container_instances_egress_nfs_tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.infrastructure_ecs_cluster_container_instances_ingress_tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.infrastructure_ecs_cluster_container_instances_ingress_udp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.infrastructure_ecs_cluster_efs_ingress_nfs_tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_sns_topic.infrastructure_ecs_cluster_autoscaling_lifecycle_termination](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource |
| [aws_sns_topic_subscription.ecs_cluster_infrastructure_draining_autoscaling_lifecycle_termination](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource |
| [aws_subnet.infrastructure_private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource |
Expand All @@ -118,7 +123,12 @@ This project creates and manages resources within an AWS account for infrastruct
|------|-------------|------|---------|:--------:|
| <a name="input_aws_profile_name_route53_root"></a> [aws\_profile\_name\_route53\_root](#input\_aws\_profile\_name\_route53\_root) | AWS Profile name which is configured for the account in which the root Route53 Hosted Zone exists. | `string` | n/a | yes |
| <a name="input_aws_region"></a> [aws\_region](#input\_aws\_region) | AWS region in which to launch resources | `string` | n/a | yes |
| <a name="input_ecs_cluster_efs_directories"></a> [ecs\_cluster\_efs\_directories](#input\_ecs\_cluster\_efs\_directories) | ECS cluster EFS directories to create | `list(string)` | n/a | yes |
| <a name="input_ecs_cluster_efs_infrequent_access_transition"></a> [ecs\_cluster\_efs\_infrequent\_access\_transition](#input\_ecs\_cluster\_efs\_infrequent\_access\_transition) | ECS cluser EFS IA transiton in days. Set to 0 to disable IA transition. | `number` | n/a | yes |
| <a name="input_ecs_cluster_efs_performance_mode"></a> [ecs\_cluster\_efs\_performance\_mode](#input\_ecs\_cluster\_efs\_performance\_mode) | ECS cluser EFS performance mode | `string` | n/a | yes |
| <a name="input_ecs_cluster_efs_throughput_mode"></a> [ecs\_cluster\_efs\_throughput\_mode](#input\_ecs\_cluster\_efs\_throughput\_mode) | ECS cluser EFS throughput mode | `string` | n/a | yes |
| <a name="input_enable_infrastructure_ecs_cluster"></a> [enable\_infrastructure\_ecs\_cluster](#input\_enable\_infrastructure\_ecs\_cluster) | Enable creation of infrastructure ECS cluster, to place ECS services | `bool` | n/a | yes |
| <a name="input_enable_infrastructure_ecs_cluster_efs"></a> [enable\_infrastructure\_ecs\_cluster\_efs](#input\_enable\_infrastructure\_ecs\_cluster\_efs) | Conditionally create and mount EFS to the ECS cluster instances | `bool` | n/a | yes |
| <a name="input_enable_infrastructure_route53_hosted_zone"></a> [enable\_infrastructure\_route53\_hosted\_zone](#input\_enable\_infrastructure\_route53\_hosted\_zone) | Creates a Route53 hosted zone, where DNS records will be created for resources launched within this module. | `bool` | n/a | yes |
| <a name="input_environment"></a> [environment](#input\_environment) | The environment name to be used as part of the resource prefix | `string` | n/a | yes |
| <a name="input_infrastructure_dockerhub_email"></a> [infrastructure\_dockerhub\_email](#input\_infrastructure\_dockerhub\_email) | Dockerhub email | `string` | n/a | yes |
Expand Down
11 changes: 11 additions & 0 deletions ec2-userdata/ecs-instance.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,14 @@ fi
sudo yum install -y \
jq \
rsync
%{~ if efs_id != ""}
# EFS
sudo mkdir -p /mnt/efs
sudo yum install -y nfs-utils
echo '${efs_id}.efs.${region}.amazonaws.com:/ /mnt/efs nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0' | sudo tee -a /etc/fstab
sudo mount -a
%{if efs_dirs != "" ~}
cd /mnt/efs
mkdir -p ${efs_dirs}
cd ..
%{~ endif}%{endif}
16 changes: 16 additions & 0 deletions ecs-cluster-infrastructure.tf
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,18 @@ resource "aws_security_group_rule" "infrastructure_ecs_cluster_container_instanc
security_group_id = aws_security_group.infrastructure_ecs_cluster_container_instances[0].id
}

resource "aws_security_group_rule" "infrastructure_ecs_cluster_container_instances_egress_nfs_tcp" {
count = local.enable_infrastructure_ecs_cluster && local.enable_infrastructure_ecs_cluster_efs ? 1 : 0

description = "Allow NFS tcp outbound to EFS security group"
type = "egress"
from_port = 2049
to_port = 2049
protocol = "tcp"
source_security_group_id = aws_security_group.infrastructure_ecs_cluster_efs[0].id
security_group_id = aws_security_group.infrastructure_ecs_cluster_container_instances[0].id
}

resource "aws_iam_role" "infrastructure_ecs_cluster" {
count = local.enable_infrastructure_ecs_cluster ? 1 : 0

Expand Down Expand Up @@ -192,6 +204,10 @@ resource "aws_launch_template" "infrastructure_ecs_cluster" {
instance_type = local.infrastructure_ecs_cluster_instance_type

user_data = local.infrastructure_ecs_cluster_user_data

depends_on = [
aws_efs_mount_target.infrastructure_ecs_cluster,
]
}

resource "aws_placement_group" "infrastructure_ecs_cluster" {
Expand Down
54 changes: 54 additions & 0 deletions efs-infrastructure.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
resource "aws_efs_file_system" "infrastructure_ecs_cluster" {
count = local.enable_infrastructure_ecs_cluster_efs ? 1 : 0

encrypted = local.infrastructure_kms_encryption
kms_key_id = local.infrastructure_kms_encryption ? aws_kms_key.infrastructure[0].arn : null
performance_mode = local.ecs_cluster_efs_performance_mode
throughput_mode = local.ecs_cluster_efs_throughput_mode

dynamic "lifecycle_policy" {
for_each = local.ecs_cluster_efs_infrequent_access_transition != 0 ? [1] : []
content {
transition_to_ia = "AFTER_${local.ecs_cluster_efs_infrequent_access_transition}_DAYS"
}
}

dynamic "lifecycle_policy" {
for_each = local.ecs_cluster_efs_infrequent_access_transition != 0 ? [1] : []
content {
transition_to_primary_storage_class = "AFTER_1_ACCESS"
}
}
}

resource "aws_efs_mount_target" "infrastructure_ecs_cluster" {
for_each = local.enable_infrastructure_ecs_cluster_efs ? local.infrastructure_vpc_network_enable_private ? toset([
for subnet in aws_subnet.infrastructure_private : subnet.id
]) : local.infrastructure_vpc_network_enable_public ? toset([
for subnet in aws_subnet.infrastructure_public : subnet.id
]) : [] : []

file_system_id = aws_efs_file_system.infrastructure_ecs_cluster[0].id
subnet_id = each.value
security_groups = local.enable_infrastructure_ecs_cluster ? [aws_security_group.infrastructure_ecs_cluster_efs[0].id] : []
}

resource "aws_security_group" "infrastructure_ecs_cluster_efs" {
count = local.enable_infrastructure_ecs_cluster_efs && local.enable_infrastructure_ecs_cluster ? 1 : 0

name = "${local.resource_prefix}-infrastructure-ecs-cluster-efs"
description = "Infrastructure ECS cluster EFS"
vpc_id = aws_vpc.infrastructure[0].id
}

resource "aws_security_group_rule" "infrastructure_ecs_cluster_efs_ingress_nfs_tcp" {
count = local.enable_infrastructure_ecs_cluster_efs && local.enable_infrastructure_ecs_cluster ? 1 : 0

description = "Allow ECS instances access to EFS (NFS) tcp"
type = "ingress"
from_port = 2049
to_port = 2049
protocol = "tcp"
source_security_group_id = aws_security_group.infrastructure_ecs_cluster_container_instances[0].id
security_group_id = aws_security_group.infrastructure_ecs_cluster_efs[0].id
}
11 changes: 11 additions & 0 deletions locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,20 @@ locals {
dockerhub_token = local.infrastructure_dockerhub_token,
dockerhub_email = local.infrastructure_dockerhub_email,
docker_storage_size = local.infrastructure_ecs_cluster_ebs_docker_storage_volume_size
efs_id = local.enable_infrastructure_ecs_cluster_efs && (
local.infrastructure_vpc_network_enable_private || local.infrastructure_vpc_network_enable_public
) ? aws_efs_file_system.infrastructure_ecs_cluster[0].id : "",
region = local.aws_region,
efs_dirs = join(" ", local.ecs_cluster_efs_directories)
})
)

enable_infrastructure_ecs_cluster_efs = var.enable_infrastructure_ecs_cluster_efs && local.infrastructure_vpc
ecs_cluster_efs_performance_mode = var.ecs_cluster_efs_performance_mode
ecs_cluster_efs_throughput_mode = var.ecs_cluster_efs_throughput_mode
ecs_cluster_efs_infrequent_access_transition = var.ecs_cluster_efs_infrequent_access_transition
ecs_cluster_efs_directories = var.ecs_cluster_efs_directories

default_tags = {
Project = local.project_name,
Infrastructure = local.infrastructure_name,
Expand Down
25 changes: 25 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,28 @@ variable "infrastructure_ecs_cluster_autoscaling_time_based_custom" {
})
)
}

variable "enable_infrastructure_ecs_cluster_efs" {
description = "Conditionally create and mount EFS to the ECS cluster instances"
type = bool
}

variable "ecs_cluster_efs_performance_mode" {
description = "ECS cluser EFS performance mode"
type = string
}

variable "ecs_cluster_efs_throughput_mode" {
description = "ECS cluser EFS throughput mode"
type = string
}

variable "ecs_cluster_efs_infrequent_access_transition" {
description = "ECS cluser EFS IA transiton in days. Set to 0 to disable IA transition."
type = number
}

variable "ecs_cluster_efs_directories" {
description = "ECS cluster EFS directories to create"
type = list(string)
}
Loading