-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feature] Add ECS modules to cztack (#132)
- Loading branch information
Showing
28 changed files
with
2,205 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# ECS Job on Fargate | ||
|
||
This creates an ECS service running on Fargate with no load balancer in front of it. Good for | ||
background worker daemon sort of things. | ||
|
||
## Terraform managed task definition vs czecs | ||
|
||
If the user sets `var.manage_task_definition = true`, Terraform will manage the lifecycle | ||
of the container definition; any external changes are reset on the next Terraform run. | ||
|
||
If var.manage_task_definition = false, the user is expected to manage the | ||
container definition external to Terraform (e.g. using [czecs](https://github.com/chanzuckerberg/czecs)). Upon creation, | ||
Terraform will use a stub definition, but from that point forward will ignore any | ||
changes to the definition, allowing external task definition management. | ||
|
||
<!-- START --> | ||
## Inputs | ||
|
||
| Name | Description | Type | Default | Required | | ||
|------|-------------|:----:|:-----:|:-----:| | ||
| cluster\_id | | string | n/a | yes | | ||
| container\_name | Name of the container. Must match name in task definition. If omitted, defaults to name derived from project/env/service. | string | `null` | no | | ||
| cpu | CPU units for Fargate task. Used if task_definition provided, or for initial stub task if externally managed. | number | `256` | no | | ||
| deployment\_maximum\_percent | (Optional) The upper limit (as a percentage of the service's desiredCount) of the number of running tasks that can be running in a service during a deployment. Not valid when using the DAEMON scheduling strategy. | number | `200` | no | | ||
| deployment\_minimum\_healthy\_percent | (Optional) The lower limit (as a percentage of the service's desiredCount) of the number of running tasks that must remain running and healthy in a service during a deployment. | number | `100` | no | | ||
| desired\_count | | number | n/a | yes | | ||
| env | Env for tagging and naming. See [doc](../README.md#consistent-tagging). | string | n/a | yes | | ||
| memory | Memory in megabytes for Fargate task. Used if task_definition provided, or for initial stub task if externally managed. | number | `512` | no | | ||
| project | Project for tagging and naming. See [doc](../README.md#consistent-tagging) | string | n/a | yes | | ||
| registry\_secretsmanager\_arn | ARN for AWS Secrets Manager secret for credentials to private registry | string | `null` | no | | ||
| security\_group\_ids | Security group to use for the Fargate task. | list | `<list>` | no | | ||
| service | Service for tagging and naming. See [doc](../README.md#consistent-tagging). | string | n/a | yes | | ||
| task\_definition | JSON to describe task. If omitted, defaults to a stub task that is expected to be managed outside of Terraform. | string | `null` | no | | ||
| task\_role\_arn | | string | n/a | yes | | ||
| task\_subnets | Subnets to launch Fargate task in. | list | `<list>` | no | | ||
|
||
## Outputs | ||
|
||
| Name | Description | | ||
|------|-------------| | ||
| ecs\_service\_arn | ARN for the ECS service. | | ||
| ecs\_task\_definition\_family | The family of the task definition defined for the given/generated container definition. | | ||
| task\_execution\_role\_arn | Task execution role for Fargate task. | | ||
|
||
<!-- END --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
data "aws_iam_policy_document" "execution_role" { | ||
statement { | ||
principals { | ||
type = "Service" | ||
identifiers = ["ecs-tasks.amazonaws.com"] | ||
} | ||
|
||
actions = ["sts:AssumeRole"] | ||
} | ||
} | ||
|
||
# Always create and attach, Fargate requires task definition to have execution role ARN to support log driver awslogs. | ||
resource "aws_iam_role" "task_execution_role" { | ||
name = "${local.name}-execution-role" | ||
assume_role_policy = data.aws_iam_policy_document.execution_role.json | ||
} | ||
|
||
# TODO(mbarrien): We can probably narrow this down to allowing access to only | ||
# the specific ECR arn if applicable, and the specific cloudwatch log group. | ||
# Either pass both identifiers in, or pass the entire role ARN as an argument | ||
resource "aws_iam_role_policy_attachment" "task_execution_role" { | ||
count = var.registry_secretsmanager_arn != null ? 1 : 0 | ||
role = aws_iam_role.task_execution_role.name | ||
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" | ||
} | ||
|
||
data "aws_iam_policy_document" "registry_secretsmanager" { | ||
count = var.registry_secretsmanager_arn != null ? 1 : 0 | ||
|
||
statement { | ||
actions = [ | ||
"kms:Decrypt", | ||
] | ||
|
||
resources = [var.registry_secretsmanager_arn] | ||
} | ||
|
||
statement { | ||
actions = [ | ||
"secretsmanager:GetSecretValue", | ||
] | ||
|
||
# Limit to only current version of the secret | ||
condition { | ||
test = "ForAnyValue:StringEquals" | ||
variable = "secretsmanager:VersionStage" | ||
values = ["AWSCURRENT"] | ||
} | ||
|
||
resources = [var.registry_secretsmanager_arn] | ||
} | ||
} | ||
|
||
resource "aws_iam_role_policy" "task_execution_role_secretsmanager" { | ||
count = var.registry_secretsmanager_arn != null ? 1 : 0 | ||
role = aws_iam_role.task_execution_role.name | ||
policy = data.aws_iam_policy_document.registry_secretsmanager[0].json | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
locals { | ||
name = "${var.project}-${var.env}-${var.service}" | ||
|
||
container_name = var.container_name == null ? local.name : var.container_name | ||
|
||
task_definition = "${aws_ecs_task_definition.job.family}:${aws_ecs_task_definition.job.revision}" | ||
|
||
tags = { | ||
managedBy = "terraform" | ||
Name = local.name | ||
project = var.project | ||
env = var.env | ||
service = var.service | ||
owner = var.owner | ||
} | ||
} | ||
|
||
# Only one of the following is active at a time, depending on var.manage_task_definition | ||
resource "aws_ecs_service" "job" { | ||
name = local.name | ||
cluster = var.cluster_id | ||
count = var.manage_task_definition ? 1 : 0 | ||
launch_type = "FARGATE" | ||
|
||
task_definition = local.task_definition | ||
desired_count = var.desired_count | ||
deployment_maximum_percent = var.deployment_maximum_percent | ||
deployment_minimum_healthy_percent = var.deployment_minimum_healthy_percent | ||
scheduling_strategy = "REPLICA" | ||
|
||
network_configuration { | ||
subnets = var.task_subnets | ||
security_groups = var.security_group_ids | ||
} | ||
|
||
tags = local.tags | ||
} | ||
|
||
resource "aws_ecs_service" "unmanaged-job" { | ||
name = local.name | ||
cluster = var.cluster_id | ||
count = var.manage_task_definition ? 0 : 1 | ||
launch_type = "FARGATE" | ||
|
||
task_definition = local.task_definition | ||
desired_count = var.desired_count | ||
deployment_maximum_percent = var.deployment_maximum_percent | ||
deployment_minimum_healthy_percent = var.deployment_minimum_healthy_percent | ||
scheduling_strategy = "REPLICA" | ||
|
||
network_configuration { | ||
subnets = var.task_subnets | ||
security_groups = var.security_group_ids | ||
} | ||
|
||
lifecycle { | ||
ignore_changes = [task_definition] | ||
} | ||
|
||
tags = local.tags | ||
} | ||
|
||
# Default container definition if var.manage_task_definition == false | ||
# Defaults to a minimal hello-world implementation; should be updated separately from | ||
# Terraform, e.g. using ecs deploy or czecs | ||
locals { | ||
template = <<TEMPLATE | ||
[ | ||
{ | ||
"name": "${local.container_name}", | ||
"image": "library/busybox:1.29", | ||
"command": ["sh", "-c", "while true; do { echo -e 'HTTP/1.1 200 OK\r\n\nRunning stub server'; date; } | nc -l -p 8080; done"] | ||
} | ||
] | ||
TEMPLATE | ||
} | ||
|
||
resource "aws_ecs_task_definition" "job" { | ||
family = local.name | ||
container_definitions = var.manage_task_definition ? var.task_definition : local.template | ||
task_role_arn = var.task_role_arn | ||
requires_compatibilities = ["FARGATE"] | ||
cpu = var.cpu | ||
memory = var.memory | ||
network_mode = "awsvpc" | ||
execution_role_arn = aws_iam_role.task_execution_role.arn | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
output "ecs_service_arn" { | ||
description = "ARN for the ECS service." | ||
|
||
# Awful hack modified from https://github.com/hashicorp/terraform/issues/16726 | ||
# Since we know exactly one of the following has count > 0, we just concatenate all the mostly empty lists, and return the first element. | ||
value = concat(aws_ecs_service.unmanaged-job.*.id, aws_ecs_service.job.*.id)[0] | ||
} | ||
|
||
output "ecs_task_definition_family" { | ||
description = "The family of the task definition defined for the given/generated container definition." | ||
value = aws_ecs_task_definition.job.family | ||
} | ||
|
||
output "task_execution_role_arn" { | ||
description = "Task execution role for Fargate task." | ||
value = aws_iam_role.task_execution_role.arn | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
variable "project" { | ||
type = string | ||
description = "Project for tagging and naming. See [doc](../README.md#consistent-tagging)" | ||
} | ||
|
||
variable "service" { | ||
type = string | ||
description = "Service for tagging and naming. See [doc](../README.md#consistent-tagging)." | ||
} | ||
|
||
variable "env" { | ||
type = string | ||
description = "Env for tagging and naming. See [doc](../README.md#consistent-tagging)." | ||
} | ||
|
||
variable "owner" { | ||
type = string | ||
description = "Owner for tagging and naming. See [doc](../README.md#consistent-tagging)." | ||
} | ||
|
||
variable "cluster_id" { | ||
type = string | ||
} | ||
|
||
variable "desired_count" { | ||
type = number | ||
} | ||
|
||
variable "deployment_maximum_percent" { | ||
description = "(Optional) The upper limit (as a percentage of the service's desiredCount) of the number of running tasks that can be running in a service during a deployment. Not valid when using the DAEMON scheduling strategy." | ||
type = number | ||
default = 200 | ||
} | ||
|
||
variable "deployment_minimum_healthy_percent" { | ||
description = "(Optional) The lower limit (as a percentage of the service's desiredCount) of the number of running tasks that must remain running and healthy in a service during a deployment." | ||
type = number | ||
default = 100 | ||
} | ||
|
||
variable "task_role_arn" { | ||
type = string | ||
} | ||
|
||
variable "task_definition" { | ||
description = "JSON to describe task. If omitted, defaults to a stub task that is expected to be managed outside of Terraform." | ||
type = string | ||
default = null | ||
} | ||
|
||
variable "cpu" { | ||
description = "CPU units for Fargate task. Used if task_definition provided, or for initial stub task if externally managed." | ||
type = number | ||
default = 256 | ||
} | ||
|
||
variable "memory" { | ||
description = "Memory in megabytes for Fargate task. Used if task_definition provided, or for initial stub task if externally managed." | ||
type = number | ||
default = 512 | ||
} | ||
|
||
variable "task_subnets" { | ||
description = "Subnets to launch Fargate task in." | ||
type = list(string) | ||
default = [] | ||
} | ||
|
||
variable "security_group_ids" { | ||
description = "Security group to use for the Fargate task." | ||
type = list(string) | ||
default = [] | ||
} | ||
|
||
variable "container_name" { | ||
description = "Name of the container. Must match name in task definition. If omitted, defaults to name derived from project/env/service." | ||
type = string | ||
default = null | ||
} | ||
|
||
variable "registry_secretsmanager_arn" { | ||
description = "ARN for AWS Secrets Manager secret for credentials to private registry" | ||
type = string | ||
default = null | ||
} | ||
|
||
variable "manage_task_definition" { | ||
description = "If false, Terraform will not touch the task definition for the ECS service after initial creation" | ||
type = bool | ||
default = true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# ECS Job | ||
|
||
This creates an ECS service with no load balancer in front of it. Good for | ||
background worker daemon sort of things. | ||
|
||
## Terraform managed task definition vs czecs | ||
|
||
If the user sets `var.manage_task_definition = true`, Terraform will manage the lifecycle | ||
of the container definition; any external changes are reset on the next Terraform run. | ||
|
||
If var.manage_task_definition = false, the user is expected to manage the | ||
container definition external to Terraform (e.g. using [czecs](https://github.com/chanzuckerberg/czecs)). Upon creation, | ||
Terraform will use a stub definition, but from that point forward will ignore any | ||
changes to the definition, allowing external task definition management. | ||
|
||
<!-- START --> | ||
## Inputs | ||
|
||
| Name | Description | Type | Default | Required | | ||
|------|-------------|:----:|:-----:|:-----:| | ||
| cluster\_id | | string | n/a | yes | | ||
| container\_name | Name of the container. Must match name in task definition. If omitted, defaults to name derived from project/env/service. | string | `null` | no | | ||
| deployment\_maximum\_percent | (Optional) The upper limit (as a percentage of the service's desiredCount) of the number of running tasks that can be running in a service during a deployment. Not valid when using the DAEMON scheduling strategy. | number | `200` | no | | ||
| deployment\_minimum\_healthy\_percent | (Optional) The lower limit (as a percentage of the service's desiredCount) of the number of running tasks that must remain running and healthy in a service during a deployment. | number | `100` | no | | ||
| desired\_count | | number | n/a | yes | | ||
| env | Env for tagging and naming. See [doc](../README.md#consistent-tagging). | string | n/a | yes | | ||
| project | Project for tagging and naming. See [doc](../README.md#consistent-tagging) | string | n/a | yes | | ||
| scheduling\_strategy | Scheduling strategy for the service: REPLICA or DAEMON. | string | `"REPLICA"` | no | | ||
| service | Service for tagging and naming. See [doc](../README.md#consistent-tagging). | string | n/a | yes | | ||
| task\_definition | JSON to describe task. If omitted, defaults to a stub task that is expected to be managed outside of Terraform. | string | `null` | no | | ||
| task\_role\_arn | | string | n/a | yes | | ||
|
||
## Outputs | ||
|
||
| Name | Description | | ||
|------|-------------| | ||
| ecs\_service\_arn | ARN for the ECS service. | | ||
| ecs\_task\_definition\_family | The family of the task definition defined for the given/generated container definition. | | ||
|
||
<!-- END --> |
Oops, something went wrong.