Created
December 12, 2018 16:04
-
-
Save 20k-ultra/579fb434d55a8a447b6beebca9acc335 to your computer and use it in GitHub Desktop.
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
/*==== | |
Cloudwatch Log Group | |
======*/ | |
resource "aws_cloudwatch_log_group" "qriket" { | |
name = "qriket" | |
tags { | |
Environment = "${var.environment}" | |
Application = "Qriket API" | |
} | |
} | |
/*==== | |
ECR repository to store our Docker images | |
======*/ | |
resource "aws_ecr_repository" "qriket_app" { | |
name = "${var.repository_name}" | |
} | |
/*==== | |
ECS cluster | |
======*/ | |
resource "aws_ecs_cluster" "cluster" { | |
name = "${var.environment}-ecs-cluster" | |
} | |
/*==== | |
ECS task definitions | |
======*/ | |
/* the task definition for the web service */ | |
data "template_file" "web_task" { | |
template = "${file("${path.module}/tasks/web_task_definition.json")}" | |
vars { | |
image = "${aws_ecr_repository.qriket_app.repository_url}" | |
secret_key_base = "${var.secret_key_base}" | |
database_host = "${var.database_endpoint}" | |
database_user = "${var.database_username}" | |
database_pass = "${var.database_password}" | |
database_name = "${var.database_name}" | |
database_port = "5432" | |
redis_endpoint = "${var.redis_endpoint}" | |
redis_port = "${var.redis_port}" | |
log_group = "${aws_cloudwatch_log_group.qriket.name}" | |
} | |
} | |
resource "aws_ecs_task_definition" "web" { | |
family = "${var.environment}_web" | |
container_definitions = "${data.template_file.web_task.rendered}" | |
requires_compatibilities = ["FARGATE"] | |
network_mode = "awsvpc" | |
cpu = "256" | |
memory = "512" | |
execution_role_arn = "${aws_iam_role.ecs_execution_role.arn}" | |
task_role_arn = "${aws_iam_role.ecs_execution_role.arn}" | |
} | |
/*==== | |
App Load Balancer | |
======*/ | |
resource "random_id" "target_group_sufix" { | |
byte_length = 2 | |
} | |
/* security group for ALB */ | |
resource "aws_security_group" "web_inbound_sg" { | |
name_prefix = "${var.environment}-web-inbound-sg" | |
description = "Allow HTTP from Anywhere into ALB" | |
vpc_id = "${var.vpc_id}" | |
ingress { | |
from_port = 80 | |
to_port = 80 | |
protocol = "tcp" | |
cidr_blocks = ["0.0.0.0/0"] | |
} | |
ingress { | |
from_port = 8 | |
to_port = 0 | |
protocol = "icmp" | |
cidr_blocks = ["0.0.0.0/0"] | |
} | |
egress { | |
from_port = 0 | |
to_port = 0 | |
protocol = "-1" | |
cidr_blocks = ["0.0.0.0/0"] | |
} | |
tags { | |
Name = "${var.environment}-web-inbound-sg" | |
} | |
lifecycle { | |
create_before_destroy = true | |
} | |
} | |
resource "aws_alb" "alb_qriket" { | |
name = "${var.environment}-alb-qriket" | |
subnets = ["${var.public_subnet_ids}"] | |
security_groups = ["${var.security_groups_ids}", "${aws_security_group.web_inbound_sg.id}"] | |
tags { | |
Name = "${var.environment}-alb-qriket" | |
Environment = "${var.environment}" | |
} | |
} | |
resource "aws_alb_target_group" "alb_target_group" { | |
name = "${var.environment}-alb-target-group-${random_id.target_group_sufix.hex}" | |
port = 80 | |
protocol = "HTTP" | |
vpc_id = "${var.vpc_id}" | |
target_type = "ip" | |
health_check { | |
path = "/" | |
port = "80" | |
protocol = "HTTP" | |
healthy_threshold = 2 | |
unhealthy_threshold = 2 | |
interval = 5 | |
timeout = 4 | |
matcher = "200-308" | |
} | |
} | |
resource "aws_alb_listener" "qriket" { | |
load_balancer_arn = "${aws_alb.alb_qriket.arn}" | |
port = "443" | |
protocol = "HTTPS" | |
ssl_policy = "${var.ssl_policy}" | |
certificate_arn = "${var.certificate_arn}" | |
depends_on = ["aws_alb_target_group.alb_target_group"] | |
default_action { | |
target_group_arn = "${aws_alb_target_group.alb_target_group.arn}" | |
type = "forward" | |
} | |
lifecycle { | |
create_before_destroy = true | |
} | |
} | |
/* | |
* IAM service role | |
*/ | |
data "aws_iam_policy_document" "ecs_service_role" { | |
statement { | |
effect = "Allow" | |
actions = ["sts:AssumeRole"] | |
principals { | |
type = "Service" | |
identifiers = ["ecs.amazonaws.com"] | |
} | |
} | |
} | |
resource "aws_iam_role" "ecs_role" { | |
name = "ecs_role" | |
assume_role_policy = "${data.aws_iam_policy_document.ecs_service_role.json}" | |
} | |
data "aws_iam_policy_document" "ecs_service_policy" { | |
statement { | |
effect = "Allow" | |
resources = ["*"] | |
actions = [ | |
"elasticloadbalancing:Describe*", | |
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer", | |
"elasticloadbalancing:RegisterInstancesWithLoadBalancer", | |
"ec2:Describe*", | |
"ec2:AuthorizeSecurityGroupIngress" | |
] | |
} | |
} | |
/* ecs service scheduler role */ | |
resource "aws_iam_role_policy" "ecs_service_role_policy" { | |
name = "ecs_service_role_policy" | |
policy = "${data.aws_iam_policy_document.ecs_service_policy.json}" | |
role = "${aws_iam_role.ecs_role.id}" | |
} | |
/* role that the Amazon ECS container agent and the Docker daemon can assume */ | |
resource "aws_iam_role" "ecs_execution_role" { | |
name = "ecs_task_execution_role" | |
assume_role_policy = "${file("${path.module}/policies/ecs-task-execution-role.json")}" | |
} | |
resource "aws_iam_role_policy" "ecs_execution_role_policy" { | |
name = "ecs_execution_role_policy" | |
policy = "${file("${path.module}/policies/ecs-execution-role-policy.json")}" | |
role = "${aws_iam_role.ecs_execution_role.id}" | |
} | |
/*==== | |
ECS service | |
======*/ | |
/* Security Group for ECS */ | |
resource "aws_security_group" "ecs_service" { | |
vpc_id = "${var.vpc_id}" | |
name_prefix = "${var.environment}-ecs-service-sg" | |
description = "Allow egress from container" | |
egress { | |
from_port = 0 | |
to_port = 0 | |
protocol = "-1" | |
cidr_blocks = ["0.0.0.0/0"] | |
} | |
ingress { | |
from_port = 8 | |
to_port = 0 | |
protocol = "icmp" | |
cidr_blocks = ["0.0.0.0/0"] | |
} | |
tags { | |
Name = "${var.environment}-ecs-service-sg" | |
Environment = "${var.environment}" | |
} | |
lifecycle { | |
create_before_destroy = true | |
} | |
} | |
/* Simply specify the family to find the latest ACTIVE revision in that family */ | |
data "aws_ecs_task_definition" "web" { | |
depends_on = ["aws_ecs_task_definition.web"] | |
task_definition = "${aws_ecs_task_definition.web.family}" | |
} | |
resource "aws_ecs_service" "web" { | |
name = "${var.environment}-web" | |
task_definition = "${aws_ecs_task_definition.web.family}:${max("${aws_ecs_task_definition.web.revision}", "${data.aws_ecs_task_definition.web.revision}")}" | |
desired_count = 2 | |
launch_type = "FARGATE" | |
cluster = "${aws_ecs_cluster.cluster.id}" | |
depends_on = ["aws_iam_role_policy.ecs_service_role_policy"] | |
network_configuration { | |
security_groups = ["${var.security_groups_ids}", "${aws_security_group.ecs_service.id}"] | |
subnets = ["${var.subnets_ids}"] | |
} | |
load_balancer { | |
target_group_arn = "${aws_alb_target_group.alb_target_group.arn}" | |
container_name = "web" | |
container_port = "80" | |
} | |
depends_on = ["aws_alb_target_group.alb_target_group"] | |
} | |
/*==== | |
Auto Scaling for ECS | |
======*/ | |
resource "aws_iam_role" "ecs_autoscale_role" { | |
name = "${var.environment}_ecs_autoscale_role" | |
assume_role_policy = "${file("${path.module}/policies/ecs-autoscale-role.json")}" | |
} | |
resource "aws_iam_role_policy" "ecs_autoscale_role_policy" { | |
name = "ecs_autoscale_role_policy" | |
policy = "${file("${path.module}/policies/ecs-autoscale-role-policy.json")}" | |
role = "${aws_iam_role.ecs_autoscale_role.id}" | |
} | |
resource "aws_appautoscaling_target" "target" { | |
service_namespace = "ecs" | |
resource_id = "service/${aws_ecs_cluster.cluster.name}/${aws_ecs_service.web.name}" | |
scalable_dimension = "ecs:service:DesiredCount" | |
role_arn = "${aws_iam_role.ecs_autoscale_role.arn}" | |
min_capacity = "${var.min_capacity}" | |
max_capacity = "${var.max_capacity}" | |
} | |
resource "aws_appautoscaling_policy" "up" { | |
name = "${var.environment}_scale_up" | |
service_namespace = "ecs" | |
resource_id = "service/${aws_ecs_cluster.cluster.name}/${aws_ecs_service.web.name}" | |
scalable_dimension = "ecs:service:DesiredCount" | |
step_scaling_policy_configuration { | |
adjustment_type = "ChangeInCapacity" | |
cooldown = 60 | |
metric_aggregation_type = "Maximum" | |
step_adjustment { | |
metric_interval_lower_bound = 0 | |
scaling_adjustment = 1 | |
} | |
} | |
depends_on = ["aws_appautoscaling_target.target"] | |
} | |
resource "aws_appautoscaling_policy" "down" { | |
name = "${var.environment}_scale_down" | |
service_namespace = "ecs" | |
resource_id = "service/${aws_ecs_cluster.cluster.name}/${aws_ecs_service.web.name}" | |
scalable_dimension = "ecs:service:DesiredCount" | |
step_scaling_policy_configuration { | |
adjustment_type = "ChangeInCapacity" | |
cooldown = 60 | |
metric_aggregation_type = "Maximum" | |
step_adjustment { | |
metric_interval_lower_bound = 0 | |
scaling_adjustment = -1 | |
} | |
} | |
depends_on = ["aws_appautoscaling_target.target"] | |
} | |
/* metric used for auto scale */ | |
resource "aws_cloudwatch_metric_alarm" "service_cpu_high" { | |
alarm_name = "${var.environment}_qriket_web_cpu_utilization_high" | |
comparison_operator = "GreaterThanOrEqualToThreshold" | |
evaluation_periods = "2" | |
metric_name = "CPUUtilization" | |
namespace = "AWS/ECS" | |
period = "60" | |
statistic = "Maximum" | |
threshold = "85" | |
dimensions { | |
ClusterName = "${aws_ecs_cluster.cluster.name}" | |
ServiceName = "${aws_ecs_service.web.name}" | |
} | |
alarm_actions = ["${aws_appautoscaling_policy.up.arn}"] | |
ok_actions = ["${aws_appautoscaling_policy.down.arn}"] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment