Skip to content

Commit

Permalink
converting cloudformation template to terraform (#1260)
Browse files Browse the repository at this point in the history
* creating TF code from the existing CFn template
* refactoring
* fixed sg id + lint
* ignore tf state file
* first steps to remove CF stack
* changed deploy command to use TF
* installing tf cli
* moved secret env vars into AWS SM
* created custom role for ecs exec (able to read newly created secret)
* reusing redis hostname
* imported acm cert
* using snake case on app vars
  • Loading branch information
fabiocicerchia authored Jan 6, 2025
1 parent b9846fb commit 72c71f4
Show file tree
Hide file tree
Showing 18 changed files with 876 additions and 39 deletions.
10 changes: 8 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,16 @@ jobs:
aws --profile $AWS_PROFILE configure set aws_access_key_id $AWS_ACCESS_KEY_ID
aws --profile $AWS_PROFILE configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
- name: Configure Terraform
uses: hashicorp/setup-terraform@v3

- name: Prepare settings
env:
PARAM_JSON: ${{ secrets.PARAM_JSON }}
run: echo "$PARAM_JSON" > sys/cloudformation/parameters.secrets.prod.json
PARAM_TFVARS: ${{ secrets.PARAM_TFVARS }}
run: echo "$PARAM_TFVARS" > sys/terraform/terraform.tfvars

- name: Terraform init
run: terraform init

- name: Deploy
env:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,7 @@ sys/nginx/certs/ca-key.pem
sys/nginx/certs/server.csr
sys/nginx/certs/server.key
sys/nginx/certs/server.pem
sys/terraform/.terraform
sys/terraform/terraform.tfvars
sys/terraform/terraform.tfstate
###< custom ###
20 changes: 3 additions & 17 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -80,23 +80,9 @@ PREVIOUS_TAG=$(shell git ls-remote --tags 2>&1 | awk '{print $$2}' | sort -r | h
ECR_REGISTRY = $(AWS_ACCOUNT_ID).dkr.ecr.$(AWS_REGION).amazonaws.com

deploy_prod: build_prod_images push_prod_images ## deploy to prod
cat sys/cloudformation/parameters.prod.json \
| sed -e 's/{"ParameterKey": "EcrImageTagNginx", "ParameterValue": ".*"}/{"ParameterKey": "EcrImageTagNginx", "ParameterValue": "'$(VER)'"}/' \
-e 's/{"ParameterKey": "EcrImageTagPhp", "ParameterValue": ".*"}/{"ParameterKey": "EcrImageTagPhp", "ParameterValue": "'$(VER)'"}/' \
| tee sys/cloudformation/parameters.prod.json.new; \
mv sys/cloudformation/parameters.prod.json sys/cloudformation/parameters.prod.json.bak; \
mv sys/cloudformation/parameters.prod.json.new sys/cloudformation/parameters.prod.json; \
cat sys/cloudformation/parameters.secrets.prod.json \
| sed -e 's/{"ParameterKey": "EcrImageTagNginx", "ParameterValue": ".*"}/{"ParameterKey": "EcrImageTagNginx", "ParameterValue": "'$(VER)'"}/' \
-e 's/{"ParameterKey": "EcrImageTagPhp", "ParameterValue": ".*"}/{"ParameterKey": "EcrImageTagPhp", "ParameterValue": "'$(VER)'"}/' \
| tee sys/cloudformation/parameters.secrets.prod.json.new; \
mv sys/cloudformation/parameters.secrets.prod.json sys/cloudformation/parameters.secrets.prod.json.bak; \
mv sys/cloudformation/parameters.secrets.prod.json.new sys/cloudformation/parameters.secrets.prod.json; \
aws --profile=$(AWS_PROFILE) cloudformation create-change-set --capabilities CAPABILITY_NAMED_IAM \
--stack=poser-ecs \
--change-set-name=poser-ecs-$(VER) \
--template-body=file://$$PWD/sys/cloudformation/stack.yaml \
--parameters=file://sys/cloudformation/parameters.secrets.prod.json
# TODO: convert to terraform apply
# TODO: modify IAM policy to allow only the creation of ECS tasks via pipelines
terraform plan -var="ecr_image_tag_nginx=$(VER)" -var="ecr_image_tag_php=$(VER)"

build_%: export BADGE_POSER_REGISTRY = $(ECR_REGISTRY)/badge-poser
build_%: export DOCKER_BUILDKIT = 1
Expand Down
19 changes: 0 additions & 19 deletions sys/cloudformation/parameters.prod.json

This file was deleted.

Binary file removed sys/cloudformation/stack.png
Binary file not shown.
18 changes: 17 additions & 1 deletion sys/cloudformation/stack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ Resources:

# SECURITY GROUP
sgelb:
DeletionPolicy: Retain
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub '${ServiceName}-elb'
Expand All @@ -210,6 +211,7 @@ Resources:
- Key: env
Value: !Ref ServiceName
sgecs:
DeletionPolicy: Retain
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub '${ServiceName}-ecs'
Expand All @@ -233,6 +235,7 @@ Resources:
- Key: env
Value: !Ref ServiceName
sgredis:
DeletionPolicy: Retain
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub '${ServiceName}-redis'
Expand All @@ -254,13 +257,15 @@ Resources:

# CLOUDWATCH LOGS
cloudwatchloggroup:
DeletionPolicy: Retain
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub '${ServiceName}-logs'
RetentionInDays: 30

# ELB
elb:
DeletionPolicy: Retain
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub '${ServiceName}-elb'
Expand All @@ -273,6 +278,7 @@ Resources:

# ELB LISTENER
elblistener80:
DeletionPolicy: Retain
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
Expand All @@ -286,6 +292,7 @@ Resources:
Protocol: HTTP

elblistener443:
DeletionPolicy: Retain
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
Expand All @@ -303,6 +310,7 @@ Resources:

# ECS CLUSTER
ecscluster:
DeletionPolicy: Retain
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Sub '${ServiceName}-cluster-${Environment}'
Expand All @@ -318,6 +326,7 @@ Resources:

# ECS SERVICE
ecsservice:
DeletionPolicy: Retain
Type: AWS::ECS::Service
Properties:
Cluster: !Ref ecscluster
Expand All @@ -342,8 +351,8 @@ Resources:

# ECS TASK DEFINITION
ecstask:
Type: AWS::ECS::TaskDefinition
DeletionPolicy: Retain
Type: AWS::ECS::TaskDefinition
UpdateReplacePolicy: Retain
Properties:
ExecutionRoleArn: !Ref ExecRoleArn
Expand Down Expand Up @@ -430,6 +439,7 @@ Resources:

# AUTO SCALING
asscalabletarget:
DeletionPolicy: Retain
Type: AWS::ApplicationAutoScaling::ScalableTarget
DependsOn:
- ecsservice
Expand All @@ -443,6 +453,7 @@ Resources:

# ELB TARGET GROUP
elbtargetgroup:
DeletionPolicy: Retain
Type: AWS::ElasticLoadBalancingV2::TargetGroup
DependsOn:
- elb
Expand All @@ -468,6 +479,7 @@ Resources:

# ELB LISTENER RULE
elblistenerrule80:
DeletionPolicy: Retain
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
Expand All @@ -485,6 +497,7 @@ Resources:
ListenerArn: !Ref elblistener80
Priority: 1
elblistenerrule443:
DeletionPolicy: Retain
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
Expand All @@ -501,6 +514,7 @@ Resources:

# SCHEDULED TASK
eventrulecontributorsupdate:
DeletionPolicy: Retain
Type: AWS::Events::Rule
Properties:
Name: 'app-contributors-update'
Expand All @@ -522,6 +536,7 @@ Resources:

# IAM USER
iamusergithubactions:
DeletionPolicy: Retain
Type: AWS::IAM::User
Properties:
Policies:
Expand Down Expand Up @@ -576,6 +591,7 @@ Resources:

# IAM ACCESS-KEY
iamkey:
DeletionPolicy: Retain
Type: AWS::IAM::AccessKey
Properties:
UserName: !Ref iamusergithubactions
Expand Down
25 changes: 25 additions & 0 deletions sys/terraform/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions sys/terraform/cloudwatch.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# TODO: import dashboard

resource "aws_cloudwatch_event_rule" "eventrulecontributorsupdate" {
name = "app-contributors-update"
schedule_expression = "rate(24 hours)"
state = "DISABLED"
// CF Property(Targets) = [
// {
// Id = "phpfpm"
// Arn = aws_ecs_cluster.ecscluster.arn
// RoleArn = aws_iam_role.ecs_task_role.arn
// Input = "{"containerOverrides":[{"name":"phpfpm","command":["./bin/console","app:contributors:update"]}]}"
// EcsParameters = {
// TaskDefinitionArn = aws_ecs_task_definition.ecstask.arn
// LaunchType = "FARGATE"
// NetworkConfiguration = {
// AwsVpcConfiguration = {
// SecurityGroups = [
// aws_security_group.sgecs.arn
// ]
// Subnets = var.subnets
// }
// }
// }
// }
// ]
}
3 changes: 3 additions & 0 deletions sys/terraform/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
data "aws_region" "current" {}

data "aws_caller_identity" "current" {}
106 changes: 106 additions & 0 deletions sys/terraform/ecs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
resource "aws_security_group" "sgecs" {
description = "${var.service_name}-ecs"
name = "${var.service_name}-ecs"
egress {
cidr_blocks = ["0.0.0.0/0"]
protocol = "-1"
from_port = 0
to_port = 0
}
vpc_id = var.vpc_id
}

resource "aws_security_group_rule" "sgecs_ingress_http" {
type = "ingress"
security_group_id = aws_security_group.sgecs.id
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
protocol = "tcp"
to_port = 80
}
resource "aws_security_group_rule" "sgecs_ingress_https" {
type = "ingress"
security_group_id = aws_security_group.sgecs.id
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
protocol = "tcp"
to_port = 443
}

resource "aws_cloudwatch_log_group" "cloudwatchloggroup" {
name = "${var.service_name}-logs"
retention_in_days = 14
}

resource "aws_ecs_cluster" "ecscluster" {
name = "${var.service_name}-cluster-${var.environment}"
// CF Property(CapacityProviders) = [
// "FARGATE",
// "FARGATE_SPOT"
// ]
setting {
name = "containerInsights"
value = "disabled"
}
}

resource "aws_ecs_service" "ecsservice" {
cluster = aws_ecs_cluster.ecscluster.arn
desired_count = 1
health_check_grace_period_seconds = 15

capacity_provider_strategy {
base = 0
capacity_provider = "FARGATE_SPOT"
weight = 2
}
capacity_provider_strategy {
base = 1
capacity_provider = "FARGATE"
weight = 1
}

load_balancer {
container_name = "nginx"
container_port = 80
target_group_arn = aws_lb_target_group.elbtargetgroup.id
}
name = var.service_name
task_definition = "${var.service_name}:${aws_ecs_task_definition.ecstask.revision}"
network_configuration {
assign_public_ip = true
security_groups = [aws_security_group.sgecs.id]
subnets = var.subnets
}
}

resource "aws_ecs_task_definition" "ecstask" {
execution_role_arn = aws_iam_role.ecs_task_role.arn
container_definitions = templatefile("ecs/task-definition.json", {
account_id = data.aws_caller_identity.current.account_id
aws_region = data.aws_region.current.name
service_name = var.service_name
ecr_image_tag_nginx = var.ecr_image_tag_nginx
ecr_image_tag_php = var.ecr_image_tag_php
cloudwatch_log_group = aws_cloudwatch_log_group.cloudwatchloggroup.name
env_app_debug = var.env_app_debug
env_app_env = var.env_app_env
env_app_xdebug = var.env_app_xdebug
env_app_xdebug_host = var.env_app_xdebug_host
env_bitbucket_auth_method = var.env_bitbucket_auth_method
env_github_auth_method = var.env_github_auth_method
env_phpfpm_host = var.env_phpfpm_host
env_redis_host = aws_elasticache_cluster.rediscluster.cache_nodes[0].address
env_resolver_ip = var.env_resolver_ip
env_sentry_dsn = var.env_sentry_dsn
env_trusted_proxies = var.env_trusted_proxies
})
memory = "2048"
family = var.service_name
requires_compatibilities = [
"FARGATE"
]
network_mode = "awsvpc"
cpu = "1024"
skip_destroy = true
}
Loading

0 comments on commit 72c71f4

Please sign in to comment.