diff --git a/README.md b/README.md index f644209..52eca63 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ This module uses Semver. | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/examples/complete-ecs/README.md b/examples/complete-ecs/README.md index 1b31d48..bed7514 100644 --- a/examples/complete-ecs/README.md +++ b/examples/complete-ecs/README.md @@ -38,7 +38,7 @@ $ terraform apply | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/examples/easy/ec2-alb/README.md b/examples/easy/ec2-alb/README.md index 5809c4f..17a2b81 100644 --- a/examples/easy/ec2-alb/README.md +++ b/examples/easy/ec2-alb/README.md @@ -31,7 +31,7 @@ To test that it's working: | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/examples/easy/ec2-alb/main.tf b/examples/easy/ec2-alb/main.tf index 1e5535e..6f5d6f3 100644 --- a/examples/easy/ec2-alb/main.tf +++ b/examples/easy/ec2-alb/main.tf @@ -28,6 +28,8 @@ module "vpc" { enable_dhcp_options = true dhcp_options_domain_name_servers = ["AmazonProvidedDNS"] + map_public_ip_on_launch = true + enable_ipv6 = var.enable_ipv6 public_subnet_assign_ipv6_address_on_creation = var.enable_ipv6 public_subnet_ipv6_prefixes = range(length(local.vpc_azs)) @@ -118,9 +120,9 @@ module "asg" { max_size = 2 desired_capacity = 1 health_check_type = "EC2" - user_data = templatefile("../../templates/ec2_userdata.tpl", { + user_data = base64encode(templatefile("../../templates/ec2_userdata.tpl", { ecs_cluster = module.ecs_cluster.name - }) + })) iam_instance_profile_arn = var.instance_profile_arn } diff --git a/examples/easy/ec2-distinct/README.md b/examples/easy/ec2-distinct/README.md new file mode 100644 index 0000000..b749835 --- /dev/null +++ b/examples/easy/ec2-distinct/README.md @@ -0,0 +1,72 @@ +# examples/easy/ec2-distinct + +In this example we'll instantiate a simple nginx webserver running in **3 distinct instances**. + +Task networking mode in this example is `host` so that the port specified in `templates/container_definitions.tpl` will be bind. +Means there cannot be more than 1 task in an instance. Do experiment with dynamic port mapping with `bridge` network mode. + +This example will also create `vpc` and `security_group` and `autoscaling group`. + +Note: Instance profile is required for EC2 to connect to ECS Cluster. See [`modules/iam/ecs-instance-profile`](https://github.com/HENNGE/terraform-aws-ecs/tree/main/modules/iam/ecs-instance-profile). + +To test that it's working: +1. Go to EC2 console +1. Find the EC2 instance started by this example. (Search the name) +1. Go to the IP Address, you should see nginx hello world screen + +## Usage + +To run this example you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 3.74.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.32.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [asg](#module\_asg) | terraform-aws-modules/autoscaling/aws | ~> 7.0 | +| [easy\_ec2\_distinct\_instance\_mode](#module\_easy\_ec2\_distinct\_instance\_mode) | ../../../modules/simple/ec2 | n/a | +| [ec2\_security\_group](#module\_ec2\_security\_group) | terraform-aws-modules/security-group/aws | ~> 4.0 | +| [ecs\_cluster](#module\_ecs\_cluster) | ../../.. | n/a | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | +| [aws_ssm_parameter.ami_image](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [availability\_zones](#input\_availability\_zones) | Override automatic detection of availability zones | `list(string)` | `[]` | no | +| [enable\_ipv6](#input\_enable\_ipv6) | Enable IPv6? | `bool` | `true` | no | +| [instance\_profile\_arn](#input\_instance\_profile\_arn) | Instance Profile to use for EC2 to join to ECS Cluster. See `modules/iam/ecs-instance-profile` | `string` | n/a | yes | + +## Outputs + +No outputs. + + + diff --git a/examples/easy/ec2-distinct/main.tf b/examples/easy/ec2-distinct/main.tf new file mode 100644 index 0000000..fd621f0 --- /dev/null +++ b/examples/easy/ec2-distinct/main.tf @@ -0,0 +1,103 @@ +# Just Supporting Infrastructures + +data "aws_availability_zones" "available" {} + +data "aws_ssm_parameter" "ami_image" { + name = "/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id" +} + +locals { + prefix = "easy-ec2" + + vpc_cidr = "10.0.0.0/16" + discovered_azs = data.aws_availability_zones.available.names + vpc_azs = length(var.availability_zones) == 0 ? local.discovered_azs : var.availability_zones +} + +module "vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 5.0" + + name = "${local.prefix}-vpc" + cidr = local.vpc_cidr + azs = local.vpc_azs + + public_subnets = [for i in range(length(local.vpc_azs)) : cidrsubnet(local.vpc_cidr, 8, i)] + + enable_nat_gateway = false + enable_dhcp_options = true + dhcp_options_domain_name_servers = ["AmazonProvidedDNS"] + + map_public_ip_on_launch = true + + enable_ipv6 = var.enable_ipv6 + public_subnet_assign_ipv6_address_on_creation = var.enable_ipv6 + public_subnet_ipv6_prefixes = range(length(local.vpc_azs)) +} + +module "ec2_security_group" { + source = "terraform-aws-modules/security-group/aws" + version = "~> 4.0" + + name = "${local.prefix}-ec2-sg" + vpc_id = module.vpc.vpc_id + + + # Ingress for HTTP + ingress_cidr_blocks = ["0.0.0.0/0"] + ingress_ipv6_cidr_blocks = ["::/0"] + ingress_rules = ["http-80-tcp"] + + # Allow all egress + egress_cidr_blocks = ["0.0.0.0/0"] + egress_ipv6_cidr_blocks = ["::/0"] + egress_rules = ["all-all"] +} + +module "asg" { + source = "terraform-aws-modules/autoscaling/aws" + version = "~> 7.0" + + name = "${local.prefix}-asg" + + image_id = data.aws_ssm_parameter.ami_image.value + instance_type = "t2.micro" + security_groups = [module.ec2_security_group.security_group_id] + vpc_zone_identifier = module.vpc.public_subnets + min_size = 1 + max_size = 5 + desired_capacity = 3 + health_check_type = "EC2" + user_data = base64encode(templatefile("../../templates/ec2_userdata.tpl", { + ecs_cluster = module.ecs_cluster.name + })) + iam_instance_profile_arn = var.instance_profile_arn +} + +# This module usage starts here +module "ecs_cluster" { + source = "../../.." + + name = "${local.prefix}-cluster" +} + +module "easy_ec2_distinct_instance_mode" { + source = "../../../modules/simple/ec2" + + name = "${local.prefix}-service" + cluster = module.ecs_cluster.name + cpu = 256 + memory = 512 + desired_count = 3 + ignore_desired_count_changes = false + + network_mode = "host" + + distinct_instance = true + + container_definitions = templatefile("../../templates/container_definitions.tpl", { + name = "${local.prefix}-cont" + cpu = 256 + memory = 512 + }) +} diff --git a/examples/easy/ec2-distinct/outputs.tf b/examples/easy/ec2-distinct/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/examples/easy/ec2-distinct/variables.tf b/examples/easy/ec2-distinct/variables.tf new file mode 100644 index 0000000..c549865 --- /dev/null +++ b/examples/easy/ec2-distinct/variables.tf @@ -0,0 +1,16 @@ +variable "instance_profile_arn" { + description = "Instance Profile to use for EC2 to join to ECS Cluster. See `modules/iam/ecs-instance-profile`" + type = string +} + +variable "availability_zones" { + description = "Override automatic detection of availability zones" + default = [] + type = list(string) +} + +variable "enable_ipv6" { + description = "Enable IPv6?" + default = true + type = bool +} diff --git a/examples/easy/ec2-distinct/versions.tf b/examples/easy/ec2-distinct/versions.tf new file mode 100644 index 0000000..88a651b --- /dev/null +++ b/examples/easy/ec2-distinct/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 3.74.0" + } + } +} diff --git a/examples/easy/ec2/README.md b/examples/easy/ec2/README.md index 8bf3b8a..b3cb000 100644 --- a/examples/easy/ec2/README.md +++ b/examples/easy/ec2/README.md @@ -37,7 +37,7 @@ $ terraform apply | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/examples/easy/ec2/main.tf b/examples/easy/ec2/main.tf index a39e5b6..e26bcb6 100644 --- a/examples/easy/ec2/main.tf +++ b/examples/easy/ec2/main.tf @@ -28,6 +28,8 @@ module "vpc" { enable_dhcp_options = true dhcp_options_domain_name_servers = ["AmazonProvidedDNS"] + map_public_ip_on_launch = true + enable_ipv6 = var.enable_ipv6 public_subnet_assign_ipv6_address_on_creation = var.enable_ipv6 public_subnet_ipv6_prefixes = range(length(local.vpc_azs)) @@ -66,9 +68,9 @@ module "asg" { max_size = 2 desired_capacity = 1 health_check_type = "EC2" - user_data = templatefile("../../templates/ec2_userdata.tpl", { + user_data = base64encode(templatefile("../../templates/ec2_userdata.tpl", { ecs_cluster = module.ecs_cluster.name - }) + })) iam_instance_profile_arn = var.instance_profile_arn } diff --git a/examples/easy/fargate-alb/README.md b/examples/easy/fargate-alb/README.md index 74bc600..72636fa 100644 --- a/examples/easy/fargate-alb/README.md +++ b/examples/easy/fargate-alb/README.md @@ -38,7 +38,7 @@ $ terraform apply | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/examples/easy/fargate-spot/README.md b/examples/easy/fargate-spot/README.md index 8394aaf..c306c55 100644 --- a/examples/easy/fargate-spot/README.md +++ b/examples/easy/fargate-spot/README.md @@ -43,7 +43,7 @@ $ terraform apply | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/examples/easy/fargate/README.md b/examples/easy/fargate/README.md index 171349d..d38e884 100644 --- a/examples/easy/fargate/README.md +++ b/examples/easy/fargate/README.md @@ -36,7 +36,7 @@ $ terraform apply | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/modules/autoscaling/alb-target-tracking/target-requests-count/README.md b/modules/autoscaling/alb-target-tracking/target-requests-count/README.md index c72ce54..4429414 100644 --- a/modules/autoscaling/alb-target-tracking/target-requests-count/README.md +++ b/modules/autoscaling/alb-target-tracking/target-requests-count/README.md @@ -70,7 +70,7 @@ module "ecs_service_scaling" { | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/modules/autoscaling/alb-target-tracking/target-response-time/README.md b/modules/autoscaling/alb-target-tracking/target-response-time/README.md index 4dbce74..c06a169 100644 --- a/modules/autoscaling/alb-target-tracking/target-response-time/README.md +++ b/modules/autoscaling/alb-target-tracking/target-response-time/README.md @@ -71,7 +71,7 @@ module "ecs_service_scaling" { | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/modules/autoscaling/asg-target-tracking/ecs-reservation/README.md b/modules/autoscaling/asg-target-tracking/ecs-reservation/README.md index 8473f85..1b7d199 100644 --- a/modules/autoscaling/asg-target-tracking/ecs-reservation/README.md +++ b/modules/autoscaling/asg-target-tracking/ecs-reservation/README.md @@ -85,7 +85,7 @@ module "asg_scaling" { | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/modules/autoscaling/ecs-scheduled/README.md b/modules/autoscaling/ecs-scheduled/README.md index db57a7a..0aa34ce 100644 --- a/modules/autoscaling/ecs-scheduled/README.md +++ b/modules/autoscaling/ecs-scheduled/README.md @@ -47,7 +47,7 @@ module "ecs_scaling_scheduled" { | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/modules/autoscaling/ecs-target-tracking/service-utilization/README.md b/modules/autoscaling/ecs-target-tracking/service-utilization/README.md index 5000305..8553e32 100644 --- a/modules/autoscaling/ecs-target-tracking/service-utilization/README.md +++ b/modules/autoscaling/ecs-target-tracking/service-utilization/README.md @@ -62,7 +62,7 @@ module "ecs_service_scaling" { | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/modules/core/ecs-autoscaling-target/README.md b/modules/core/ecs-autoscaling-target/README.md index e5e41ec..66fbd26 100644 --- a/modules/core/ecs-autoscaling-target/README.md +++ b/modules/core/ecs-autoscaling-target/README.md @@ -61,7 +61,7 @@ module "ecs_service_scaling_target" { | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/modules/core/service/main.tf b/modules/core/service/main.tf index 8efa148..2cdd7ad 100644 --- a/modules/core/service/main.tf +++ b/modules/core/service/main.tf @@ -73,8 +73,8 @@ resource "aws_ecs_service" "main" { dynamic "placement_constraints" { for_each = var.service_placement_constraints content { - type = lookup(service_placement_constraints.value, "type", null) - expression = lookup(service_placement_constraints.value, "expression", null) + type = lookup(placement_constraints.value, "type", null) + expression = lookup(placement_constraints.value, "expression", null) } } @@ -173,8 +173,8 @@ resource "aws_ecs_service" "main_ignore_desired_count_changes" { dynamic "placement_constraints" { for_each = var.service_placement_constraints content { - type = lookup(service_placement_constraints.value, "type", null) - expression = lookup(service_placement_constraints.value, "expression", null) + type = lookup(placement_constraints.value, "type", null) + expression = lookup(placement_constraints.value, "expression", null) } } diff --git a/modules/core/task/README.md b/modules/core/task/README.md index ff8be56..d31fd8e 100644 --- a/modules/core/task/README.md +++ b/modules/core/task/README.md @@ -18,7 +18,7 @@ Almost a 1-1 mapping to `resources`. | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/modules/iam/ecs-instance-profile/README.md b/modules/iam/ecs-instance-profile/README.md index c22ad5a..9552d7f 100644 --- a/modules/iam/ecs-instance-profile/README.md +++ b/modules/iam/ecs-instance-profile/README.md @@ -16,7 +16,7 @@ Module to generate IAM Instance Profile (and Role) for EC2 instances backing ECS | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/modules/scheduled-actions/README.md b/modules/scheduled-actions/README.md index 05ceefc..49b19be 100644 --- a/modules/scheduled-actions/README.md +++ b/modules/scheduled-actions/README.md @@ -82,7 +82,7 @@ module "ecs_fargate_cron" { | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 3.74.0 | +| [aws](#provider\_aws) | 5.32.0 | ## Modules diff --git a/modules/simple/ec2/README.md b/modules/simple/ec2/README.md index 92ec49b..260104d 100644 --- a/modules/simple/ec2/README.md +++ b/modules/simple/ec2/README.md @@ -49,6 +49,7 @@ No resources. | [deployment\_maximum\_percent](#input\_deployment\_maximum\_percent) | upper limit (% of `desired_count`) of # of running tasks during a deployment. Do not fill when using `DAEMON` scheduling strategy. | `number` | `null` | no | | [deployment\_minimum\_healthy\_percent](#input\_deployment\_minimum\_healthy\_percent) | lower limit (% of `desired_count`) of # of running tasks during a deployment | `number` | `100` | no | | [desired\_count](#input\_desired\_count) | The number of instances of the task definition to place and keep running. Defaults to 0. Do not specify if using the `DAEMON` scheduling strategy. | `number` | `null` | no | +| [distinct\_instance](#input\_distinct\_instance) | Make the service run tasks in distinct instance. Sets the service\_placement\_constraints to distinctInstance. | `bool` | `false` | no | | [elb\_name](#input\_elb\_name) | Name of ELB (Classic ELB) to associate with the service | `string` | `null` | no | | [enable\_deployment\_circuit\_breaker\_with\_rollback](#input\_enable\_deployment\_circuit\_breaker\_with\_rollback) | Enable Deployment Circuit Breaker with Rollback. When a service deployment fails, the service is rolled back to the last deployment that completed successfully. | `bool` | `false` | no | | [enable\_deployment\_circuit\_breaker\_without\_rollback](#input\_enable\_deployment\_circuit\_breaker\_without\_rollback) | Enable Deployment Circuit Breaker without Rollback. | `bool` | `false` | no | @@ -66,11 +67,9 @@ No resources. | [propagate\_tags](#input\_propagate\_tags) | Specifies whether to propagate the tags from the task definition or the service to the tasks. The valid values are `SERVICE` and `TASK_DEFINITION`. | `string` | `null` | no | | [proxy\_configuration](#input\_proxy\_configuration) | The proxy configuration details for the App Mesh proxy. Defined as map argument. [Terraform Docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition#proxy_configuration) | `any` | `null` | no | | [runtime\_platform](#input\_runtime\_platform) | Runtime platform (operating system and CPU architecture) that containers may use. Defined as map argument. [Terraform Docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition#runtime_platform) | `any` | `null` | no | -| [service\_placement\_constraints](#input\_service\_placement\_constraints) | List of map of placement constraints for Service. Max 10. [Terraform Docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service#placement_constraints) | `list(any)` | `[]` | no | | [service\_registry](#input\_service\_registry) | Map of a service discovery registries for the service. Consists of `registry_arn`, `port`(optional), `container_port`(optional), `container_port`(optional). [Terraform Docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service#service_registries) | `any` | `null` | no | | [tags](#input\_tags) | Key-value mapping of resource tags | `map(string)` | `{}` | no | | [target\_group\_arn](#input\_target\_group\_arn) | ARN of the Application Load Balancer / Network Load Balancer target group | `string` | `null` | no | -| [task\_placement\_constraints](#input\_task\_placement\_constraints) | Placement constraints for Task Definition. List of map. [Terraform Docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition#placement_constraints) | `list(any)` | `[]` | no | | [volume\_configurations](#input\_volume\_configurations) | Volume Block Arguments for Task Definition. List of map. Note that `docker_volume_configuration` should be specified as map argument instead of block. [Terraform Docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition#volume) | `list(any)` | `[]` | no | | [wait\_for\_steady\_state](#input\_wait\_for\_steady\_state) | If `true`, Terraform will wait for the service to reach a steady state (like aws ecs wait services-stable) before continuing. | `bool` | `null` | no | diff --git a/modules/simple/ec2/main.tf b/modules/simple/ec2/main.tf index 4ebff0a..46dbc47 100644 --- a/modules/simple/ec2/main.tf +++ b/modules/simple/ec2/main.tf @@ -45,8 +45,7 @@ module "ec2" { } ] - service_placement_constraints = var.service_placement_constraints - task_placement_constraints = var.task_placement_constraints + service_placement_constraints = var.distinct_instance ? [{ type = "distinctInstance" }] : [] wait_for_steady_state = var.wait_for_steady_state diff --git a/modules/simple/ec2/variables.tf b/modules/simple/ec2/variables.tf index 0f22494..7510210 100644 --- a/modules/simple/ec2/variables.tf +++ b/modules/simple/ec2/variables.tf @@ -149,16 +149,10 @@ variable "capacity_provider_arn" { type = string } -variable "service_placement_constraints" { - description = "List of map of placement constraints for Service. Max 10. [Terraform Docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service#placement_constraints)" - default = [] - type = list(any) -} - -variable "task_placement_constraints" { - description = "Placement constraints for Task Definition. List of map. [Terraform Docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition#placement_constraints)" - default = [] - type = list(any) +variable "distinct_instance" { + description = "Make the service run tasks in distinct instance. Sets the service_placement_constraints to distinctInstance." + default = false + type = bool } variable "enable_deployment_circuit_breaker_without_rollback" {