【AWS】GithubからCodePipelineでECS/Fargateにデプロイする方法
CodePipelineを使ってECS/Fargateにnginx,phpコンテナをデプロイする方法をまとめます。
目次
構築イメージ
動作環境・前提条件
【動作環境】
OS : macOS 10.14.6
【前提条件】
VPC,サブネットは作成済
STEP1. ECRの作成とイメージのプッシュ
ECR(Amazon Elastic Container Registry)とはDocker Hubのようなコンテナイメージを保管するAWS上のレジストリのことです.
ECRの作成
複数のイメージコンテナをデプロイするため、レジストリも複数作成します.
リポジトリ名は任意で構いませんが、後ほどdockerイメージとタグ付けを行うため,管理しやすいようdockerfileで定義したコンテナ名と同じ名前をつけています.
イメージのプッシュ
次にそれぞれのリポジトリ名をクリックし、リポジトリに入り、プッシュコマンドの表示
を押します.
表示されたコマンドを手元のMACのターミナルで実行します.
実行後、ECRにlatestタグが付いたイメージがアップロードされます.
STEP2. タスク定義ファイルとAppspecファイルの作成
タスク定義ファイル
AWSのチュートリアルではtaskdef.json
と記載されていますが、
複数コンテナを同じタスクに登録する場合,この時点ではテンプレートを作成し、codebuildの際にtaskdef.jsonを作成するように設定します.
{
"executionRoleArn": "arn:aws:iam::アカウントID:role/ecsTaskExecutionRole",
"containerDefinitions": [{
"name": "nginx",
"image": "<IMAGE_NGINX_NAME>",
"essential": true,
"portMappings": [{
"hostPort": 80,
"protocol": "tcp",
"containerPort": 80
}]
},
{
"name": "php",
"image": "<IMAGE_PHP_NAME>",
"essential": true,
"portMappings": [{
"hostPort": 9000,
"protocol": "tcp",
"containerPort": 9000
}]
}
],
"requiresCompatibilities": [
"FARGATE"
],
"networkMode": "awsvpc",
"cpu": "256",
"memory": "512",
"family": "ecs-task"
}
Appspecファイル
AppspecファイルはCodeDeployの際に実行されます.
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: <TASK_DEFINITION>
#<TASK_DEFINITION>は変えずにそのままにする
LoadBalancerInfo:
ContainerName: "nginx"
ContainerPort: 80
作成したタスク定義ファイルとAppspecファイルをプロジェクト直下のフォルダに保存し、githubにpushします.
STEP3. アプリケーションロードバランサーとターゲットグループを作成する
アプリケーションロードバランサとターゲットグループをAWSチュートリアルに沿って作成します.
https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/tutorials-ecs-ecr-codedeploy.html#tutorials-ecs-ecr-codedeploy-loadbal
STEP4. ECSクラスターとサービスを作成する
ECSクラスターとサービスも上記リンクのSTEP4
と同じように作成します.
参考までに作成したサービス作成ファイルを掲示します.
{
"taskDefinition": "ecs-task",
"cluster": "ecs-cluster01",
"loadBalancers": [{
"targetGroupArn": "AWSのサイトで確認したtargetgroupのArnを入力",
"containerName": "nginx",
"containerPort": 80
}],
"desiredCount": 1, #タスク実行数を定義しています.
"launchType": "FARGATE",
"schedulingStrategy": "REPLICA",
"deploymentController": {
"type": "CODE_DEPLOY"
},
"networkConfiguration": {
"awsvpcConfiguration": {
"subnets": [
"subnet-0fXXXXXのようなsubnet IDを記載",
"subnet-0fXXXXXのような2つ目のsubnet IDを記載"
],
"securityGroups": [
"security gropuのIDを記載"
],
"assignPublicIp": "ENABLED"
}
}
}
こちらもプロジェクトフォルダに保存し、ローカルPCのターミナルからコマンドを実行,サービスを作成します.
*ecs-test-serviceはサービス名のため任意の名前を付けられます
aws ecs create-service --service-name ecs-test-service --cli-input-json file://create-service.json
STEP5. CodeDeployアプリケーションとデプロイグループを作成
こちらもAWSチュートリアルに従って作成していきます
https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/tutorials-ecs-ecr-codedeploy.html#tutorials-ecs-ecr-codedeploy-cluster
注釈
まずは動かして動作を確かめる場合はチュートリアル通りで問題ないです。
ただチュートリアルだとすぐにトラフィックを再ルーティング
となっておりデプロイした新しいターゲットグループに対してすぐにユーザがアクセスできるようになっています。
またデフォルトでは1時間後に、古いリビジョンが消去されるようになっているため、こちらも運用ポリシーに沿って変更します。
こちらではどちらも1日と設定しています。
STEP6. CodeBuildを作成
CodeBuildを実行するためにBuildspecファイルを作成し、プロジェクトフォルダのルートに保存します.そして、GithubにPushします.
version: 0.2
phases:
pre_build:
commands:
- IMAGE_URI_WEB=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME_WEB
- IMAGE_URI_PHP=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME_PHP
- $(aws ecr get-login --no-include-email --region ${AWS_DEFAULT_REGION})
build:
commands:
- docker-compose -f docker-compose-production.yml build
- docker tag src_web:$IMAGE_TAG $IMAGE_URI_WEB:$IMAGE_TAG
- docker tag src_php:$IMAGE_TAG $IMAGE_URI_PHP:$IMAGE_TAG
post_build:
commands:
- docker push $IMAGE_URI_WEB:$IMAGE_TAG
- docker push $IMAGE_URI_PHP:$IMAGE_TAG
#taskdef-templateで定義したIMAGE_URIを環境変数で置き換えています.
- cat taskdef-template.json | sed -e s@\<IMAGE_WEB_NAME\>@$IMAGE_URI_WEB:$IMAGE_TAG@ -e s@\<IMAGE_PHP_NAME\>@$IMAGE_URI_PHP:$IMAGE_TAG@ > taskdef.json
artifacts:
files:
- appspec.yaml
- taskdef.json
その後、AWSの管理画面からCodeBuildの作成を選択します。
作成時に環境変数を設定する画面があるためにそこにリポジトリ名などを入れます。
そして、ソースとしてGithubを選択します.
アーティファクトも不要です.
ポイント1. 特権を付与
そしてBuildの作成を実行します.
ポイント2. CodeBuildにポリシーを付与
codebuild作成後、CodeBuildがECRにアクセスできるようにCodeBuildのサービスロールにAmazonEC2ContainerRegistryPowerUser
ポリシーをアタッチします.
STEP7. CodePipelineを作成
最後にCodePipelineの作成を選択し、ソースにはGithub, ビルドステップではSTEP5で作成したCodeBuildを選択します。
デプロイステップではAmazon ECS(ブルー/グリーン)を選択し、
Source Artifactでtaskdef.jsonとappspec.ymlを選択します。
タスク定義の動的な更新イメージ - オプショナル
は入力不要です。
動作確認
作成が完了するとCodePipelineがスタートします。
ここでDeployのところでステータスが処理中になります。
そのため、ロードバランサのDNS:8080(テスト用のリスナー)にアクセスに新しくデプロイしたシステムが問題なく動くか確認します。
問題なさそうであればDeploy画面からトラフィックの再ルーティングをクリックすると、
新システムにトラフィックが流れ始めます。
その後、CodeDeployで設定した待機時間をすぎると古いタスクが停止されCodeDeployが成功となります。
実際にAWSの管理画面からECSを選択し、タスクが実行されていることを確認します。
そしてブラウザからロードバランサが持つ、パブリックDNSに対してアクセスし、PHPの画面が表示されれば成功です。
その後、githubに対して新たなバージョンをpushするとcodepiplineが実行されます.