#はじめに
本記事では、Terraform で ECS の Fargate の環境とBlue/Green デプロイのパイプライン
(CodeCommit + CodeBuild + CodeDeploy +CodePipeline)をお試しで構築する手順を記載しています。
#Terraform で構築するAWSリソースのBlackBeltの資料
VPC
ALB
ECS
CodeCommit
CodeBuild
CodeDeploy
CodePipeline
CloudWatchEvents
IAM
#Terraform のコードと構成
$ tree aws-tf-fargate-blue-green-deploy
aws-tf-fargate-blue-green-deploy
├── modules
│ ├── ecs
│ │ ├── alb.tf
│ │ ├── alb_listener.tf
│ │ ├── alb_security_group.tf
│ │ ├── alb_target_group.tf
│ │ ├── buildspec.yml
│ │ ├── cloudwatch_event.tf
│ │ ├── codebuild.tf
│ │ ├── codecommit.tf
│ │ ├── codedeploy.tf
│ │ ├── codepipeline.tf
│ │ ├── ecr_docker_push.tf
│ │ ├── ecr_repository.tf
│ │ ├── ecs_cluster.tf
│ │ ├── ecs_security_group.tf
│ │ ├── ecs_service.tf
│ │ ├── ecs_task.tf
│ │ ├── ecs_task_role.tf
│ │ ├── ecs_taskdef.json
│ │ ├── files
│ │ │ ├── Dockerfile
│ │ │ └── index.html
│ │ ├── iam_policy
│ │ │ ├── cloudwatch_event_policy.json
│ │ │ ├── cloudwatch_event_trust_policy.json
│ │ │ ├── codebuild_policy.json
│ │ │ ├── codebuild_trust_policy.json
│ │ │ ├── codedeploy_trust_policy.json
│ │ │ ├── codepipeline_policy.json
│ │ │ ├── codepipeline_trust_policy.json
│ │ │ ├── ecs_task_policy.json
│ │ │ └── ecs_task_trust_policy.json
│ │ ├── iam_role.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ └── network
│ ├── internet_gateway.tf
│ ├── outputs.tf
│ ├── route_table.tf
│ ├── subnet.tf
│ ├── variables.tf
│ └── vpc.tf
├── main.tf
├── provider.tf
├── outputs.tf
├── variables.tf
├── sample-app
│ ├── Dockerfile
│ ├── appspec.yaml
│ ├── index.html
│ └── taskdef.json
└── terraform.tfvars-
#Terraform で構築する各リソース名
リソース | 名前(デフォルト) |
---|---|
VPC 名 | prefix-dev-vpc |
ALB 名 | prefix-dev-sample-app-alb |
ALB セキュリティグループ名 | prefix-dev-sample-app-alb-sg |
ECS クラスタ名 | prefix-dev-cluster |
ECR リポジトリ名 | prefix-sample-app |
タスク定義名 | prefix-dev-sample-app-task |
コンテナ名 | prefix-sample-app |
サービス名 | prefix-dev-sample-app-svc |
サービス セキュリティグループ名 | prefix-dev-sample-app-svc-sg |
CodePipeline 名 | prefix-dev-sample-app-cp |
CloudWatch Events名 | prefix-dev-sample-app-cp-event |
CodeCommit リポジトリ名 | prefix-sample-app |
CodeBuild プロジェクト名 | prefix-dev-sample-app-cb |
CodeDeploy アプリケーション名 | prefix-dev-sample-app |
CodeDeoloy デプロイグループ名 | dev |
#モジュールに渡すパラメータ
###################
# Network SAMPLE
###################
module "network" {
source = "./modules/network"
vpc = {
name = "${var.prefix}-${var.env}-vpc"
cidr = "10.0.0.0/16"
}
igw_name = "${var.prefix}-${var.env}-igw"
public_subnet_a = {
name = "${var.prefix}-${var.env}-public-a"
cidr = "10.0.1.0/24"
}
public_subnet_c = {
name = "${var.prefix}-${var.env}-public-c"
cidr = "10.0.2.0/24"
}
private_subnet_a = {
name = "${var.prefix}-${var.env}-private-a"
cidr = "10.0.10.0/24"
}
private_subnet_c = {
name = "${var.prefix}-${var.env}-private-c"
cidr = "10.0.20.0/24"
}
}
############################################
# ECS on Fargate Blue/Green Deploy SAMPLE
############################################
module "ecs" {
source = "./modules/ecs"
## AWS Account ID
aws_account_id = data.aws_caller_identity.current.account_id
## Region
aws_region = var.aws_region
## Network
vpc_id = module.network.vpc_id
subnet_ids = [
module.network.public_subnet_a_id,
module.network.public_subnet_c_id,
]
my_remote_ip = var.my_remote_ip
## ALB
alb_name = "${var.prefix}-${var.env}-sample-app-alb"
## ECS Cluster
cluster_name = "${var.prefix}-${var.env}-cluster"
## ECR
ecr_name = "${var.prefix}-sample-app"
## ECS Task
task_definition = {
name = "${var.prefix}-${var.env}-sample-app-task"
container_name = "${var.prefix}-sample-app"
cwlogs_name = "/aws/ecs/${var.prefix}-sample-app"
cwlogs_prefix = var.env
}
## ECS Service
service_name = "${var.prefix}-${var.env}-sample-app-svc"
desired_count = 1
## CodePipeline
codepipeline_name = "${var.prefix}-${var.env}-sample-app-cp"
## Stage > Source > CodeCommit
repository_name = "${var.prefix}-sample-app"
repository_description = "Sample App"
## Stage > Build > CodeBuild
build_project_name = "${var.prefix}-${var.env}-sample-app-cb"
## Stage > Deploy > CodeDeploy
codedeploy_app_name = "${var.prefix}-sample-app"
codedeploy_deployment_group_name = var.env
}
#事前準備
・Docker Desktop のインストール
・Terraform のインストール
・tfenv のインストール
・Terraform を実行するための IAM のアクセスキーとシークレットキー
・CodeCommit への HTTPS 接続用の Git 認証情報
・AWS CLI のインストール
#Terraform の動作確認環境
$ terraform -version
Terraform v1.0.4
on darwin_amd64
+ provider registry.terraform.io/hashicorp/aws v3.59.0
+ provider registry.terraform.io/hashicorp/null v3.1.0
+ provider registry.terraform.io/hashicorp/template v2.2.0
Your version of Terraform is out of date! The latest version
is 1.0.7. You can update by downloading from https://www.terraform.io/downloads.html
#Terrraform で環境を構築する手順
本手順は、Mac環境で実施することを想定しています。
Terraformのコードをダウンロードします。
$ git clone https://github.com/okubo-t/aws-tf-fargate-blue-green-deploy.git
Terraform のコードがあるディレクトへ移動します。
$ cd aws-tf-fargate-blue-green-deploy/
terraform.tfvars ファイルを作成します。
$ cp -p terraform.tfvars- terraform.tfvars
作成した terraform.tfvars 内の各パラメータを環境に応じて、任意で変更します。
# リージョン
aws_region = "ap-northeast-1"
# リソース名のプレフィックス
prefix = "prefix"
# リソースの環境
env = "dev"
# ALBに HTTPアクセスする時の送信元 IPアドレス
my_remote_ip = "0.0.0.0/0"
Docker Desktop が起動していることを確認します。
$ docker info
AWS CLIがインストールされていることを確認します。(AWS CLIの動作確認済み環境)
$ aws --version
aws-cli/1.19.92 Python/3.7.4 Darwin/18.7.0 botocore/1.20.92
AWS 認証情報を設定します。
$ export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXX # アクセスキー
$ export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXX # シークレットアクセスキー
$ export AWS_DEFAULT_REGION=ap-northeast-1 # デフォルトリージョン
下記コマンドで、Terraform の初期設定をします。
$ terraform init
下記コマンドで、環境のデプロイを実行します。
$ terraform apply
デプロイ後に出力される Outputsの内容をメモします。(下記の値は例です。)
Apply complete! Resources: 53 added, 0 changed, 0 destroyed.
Outputs:
codecommit_repository = "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/prefix-sample-app"
prod_url = "http://prefix-dev-sample-app-alb-1234567890.ap-northeast-1.elb.amazonaws.com"
test_url = "http://prefix-dev-sample-app-alb-1234567890.ap-northeast-1.elb.amazonaws.com:10080"
これで、Terraformによる環境の構築は完了です。
#Blue/Green デプロイパイプラインを実行する
ALBの本番用のリスナーに、curl コマンドを実行して、「Hello World v1」 と表示されることを確認します。(メモしたOutputsの prod_url の値を参照します。)
$ curl http://prefix-dev-sample-app-alb-1234567890.ap-northeast-1.elb.amazonaws.com
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Hello</title>
</head>
<body>
<h1>Hello World v1</h1>
</body>
</html>
下記コマンドを実行して、CodeCommit のリポジトリをクローンします。(メモしたOutputsの codecommit_repository の値を参照します。)
$ git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/prefix-sample-app
Terraform のコード内のディレクトリ(sample-app)の各ファイルをクローンしたリポジトリにコピーします。
$ cp -p ./sample-app/* [クローンしたリポジトリ名]
クローンしたリポジトリに移動します。
$ cd [クローンしたリポジトリ名]
$ ls
Dockerfile appspec.yaml index.html taskdef.json
$ cat index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Hello</title>
</head>
<body>
<h1>Hello World v2</h1>
</body>
</html>
「Hello World v2」と表示されるコードを、リポジトリにプッシュします。
$ git add .
$ git commit -m "Hello World v2"
$ git push
CodePipeline の管理コンソールから Blue/Green デプロイパイプラインが実行されていることを確認し、Deploy の詳細をクリックします。
CodeDeploy の管理コンソールからデプロイのステータスを確認します。
[デプロイのステータス]が、ステップ2 の状態で、ALBのテスト用のリスナー に対して、curl コマンドを実行して、「Hello World v2」 と表示されることを確認します。(メモしたOutputsの test_url の値を参照します。)
$ curl http://prefix-dev-sample-app-alb-1234567890.ap-northeast-1.elb.amazonaws.com:10080
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Hello</title>
</head>
<body>
<h1>Hello World v2</h1>
</body>
</html>
[トラフィックの再ルーティング]をクリックして、ALBの本番用のリスナーにトラフィックを切り替えます。
デプロイのステータスの各ステップが、成功することを確認します。
CodePipeline の管理コンソールからデプロイパイプラインが成功していることを確認します。
ALBの本番用のリスナーに、curl コマンドを実行して、「Hello World v2」 と切り替われば、Blue/Green デプロイ環境の構築は完了です。(メモしたOutputsの prod_url の値を参照します。)
$ curl http://prefix-dev-sample-app-alb-1234567890.ap-northeast-1.elb.amazonaws.com
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Hello</title>
</head>
<body>
<h1>Hello World v2</h1>
</body>
</html>
詳細は、管理コンソール上から各リソースの設定を確認して下さい。
#後片付け
下記コマンドで、Terraform で作成したAWS環境を削除します。
$ terraform destroy
#さいごに
少しでも初学者のFargate の環境とBlue/Green デプロイパイプラインの学習に役立てれば幸いです。