My Note

自己理解のためのブログ

ECS FargateでGoコンテナを起動してローリングアップデートする

はじめに

今回は ECS FargateでGoコンテナを起動してローリングアップデートする をテーマに書いていきます。

以前の記事でGAEにGo echoで実装したAPIをデプロイしました。

yhidetoshi.hatenablog.com

今回はこのAPIをECSのFargate上にデプロイしてコンテナをローリングアップデートでデプロイします。 Blue/Greenデプロイについては別記事にて紹介する予定です。

アーキテクチャ

本記事のアーキテクチャとデプロイフローは↓

アーキテクチャ f:id:yhidetoshi:20191209211311p:plain

■ デプロイフロー f:id:yhidetoshi:20191209210302p:plain

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 buildgolang:1.13-alpine3.10 のイメージで Goのソースコードコンパイルします。

そして 2つ目の FROM alpine:3.10 のイメージにて、 COPY --from=build /app/go-scraping-apiFROM 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 としています。

■ タスクの定義

f:id:yhidetoshi:20191208094050p:plain

■ コンテナの定義

f:id:yhidetoshi:20191208094054p:plain

ECS Fargateのサービスを作成する

ALBを作成する

サービスをつくる前に ALB と ターゲットグループ を作成します。 今回はFargateのサービスを作るときにALBありで作成します。 説明に必要なところだけピックアップします。

■ ルーティングの設定

f:id:yhidetoshi:20191208103444p:plain

→ ターゲットの種類は IP を選択する必要があります。ヘルスチェックのパスは echoで /ping で実装したためです。

f:id:yhidetoshi:20191208100508p:plain

ネットワーク はFargateを展開するVPCを選択。IP(許容範囲) は何も入力せずに次に進みます。( Fargateのサービスを作成するときにコンテナを展開するサブネットを選択します )

サービスをつくる

■ サービスの設定とデプロイメント

起動タイプは Fargate を選択し、タスク定義は事前に作成したものを選択します。タスク数は1、最小ヘルス率を100% 最大ヘルス数を200% にしました。 これは、タスク数2のときにローリングアップデートすると、最低で2台、最大で4台まで増えてデプロイされます。

f:id:yhidetoshi:20191208104008p:plain

■ ネットワーク構成

コンテナを稼働させるVPCとサブネットを選択します。ALB配下にぶら下げるために先ほど作成したALBの環境に考慮して作成します。 セキュリティグループとパブリックIPの割り当ても環境に応じて設定してします。

f:id:yhidetoshi:20191208103646p:plain

■ Load balancing / ロードバランス用のコンテナ

ロードバランサの種類は ALB を選択。ロードバランサを選択してコンテナを選択します。 コンテナの選択は先ほど作成したタスクに紐づいたコンテナを選択します。ターゲットグループを選択すると先ほど作成したターゲットグループの設定が反映されます。

f:id:yhidetoshi:20191208101731p:plain

プロダクションリスナーポート は ALBが外部から受け付けるポートになります。 今回にALBを作成するときに外部受付ポートを80にして作成したので80がセットされています。

■ コンテナが正常に起動したかを確認

ターゲットグループで登録済みターゲットのステータスが healthyになっていればOK。

f:id:yhidetoshi:20191208104649p:plain

CodePipelineを作成する

Source ( GitHub )

f:id:yhidetoshi:20191207212928p:plain

CodeBuild

CodeBuild上でdockerコマンドを利用してコンテナイメージを作成するので 特権付与を有効 にします。 また、作成したイメージをECRに登録するのでIAMロールにECRにイメージをpushできる権限を付与する必要があります。

■ 環境

f:id:yhidetoshi:20191207213646p:plain

f:id:yhidetoshi:20191207213834p:plain

■ キャッシュ

f:id:yhidetoshi:20191208085215p:plain

docker pullやbuildの処理が高速化されます。しかし、検証したところキャッシュが有効になるのはキャッシュされた次の1回だけでした。

次はbuildspec.ymlを用意していきます。

イメージ定義ファイル名 imagedefinitions.jsonimageUri はこの名前にする必要があります。 さらに、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

docs.aws.amazon.com

CodeDeploy

アクションプロバイダについて、ローリングアップデートする場合は Amazon ECS を選択します。そして、デプロイするコンテナはCodeBuildで作成したイメージを利用するので入力アーティファクトBuildArtifact を選択します。

f:id:yhidetoshi:20191207215111p:plain

作成したコードパイプラインの全体は↓。

f:id:yhidetoshi:20191208151718p:plain

ローリングアップデートの実行と動作確認

ローリングアップデート

ローリングアップデート中にサービスのタスクについて確認した結果↓

■ 開始時 go-scraping-api:5 だけが稼働

f:id:yhidetoshi:20191208151911p:plain

■ 新コンテナのプロビジョニング

go-scraping-api:6 が起動中

f:id:yhidetoshi:20191208151929p:plain

■ 新コンテナ起動完了 f:id:yhidetoshi:20191208152011p:plain

■ 完了時 ( 旧コンテナの削除済 )

go-scraping-api:5 が退役した

f:id:yhidetoshi:20191208152103p:plain

動作確認

動作確認として金とプラチナの価格の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の検証を進めていきたい。