LoginSignup
20
20

More than 1 year has passed since last update.

Terraformで FargateのBlue/Greenデプロイ環境を構築する

Last updated at Posted at 2021-09-22

はじめに

本記事では、Terraform で ECS の Fargate の環境とBlue/Green デプロイのパイプライン
(CodeCommit + CodeBuild + CodeDeploy +CodePipeline)をお試しで構築する手順を記載しています。

Terraform で構築する全体構成図

00_fargate_blue_green_deploy.png

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

モジュールに渡すパラメータ

main.tf
###################
# 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 内の各パラメータを環境に応じて、任意で変更します。

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 の詳細をクリックします。
01_fargate_blue_green_deploy.png

CodeDeploy の管理コンソールからデプロイのステータスを確認します。
02_fargate_blue_green_deploy.png

[デプロイのステータス]が、ステップ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の本番用のリスナーにトラフィックを切り替えます。

03_fargate_blue_green_deploy.png

デプロイのステータスの各ステップが、成功することを確認します。
04_fargate_blue_green_deploy.png

CodePipeline の管理コンソールからデプロイパイプラインが成功していることを確認します。
05_fargate_blue_green_deploy.png

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 デプロイパイプラインの学習に役立てれば幸いです。

参考サイト

ECS Fargateデプロイ用CodePipelineのtaskdef.jsonに変数を持たせる方法

20
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
20