はじめに
プロジェクトによってインフラ構成の違いはありますが、みなさんは快適なデプロイフロー組めてますか?
自分は今週にフルスクラッチでサービスをリリースする事が出来ました。
その際にインフラ構成にECSを採用しました。
前職でもECSを使っており、もうEC2には戻れない体になってしまいました。。
そしてgithub actionsが正式にリリースされてからその魅力に取り憑かれてしまい、前職の会社でも色んな物を無人化していました。
前職は大きな会社だった為、prdへのデプロイは最新の注意が図られていた為、approveも無いgithub actionsでprdへのデプロイは少し難しい環境でした。
codepipelineもapprove, blue/greenが魅力的ですが、体制が整っておらず速度を求められるスタートアップや、個人開発だとこのデプロイで事足りると思います!
前提
- cluster,service,taskは事前に用意して下さい(環境別に命名規則を決めておいて下さい)
今回の場合では下記の様に設定しています。(prdの場合)適宜読み直して下さい
- cluster -> prd-api
- ecs-task-definition -> prd-api
- container-name -> prd-api
- service -> prd-api
さあこれが最強デプロイだ!
on:
push:
branches:
- master
- deploy/production
env:
INTERMEDIATE_TASK_DEFINITION: task-definition.json
ECR_REPOSITORY: レポジトリ名入れてね
name: Deploy to ECS
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- name: Set variables
id: variables
run: |
if [ "${{ github.ref }}" == "refs/heads/deploy/production" ]; then
env="prd"
else
env="stg"
fi
// ここら辺に命名規則
// 環境を切り替えて変数をセットしていきます。
echo "::set-output name=env::$env"
echo "::set-output name=ecs-task-definition::$env-api"
echo "::set-output name=container-name::$env-api"
echo "::set-output name=service::sw-$env-api"
echo "::set-output name=cluster::sw-$env"
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
// githubのsecretにecrとecsのポリシーをアタッチしたIAMを同じ名前でセットして下さい
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
// loginします
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Set ECR repository name
id: repository-name
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: |
IMAGE_TAG=$(echo ${{ github.sha }} | cut -c 1-7)
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
// dockerをbuildします。ここは各プロジェクトによって変わると思います。
// 複数のコンテナの場合も下で説明します。
- name: Build and push image to Amazon ECR
id: build-image
if: "steps.variables.outputs.env != 'prd'"
run: |
docker build -t ${{ steps.repository-name.outputs.image }} --build-arg version=$IMAGE_TAG .
docker push ${{ steps.repository-name.outputs.image }}
// 現在のtask-definitionを取得して、上で設定したtask-definition.jsonで書き込みます。
- name: Fetch current task definition
run: |
aws ecs describe-task-definition --task-definition ${{ steps.variables.outputs.ecs-task-definition }} --query taskDefinition | \
jq '(del(.revision, .requiresAttributes, .compatibilities, .taskDefinitionArn, .status))' > ${INTERMEDIATE_TASK_DEFINITION}
// 新しいタスクでサービスを更新します
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ env.INTERMEDIATE_TASK_DEFINITION }}
container-name: ${{ steps.variables.outputs.container-name }}
image: ${{ steps.repository-name.outputs.image }}
// デプロイ!
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ steps.variables.outputs.service }}
cluster: ${{ steps.variables.outputs.cluster }}
wait-for-service-stability: false
終わり
まあawsのブログ見たら載ってるんだけどな。。
開発フローとしては
- prベースでmasterにマージ
- stg環境にデプロイされる
- prd環境デプロイする為には最新のimageからデプロイする為にローカルのmasterからoriginのdeploy/productionにpushする
この様なフローをとる必要があるので注意して下さい!