-
-
Couldn't load subscription status.
- Fork 631
Create ECS cluster #2
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
Changes from 5 commits
79d2d1b
d7cbfa4
a293e01
cfbf963
5a53fd4
dae88fd
5c8e9d5
128fafb
5a8bdde
b59be38
705a1f9
de0adba
48bd9e1
3adccfb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| .terraform | ||
| terraform.tfstate | ||
| *.tfstate* | ||
| terraform.tfvars | ||
| todo.txt |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,38 @@ | ||
| # terraform-aws-ecs | ||
|
|
||
| Terraform module which creates AWS ECS resources | ||
|
|
||
| This module focuses purely on ECS and nothing else. Therefore only these resources can be created with this module: | ||
|
|
||
| * [ECS](https://www.terraform.io/docs/providers/aws/r/ecs_cluster.html) | ||
| * [IAM](https://www.terraform.io/docs/providers/aws/r/iam_instance_profile.html) | ||
|
|
||
| However, having said the above to have a proper ECS cluster up and running multiple resources are needed. In most cases creating these resources is heavily opinionated and or context-bound. That is why this module does not create these resources. But you still need them to have a production ready environment. Therefore the example area shows how to create everything needed for a production environment. | ||
|
|
||
| ## Usage | ||
|
|
||
| ```hcl | ||
| module "ecs" { | ||
| source = "terraform-aws-modules/ecs/aws" | ||
| name = "my-ecs" | ||
| } | ||
| ``` | ||
|
|
||
| ## Conditional creation | ||
|
|
||
| Sometimes you need to have a way to create ECS resources conditionally but Terraform does not allow to use `count` inside `module` block, so the solution is to specify argument `create_ecs`. | ||
|
|
||
| ```hcl | ||
| # ECS cluster will not be created | ||
| module "ecs" { | ||
| source = "terraform-aws-modules/ecs/aws" | ||
| create_ecs = false | ||
| # ... omitted | ||
| } | ||
| ``` | ||
|
|
||
| ## License | ||
|
|
||
| **WORK IN PROGRESS** | ||
| Apache 2 Licensed. See LICENSE for full details. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| # Complete ECS | ||
|
|
||
| This example uses only verified Terraform modules to create all resources that are needed for an ECS cluster that is sufficient for staging or production environment. | ||
|
|
||
| While this example is still in the early stage there are other repositories that show how to create an ECS cluster: | ||
|
|
||
| * <https://github.com/anrim/terraform-aws-ecs> | ||
| * <https://github.com/arminc/terraform-ecs> | ||
| * <https://github.com/alex/ecs-terraform> | ||
| * <https://github.com/Capgemini/terraform-amazon-ecs> | ||
|
|
||
| ## TODO | ||
|
|
||
| Things still needed in the example: | ||
|
|
||
| * AWS network infrastructure on what is created | ||
| * Full explanation on why certain resources are created | ||
| * Create EC2 instance specific SecurityGroup instead of using the default one from VPC module | ||
| * Push logs of default EC2 stuff (docker, ecs agent, etc...) to CloudWatch logs | ||
| * Add an example with ALB | ||
| * Add an example with NLB | ||
| * Add an example with ELB | ||
| * Create a Fargate example | ||
|
|
||
| ## Usage | ||
|
|
||
| To run this example you need to execute: | ||
|
|
||
| ```bash | ||
| terraform init | ||
| terraform plan | ||
| terraform apply | ||
| ``` | ||
|
|
||
| Note that this example may create resources which can cost money (AWS EC2 instances, for example). Run `terraform destroy` when you don't need these resources. | ||
|
|
||
| ## Explanation | ||
|
|
||
| Current version creates an high-available VPC with instances that are attached to ECS. ECS tasks can be run on these instances but they are not exposed to anything. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| #For now we only use the AWS ECS optimized ami <https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html> | ||
| data "aws_ami" "amazon_linux_ecs" { | ||
| most_recent = true | ||
|
|
||
| filter { | ||
| name = "name" | ||
| values = ["amzn-ami-*-amazon-ecs-optimized"] | ||
| } | ||
|
|
||
| filter { | ||
| name = "owner-alias" | ||
| values = ["amazon"] | ||
| } | ||
| } | ||
|
|
||
| # This is the convention we use to know wht belongs to each other | ||
| locals { | ||
| name = "${var.ecs_cluster}-${var.environment}" | ||
| } | ||
|
|
||
| module "this" { | ||
| source = "terraform-aws-modules/autoscaling/aws" | ||
| version = "v2.2.2" | ||
|
|
||
| name = "${local.name}" | ||
|
|
||
| # Launch configuration | ||
| lc_name = "${local.name}" | ||
|
|
||
| image_id = "${data.aws_ami.amazon_linux_ecs.id}" | ||
| instance_type = "t2.micro" | ||
| security_groups = "${var.security_groups}" | ||
| iam_instance_profile = "${var.ec2_profile}" | ||
| user_data = "${data.template_file.user_data.rendered}" | ||
|
|
||
| # Auto scaling group | ||
| asg_name = "${local.name}" | ||
| vpc_zone_identifier = "${var.vpc_zone_identifier}" | ||
| health_check_type = "EC2" | ||
| min_size = 0 | ||
| max_size = 1 | ||
| desired_capacity = 1 | ||
| wait_for_capacity_timeout = 0 | ||
|
|
||
| tags = [ | ||
| { | ||
| key = "Environment" | ||
| value = "${var.environment}" | ||
| propagate_at_launch = true | ||
| }, | ||
| { | ||
| key = "Cluster" | ||
| value = "${var.ecs_cluster}" | ||
| propagate_at_launch = true | ||
| }, | ||
| ] | ||
| } | ||
|
|
||
| data "template_file" "user_data" { | ||
| template = "${file("${path.module}/templates/user-data.sh")}" | ||
|
|
||
| vars { | ||
| cluster_name = "${var.ecs_cluster}" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #!/bin/bash | ||
|
|
||
| # ECS config | ||
| { | ||
| echo "ECS_CLUSTER=${cluster_name}" | ||
| } >> /etc/ecs/ecs.config | ||
|
|
||
| start ecs | ||
|
|
||
| echo "Done" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| variable "environment" { | ||
| description = "Name of the Environment, for example dev" | ||
| default = "dev" | ||
| } | ||
|
|
||
| variable "ecs_cluster" { | ||
| description = "Name of the ECS cluster, name to be used on all the resources as identifier" | ||
| } | ||
|
|
||
| variable "vpc_zone_identifier" { | ||
| description = "A list of subnet IDs to launch resources in" | ||
| type = "list" | ||
| } | ||
|
|
||
| variable "security_groups" { | ||
| description = "A list of security group IDs to assign to the launch configuration" | ||
| type = "list" | ||
| } | ||
|
|
||
| # ASG | ||
| variable "max_size" { | ||
| description = "The maximum size of the auto scale group" | ||
| default = 1 | ||
| } | ||
|
|
||
| variable "min_size" { | ||
| description = "The minimum size of the auto scale group" | ||
| default = 0 | ||
| } | ||
|
|
||
| variable "desired_capacity" { | ||
| description = "The number of Amazon EC2 instances that should be running in the group" | ||
| default = 1 | ||
| } | ||
|
|
||
| variable "wait_for_capacity_timeout" { | ||
| description = "A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. (See also Waiting for Capacity below.) Setting this to '0' causes Terraform to skip all Capacity Waiting behavior." | ||
| default = "10m" | ||
| } | ||
|
|
||
| variable "ec2_profile" {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| provider "aws" { | ||
| region = "eu-west-1" | ||
| version = "v1.18.0" | ||
|
||
| } | ||
|
|
||
| provider "terraform" {} | ||
|
|
||
| locals { | ||
| name = "my-ecs" | ||
|
||
| } | ||
|
|
||
| module "vpc" { | ||
| source = "terraform-aws-modules/vpc/aws" | ||
| version = "v1.30.0" | ||
|
||
|
|
||
| name = "${local.name}" | ||
|
|
||
| cidr = "10.1.0.0/16" | ||
|
|
||
| azs = ["eu-west-1a", "eu-west-1b"] | ||
| private_subnets = ["10.1.1.0/24", "10.1.2.0/24"] | ||
| public_subnets = ["10.1.11.0/24", "10.1.12.0/24"] | ||
|
|
||
| enable_nat_gateway = true | ||
| single_nat_gateway = true | ||
|
|
||
| tags = { | ||
| Environment = "${local.name}" | ||
| Name = "${local.name}" | ||
| } | ||
| } | ||
|
|
||
| #----- ECS -------- | ||
| module "ecs" { | ||
| source = "../../" | ||
| name = "${local.name}" | ||
| } | ||
|
|
||
| module "ec2-profile" { | ||
| source = "../../modules/ecs-instance-profile" | ||
| name = "my-ecs" | ||
| } | ||
|
|
||
| #----- ECS Resources-------- | ||
| module "ec2" { | ||
|
||
| source = "ec2-instances" | ||
| ecs_cluster = "${local.name}" | ||
| vpc_zone_identifier = ["${module.vpc.private_subnets}"] | ||
| security_groups = ["${module.vpc.default_security_group_id}"] | ||
| ec2_profile = "${module.ec2-profile.instance_profile_id}" | ||
| } | ||
|
|
||
| #----- ECS Services-------- | ||
|
|
||
| module "hello-world" { | ||
| source = "service-hello-world" | ||
| cluser_id = "${module.ecs.ecs_cluster_id}" | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| resource "aws_cloudwatch_log_group" "hello-world" { | ||
| name = "hello-world" | ||
| retention_in_days = 1 | ||
| } | ||
|
|
||
| resource "aws_ecs_task_definition" "hello-world" { | ||
| family = "hello-world" | ||
|
|
||
| container_definitions = <<EOF | ||
| [ | ||
| { | ||
| "name": "hello-world", | ||
| "image": "hello-world", | ||
| "cpu": 0, | ||
| "memory": 128, | ||
| "logConfiguration": { | ||
| "logDriver": "awslogs", | ||
| "options": { | ||
| "awslogs-region": "eu-west-1", | ||
| "awslogs-group": "hello-world", | ||
| "awslogs-stream-prefix": "my-ecs" | ||
| } | ||
| } | ||
| } | ||
| ] | ||
| EOF | ||
| } | ||
|
|
||
| resource "aws_ecs_service" "hello-world" { | ||
|
||
| name = "hello-world" | ||
| cluster = "${var.cluser_id}" | ||
| task_definition = "${aws_ecs_task_definition.hello-world.arn}" | ||
|
|
||
| desired_count = 1 | ||
|
|
||
| deployment_maximum_percent = 100 | ||
| deployment_minimum_healthy_percent = 0 | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| variable "cluser_id" { | ||
| description = "The ECS cluster ID" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| terraform { | ||
| required_version = ">= 0.11.7" | ||
| } | ||
|
|
||
| provider "template" { | ||
| version = ">= 1.0.0" | ||
| } | ||
|
|
||
| resource "aws_ecs_cluster" "ecs" { | ||
|
||
| count = "${var.create_ecs ? 1 : 0}" | ||
|
|
||
| name = "${var.name}" | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # ECS instance policy | ||
|
|
||
| For an EC2 instance to connect it self to ECS it needs rights to do so. | ||
|
||
|
|
||
| * [Why do we need ECS instance policies?](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html) | ||
| * [ECS roles explained](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_managed_policies.html) | ||
| * [More ECS policy examples explained](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/IAMPolicyExamples.html) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| resource "aws_iam_role" "this" { | ||
| name = "${var.name}_ecs_instance_role" | ||
| path = "/ecs/" | ||
|
|
||
| assume_role_policy = <<EOF | ||
| { | ||
| "Version": "2008-10-17", | ||
| "Statement": [ | ||
| { | ||
| "Action": "sts:AssumeRole", | ||
| "Principal": { | ||
| "Service": ["ec2.amazonaws.com"] | ||
| }, | ||
| "Effect": "Allow" | ||
| } | ||
| ] | ||
| } | ||
| EOF | ||
| } | ||
|
|
||
| resource "aws_iam_instance_profile" "this" { | ||
| name = "${var.name}_ecs_instance_profile" | ||
| role = "${aws_iam_role.this.name}" | ||
| } | ||
|
|
||
| resource "aws_iam_role_policy_attachment" "ecs_ec2_role" { | ||
| role = "${aws_iam_role.this.id}" | ||
| policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role" | ||
| } | ||
|
|
||
| resource "aws_iam_role_policy_attachment" "ecs_ec2_cloudwatch_role" { | ||
| role = "${aws_iam_role.this.id}" | ||
| policy_arn = "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| output "instance_profile_id" { | ||
|
||
| value = "${aws_iam_instance_profile.this.id}" | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| variable "name" { | ||
| description = "Name to be used on all the resources as identifier" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| output "ecs_cluster_id" { | ||
| value = "${aws_ecs_cluster.ecs.0.id}" | ||
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| variable "create_ecs" { | ||
| description = "Controls if ECS should be created" | ||
| default = true | ||
| } | ||
|
|
||
| variable "name" { | ||
| description = "Name to be used on all the resources as identifier, also the name of the ECS cluster" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a section
Examplesto describe each kind of example.