ECS FargateでGoコンテナを起動してローリングアップデートする
- はじめに
- アーキテクチャ
- GitHub
- ECRに登録するGoコンテナを作成する
- ECS Fargateのタスクを作成する
- ECS Fargateのサービスを作成する
- CodePipelineを作成する
- ローリングアップデートの実行と動作確認
- まとめ
はじめに
今回は ECS FargateでGoコンテナを起動してローリングアップデートする をテーマに書いていきます。
以前の記事でGAEにGo echoで実装したAPIをデプロイしました。
今回はこのAPIをECSのFargate上にデプロイしてコンテナをローリングアップデートでデプロイします。 Blue/Greenデプロイについては別記事にて紹介する予定です。
アーキテクチャ
本記事のアーキテクチャとデプロイフローは↓
■ アーキテクチャ
■ デプロイフロー
GitHub
ソースコード全体はこちらに公開しています。 github.com
ECRに登録するGoコンテナを作成する
docker imageを作成
FROM golang:1.13-alpine3.10 as build RUN apk add --update --no-cache git RUN mkdir /app WORKDIR /app COPY go.mod ./ RUN go mod download COPY . . RUN go build -o go-scraping-api . FROM alpine:3.10 RUN apk add --update --no-cache ca-certificates WORKDIR /app COPY --from=build /app/go-scraping-api /app/go-scraping-api ENTRYPOINT ["/app/go-scraping-api"]
Dockerfileに イメージを指定する FROM
が2箇所あります。これは、最初の FROM golang:1.13-alpine3.10 as build
で golang:1.13-alpine3.10
のイメージで Goのソースコードをコンパイルします。
そして 2つ目の FROM alpine:3.10
のイメージにて、 COPY --from=build /app/go-scraping-api
で FROM golang:1.13-alpine3.10 as build
でコンパイルしたバイナリファイルをFROM alpine:3.10
の /app/go-scraping-api
にコピーしています。かなり軽
ECRにdocker imageをpushする
■ イメージを確認
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE go-metal-api latest 581f8817569a 5 hours ago 19.7MB
■ ecrにログイン
$(aws ecr get-login --no-include-email --region ap-northeast-1 --profile my-dev)
■ イメージにタグづけ
docker tag go-metal-api:latest ${ACCOUNT}.dkr.ecr.ap-northeast-1.amazonaws.com/go-scraping-api:latest
■ ecrにimageをpush
docker push ${ACCOUNT}.dkr.ecr.ap-northeast-1.amazonaws.com/go-scraping-api:latest
ECS Fargateのタスクを作成する
ネットワークモードを awsvpc
、 互換性に Fargate
を選択しました。タスク実行ロールは ecsTaskExecutionRole
を適用し
タスクに割り当てるメモリとCPUは最小のものをそれぞれ選択しています。
コンテナについては、イメージは ECR でリポジトリを作成すると払い出させる値をセット。ポートマッピングについては 今回のGoコンテナは3000番ポートでListenするので 3000 としています。
■ タスクの定義
■ コンテナの定義
ECS Fargateのサービスを作成する
ALBを作成する
サービスをつくる前に ALB と ターゲットグループ を作成します。 今回はFargateのサービスを作るときにALBありで作成します。 説明に必要なところだけピックアップします。
■ ルーティングの設定
→ ターゲットの種類は IP
を選択する必要があります。ヘルスチェックのパスは echoで /ping
で実装したためです。
→ ネットワーク
はFargateを展開するVPCを選択。IP(許容範囲)
は何も入力せずに次に進みます。( Fargateのサービスを作成するときにコンテナを展開するサブネットを選択します )
サービスをつくる
■ サービスの設定とデプロイメント
起動タイプは Fargate を選択し、タスク定義は事前に作成したものを選択します。タスク数は1、最小ヘルス率を100% 最大ヘルス数を200% にしました。 これは、タスク数2のときにローリングアップデートすると、最低で2台、最大で4台まで増えてデプロイされます。
■ ネットワーク構成
コンテナを稼働させるVPCとサブネットを選択します。ALB配下にぶら下げるために先ほど作成したALBの環境に考慮して作成します。 セキュリティグループとパブリックIPの割り当ても環境に応じて設定してします。
■ Load balancing / ロードバランス用のコンテナ
ロードバランサの種類は ALB を選択。ロードバランサを選択してコンテナを選択します。 コンテナの選択は先ほど作成したタスクに紐づいたコンテナを選択します。ターゲットグループを選択すると先ほど作成したターゲットグループの設定が反映されます。
プロダクションリスナーポート は ALBが外部から受け付けるポートになります。 今回にALBを作成するときに外部受付ポートを80にして作成したので80がセットされています。
■ コンテナが正常に起動したかを確認
ターゲットグループで登録済みターゲットのステータスが healthyになっていればOK。
CodePipelineを作成する
Source ( GitHub )
CodeBuild
CodeBuild上でdockerコマンドを利用してコンテナイメージを作成するので 特権付与を有効
にします。
また、作成したイメージをECRに登録するのでIAMロールにECRにイメージをpushできる権限を付与する必要があります。
■ 環境
■ キャッシュ
docker pullやbuildの処理が高速化されます。しかし、検証したところキャッシュが有効になるのはキャッシュされた次の1回だけでした。
次はbuildspec.ymlを用意していきます。
イメージ定義ファイル名 imagedefinitions.json
と imageUri
はこの名前にする必要があります。
さらに、imagedefinitions.jsonの中身は []
arrayにする必要があり、こう書かないと invalid json format.. となりエラーとなります。
printf '[{"name":"go-scraping-api","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
→ imagedefinitions.json
の内容は CodeDeplyで BuildArtifact
として参照される。
- buildspec.yml
version: 0.2 phases: install: runtime-versions: golang: 1.13 docker: 18 pre_build: commands: - echo Logging in to Amazon ECR... - aws --version - $(aws ecr get-login --region ap-northeast-1 --no-include-email) - REPOSITORY_URI=`aws sts get-caller-identity --query 'Account' --output text`.dkr.ecr.ap-northeast-1.amazonaws.com/go-scraping-api - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7) - IMAGE_TAG=${COMMIT_HASH:=latest} build: commands: - echo Build started on `date` - echo Building the Docker image... - docker build -t $REPOSITORY_URI:latest . - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG post_build: commands: - echo Build completed on `date` - echo Pushing the Docker images... - docker push $REPOSITORY_URI:latest - docker push $REPOSITORY_URI:$IMAGE_TAG - printf '[{"name":"go-scraping-api","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json artifacts: files: imagedefinitions.json
- Ref
CodeDeploy
アクションプロバイダについて、ローリングアップデートする場合は Amazon ECS
を選択します。そして、デプロイするコンテナはCodeBuildで作成したイメージを利用するので入力アーティファクトは BuildArtifact
を選択します。
作成したコードパイプラインの全体は↓。
ローリングアップデートの実行と動作確認
ローリングアップデート
ローリングアップデート中にサービスのタスクについて確認した結果↓
■ 開始時 go-scraping-api:5 だけが稼働
■ 新コンテナのプロビジョニング
go-scraping-api:6 が起動中
■ 新コンテナ起動完了
■ 完了時 ( 旧コンテナの削除済 )
go-scraping-api:5 が退役した
動作確認
動作確認として金とプラチナの価格のjsonを返すAPIを実行した。
$ curl http://go-scraping-api-XXXXXXXXXX.ap-northeast-1.elb.amazonaws.com/metal
{"time":"2019-12-07T15:47:18.57576583+09:00","goldInfo":{"retailTax":5707,"purchaseTax":5620},"platinum":{"retailTax":3539,"purchaseTax":3408}}
まとめ
今回は GAEで動かしている貴金属を返すGoのAPIを Dockerコンテナ化してECS Fargateに自動デプロイできるようにしました。今回はローリングアップデートについて記載しましたが 次回はBlue/Greenデプロイについて書いていきたいと思います。FargateはEC2の管理が必要ないので複雑でないコンテナ構成であればFargateにデプロイしていくのはとてもいいと思います。 Blue/Greenデプロイをまとめたら EKSの検証を進めていきたい。