参考文献
- [Terraform][Backends][v0.9]tfstateファイルの管理方法
- グループ会社のインフラをECS/Fargateに移行して振り返る
- [AWS][Terraform][Fargate]ECSでコンテナをALB配下に置く
- circleci/aws-ecs@1.4.0
- AWS ECR/ECS へのデプロイ
ツリー図
.
├── acm.tf
├── alb.tf
├── backend.tf
├── ecs.tf
├── files
│ └── task-definitions
│ └── container.json
├── rds.tf
├── security_group.tf
├── terraform.tfvars
├── variables.tf
├── vpc.tf
├── vpc_gateway.tf
├── vpc_routetable.tf
└── vpc_subnet.tf
Terraform / AWS CLIコマンド
◆ AWS CLIコマンド
/// ECS
$ aws ecs list-task-definitions --region ap-northeast-1
$ aws ecs list-clusters
$ aws ecs register-task-definition --family sample-service --cli-input-json file://container.json
/// RDS
$ mysql -h sample-rds.XXXXXX.XXXXXX.rds.amazonaws.com -P 3306 -u XXXX -p
◆ EC2インストール
$ sudo yum install git
$ yum list installed | grep mariadb
$ sudo yum remove mariadb-libs
$ sudo yum-config-manager --disable mysql57-community
$ sudo yum-config-manager --enable mysql80-community
$ sudo yum install -y mysql-community-client
$ mysql --version
各tfファイル
◆ ecs.tf
ecs.tf
# ====================
# Cluster
# ====================
resource "aws_ecs_cluster" "sample-cluster" {
name = "sample-cluster"
}
# ====================
# CloudWatch logs
# ====================
resource "aws_cloudwatch_log_group" "sample-log-group" {
name = "sample-log-group"
tags = {}
}
# ====================
# task_definition
# ====================
resource "aws_ecs_task_definition" "sample-task-definition" {
//family:複数のタスク定義をまとめる際に使用
family = "sample-service"
requires_compatibilities = ["FARGATE"]
network_mode = "awsvpc"
task_role_arn = "arn:aws:iam::${var.aws_account_id}:role/ecsTaskExecutionRole"
execution_role_arn = "arn:aws:iam::${var.aws_account_id}:role/ecsTaskExecutionRole"
cpu = 1024
memory = 2048
container_definitions = file("files/task-definitions/container.json")
}
# ====================
# Service
# ====================
resource "aws_ecs_service" "sample-service" {
cluster = aws_ecs_cluster.sample-cluster.id
launch_type = "FARGATE"
deployment_minimum_healthy_percent = 100
deployment_maximum_percent = 200
name = "sample-service"
task_definition = aws_ecs_task_definition.sample-task-definition.arn
//desired_count:タスク数
desired_count = 1
/// autoscalingで動的に変化する値を無視する ///
lifecycle {
ignore_changes = [desired_count, task_definition]
}
load_balancer {
target_group_arn = aws_alb_target_group.sample-target-group.arn
container_name = "sample-container"
container_port = 80
}
network_configuration {
subnets = [aws_subnet.sample-subnet-1.id, aws_subnet.sample-subnet-2.id]
security_groups = [aws_security_group.sample-security-group-app.id, aws_security_group.sample-security-group-rds.id]
assign_public_ip = "true"
}
}
◆ container.json
files/container.json
[
{
"image": "XXXXXX.dkr.ecr.XXXXXX.amazonaws.com/sample_dev:latest",
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "sample-log-group",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
},
"cpu": 512,
"memory": 1024,
"mountPoints": [],
"environment": [],
"networkMode": "awsvpc",
"name": "sample-container",
"essential": true,
"portMappings": [
{
"hostPort": 80,
"containerPort": 80,
"protocol": "tcp"
}
],
"command": [
"/usr/bin/supervisord"
]
}
]
◆ alb.tf
alb.tf
# ====================
# ALB
# ====================
resource "aws_alb" "sample-alb" {
name = "sample-alb"
security_groups = [aws_security_group.sample-security-group-alb.id]
subnets = [aws_subnet.sample-subnet-1.id, aws_subnet.sample-subnet-2.id]
internal = false
enable_deletion_protection = false
}
# ====================
# Target Group
# ====================
resource "aws_alb_target_group" "sample-target-group" {
name = "sample-target-group"
depends_on = [aws_alb.sample-alb]
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.sample-vpc.id
target_type = "ip"
health_check {
protocol = "HTTP"
path = "/ping"
port = 80
unhealthy_threshold = 5
timeout = 5
interval = 10
matcher = 200
}
}
# ====================
# ALB Listener HTTP
# ====================
resource "aws_alb_listener" "sample-alb-http" {
load_balancer_arn = aws_alb.sample-alb.arn
port = 80
protocol = "HTTP"
default_action {
target_group_arn = aws_alb_target_group.sample-target-group.arn
type = "forward"
}
}
# ====================
# ALB Listener HTTPS
# ====================
resource "aws_alb_listener" "sample-alb-https" {
load_balancer_arn = aws_alb.sample-alb.arn
port = "443"
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2015-05"
certificate_arn = aws_acm_certificate.sample-acm.arn
default_action {
target_group_arn = aws_alb_target_group.sample-target-group.arn
type = "forward"
}
}
# ====================
# listener_rule
# ====================
resource "aws_alb_listener_rule" "sample-listener-rule" {
depends_on = [aws_alb_target_group.sample-target-group]
listener_arn = aws_alb_listener.sample-alb-http.arn
priority = 100
action {
type = "forward"
target_group_arn = aws_alb_target_group.sample-target-group.arn
}
condition {
path_pattern {
values = ["*"]
}
}
}
◆ acm.tf
acm.tf
# ====================
# ACM
# ====================
resource "aws_acm_certificate" "sample-acm" {
domain_name = "sample.com"
subject_alternative_names = ["*.sample.com"]
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
}
◆ rds.tf
rds.tf
# ====================
# db_subnet_group
# ====================
resource "aws_db_subnet_group" "sample-rds-subnet-group" {
name = "sample-rds-subnet-group"
description = "sample-rds-subnet-group"
subnet_ids = [aws_subnet.sample-subnet-1.id, aws_subnet.sample-subnet-2.id]
}
# ====================
# db_instance
# ====================
resource "aws_db_instance" "sample-rds" {
identifier = "sample-rds"
allocated_storage = 20
storage_type = "gp2"
engine = "mysql"
engine_version = "5.7"
instance_class = "db.t2.micro"
username = "test"
password = "XXXXXX"
parameter_group_name = "default.mysql5.7"
port = "3306"
vpc_security_group_ids = [aws_security_group.sample-security-group-rds.id]
db_subnet_group_name = "${aws_db_subnet_group.sample-rds-subnet-group.name}"
skip_final_snapshot = true
}
◆ security_group.tf
security_group.tf
# ====================
# Security Group (app)
# ====================
resource "aws_security_group" "sample-security-group-app" {
vpc_id = aws_vpc.sample-vpc.id
name = "sample-security-group-app"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["X.X.X.X/16"]
security_groups = [aws_security_group.sample-security-group-alb.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "sample-security-group-app"
}
}
# ====================
# Security Group(ALB)
# ====================
resource "aws_security_group" "sample-security-group-alb" {
name = "sample-security-group-alb"
description = "sample-security-group-alb"
vpc_id = aws_vpc.sample-vpc.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
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 = "sample-security-group-alb"
}
}
# ====================
# Security Group (RDS)
# ====================
resource "aws_security_group" "sample-security-group-rds" {
name = "sample-security-group-rds"
description = "sample-security-group-rds"
vpc_id = aws_vpc.sample-vpc.id
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
security_groups = [aws_security_group.sample-security-group-app.id]
}
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["X.X.X.X/16"]
description = "sample-security-group-rds"
}
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["X.X.X.X/28"]
description = "sample-security-group-rds"
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "sample-security-group-rds"
}
}
◆ vpc.tf
vpc.tf
# ====================
# VPC
# ====================
resource "aws_vpc" "sample-vpc" {
cidr_block = "X.X.X.X/16"
tags = {
Name = "sample-vpc"
}
}
◆ vpc_subnet.tf
vpc_subnet.tf
# ====================
# Subnet
# ====================
resource "aws_subnet" "sample-subnet-1" {
cidr_block = "X.X.X.X/24"
availability_zone = "ap-northeast-1a"
vpc_id = aws_vpc.sample-vpc.id
tags = {
Name = "sample-subnet-1"
}
}
resource "aws_subnet" "sample-subnet-2" {
cidr_block = "X.X.X.X/24"
availability_zone = "ap-northeast-1c"
vpc_id = aws_vpc.sample-vpc.id
tags = {
Name = "sample-subnet-2"
}
}
◆ vpc_routetable.tf
vpc_routetable.tf
# ====================
# Subnet
# ====================
resource "aws_subnet" "sample-subnet-1" {
cidr_block = "X.X.X.X/24"
availability_zone = "ap-northeast-1a"
vpc_id = aws_vpc.sample-vpc.id
tags = {
Name = "sample-subnet-1"
}
}
resource "aws_subnet" "sample-subnet-2" {
cidr_block = "X.X.X.X/24"
availability_zone = "ap-northeast-1c"
vpc_id = aws_vpc.sample-vpc.id
tags = {
Name = "sample-subnet-2"
}
}
◆ vpc_gateway.tf
vpc_gateway.tf
# ====================
# Internet Gateway
# ====================
resource "aws_internet_gateway" "sample-gateway" {
vpc_id = aws_vpc.sample-vpc.id
tags = {
Name = "sample-gateway"
}
}
◆ variables.tf
variables.tf
/// tfファイルで使用する変数定義 ///
/// 変数の中身はterraform.tfvarsに記載 ///
variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "region" {}
variable "aws_account_id" {}
◆ backend.tf
backend.tf
provider "aws" {
access_key = "${var.aws_access_key}"
secret_key = "${var.aws_secret_key}"
region = "${var.region}"
profile = "s3-profile"
}
terraform {
backend "s3" {
bucket = "sample-s3-file"
key = "terraform.tfstate"
region = "ap-northeast-1"
shared_credentials_file = "~/.aws/credentials"
profile = "s3-profile"
}
}