エンジニア

2019.05.21

バッチ処理をECSに移行した話(GitHubActionsもあるよ)その2

バッチ処理をECSに移行した話(GitHubActionsもあるよ)その2

こんにちは、ハンズラボの清水です。東急ハンズのECサイトを担当しています。今回は前回の続き、GitHubのリポジトリにpushしたらECRへpushを行うGitHubActionsを紹介します。

前回の記事はこちら
バッチ処理をECSに移行した話(GitHubActionsもあるよ)その1

前回の記事の追記(Fargateになりました)

前回の記事のクラスターを作成にEC2を利用しましたが、その後、NATGatewayにElasticIPをつけることでFargateで出て行くIPアドレスを固定することができたのでFargateになりました。

IPアドレスを固定する理由は外部ECモール(yahoo, 楽天など)のAPIを利用する際、IPアドレスの制限があるのでIPを固定しています。

GitHubActionsを作成する

ここから本題!GitHubのリポジトリにpushしたらECRへpushを行うGitHubActionsを作成していきます。
参考にしたもの(https://github.com/actions/example-aws)

主な流れはこんな感じ

  1. GitHubのリポジトリにコードをpushする
  2. docker buildを行う
  3. dockerにタグをつける
  4. AWSのアカウントにログイン
  5. ECRにpushする

GitHubのリポジトリから作成します。
作成を行うとプロジェクト内に.github/main.workflowというファイルが作成されます。GitHubActionsのGUIで作成も出来ますし、main.workflowを編集して作成もできます。

個人的にはGUIで大まかな流れを作成して、main.workflowを編集するやり方が個人的には作成しやすいです。

main.workflowの見方

workflow "Build and Deploy(prod)" {
  resolves = [ # 実行するAction
    "Filters Branch(prod)",
    "Slack Push Finish(prod)",
    "Slack Push Start(prod)",
  ]
  on = "push"
}
action "Filters Branch(prod)" {
  uses = "actions/bin/filter@master"
  args = "branch master" # ブランチがmasterの時のみ
}
action "Build Docker Image(prod)" {
  uses = "actions/docker/cli@master"
  # 環境変数
  env = {
    STAGE = "prod"
  }
  args = ["build", "-t", "test-python", ".", "--build-arg", "STAGE=$STAGE"] # dockerコマンドのargs
  needs = ["Filters Branch(prod)"] # Filters Branch(prod)の後に実行
}

がっつりmain.workflowを書くことはありませんが、GUIである程度作成してしまえばいいので編集するのはenvargsくらいです。
usesは使用するdocker imageです。(独自の環境での実行もできます)

作成したもの

各説明(処理の流れ)

1. ブランチをフィルタリングする

pushされたブランチがmasterの時のみ下に処理を流します。
GitHubActionsでは条件分岐ができないのでFillterを使用しています。

2. イメージのbuild, ECRへのログイン, slack通知

ここではイメージの build、ECRへのログイン、slackへの通知を並列で実行します。

action "Build Docker Image(prod)" {
  uses = "actions/docker/cli@master"
  env = {
    STAGE = "prod"
  }
  args = ["build", "-t", "test-python", ".", "--build-arg", "STAGE=$STAGE"]
  needs = ["Filters Branch(prod)"]
}

やっていることはdocker build -t test-python . –build-arg STAGE=$STAGEのコマンドを実行しています。

action "Login to ECR(prod)" {
  uses = "actions/aws/cli@master"
  args = "ecr get-login --no-include-email --region ap-northeast-1 | sh"
  secrets = [
    "AWS_ACCESS_KEY_ID",
    "AWS_SECRET_ACCESS_KEY",
  ]
  needs = ["Filters Branch(prod)"]
}

ECRへのログインも先ほどのdocker build同様にawsのコマンドを実行しています。secretsAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYをセットすることでECRにログインできます。

secretsの登録は割と簡単です。

action "Slack Push Start(prod)" {
  uses = "Ilshidur/action-slack@master"
  needs = ["Filters Branch(prod)"]
  secrets = ["SLACK_WEBHOOK"]
  args = "push開始(prod)"
}

slack通知はsecretsにwebhookのURLをセットしてargsにチャンネルに通知するメッセージを設定します。

3. dockerイメージにタグをつける

action "Tag image for ECR(prod)" {
  uses = "actions/docker/tag@master"
  env = {
    CONTAINER_REGISTRY_PATH = "<アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com"
    IMAGE_NAME = "test-python"
  }
  args = ["$IMAGE_NAME", "$CONTAINER_REGISTRY_PATH/$IMAGE_NAME"]
  needs = ["Build Docker Image(prod)"]
}
docker tag test-python:latest <アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/hogehoge:latest

行なっていることは上記のコマンドと同じですコマンドではバージョンをlatestとしていますが、GitHubActionsではバージョンにブランチ名が適応されます。

4. ECRへpushする

action "Push image to ECR(prod)" {
  uses = "actions/docker/cli@master"
  needs = [
    "Login to ECR(prod)",
    "Tag image for ECR(prod)",
  ]
  env = {
    CONTAINER_REGISTRY_PATH = "<アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com"
    IMAGE_NAME = "test-python"
  }
  args = ["push", "$CONTAINER_REGISTRY_PATH/$IMAGE_NAME"]
}

dockerイメージのタグ付け、ECRへのログインが終わり次第ECRへpushを行います。

docker push <アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/test-python:latest

行なっているコマンドは同じですがバージョンのlatestは今回masterになっています。ECSのタスク定義でイメージのURLをlatestにしている場合はmasterに変更しましょう。

5. 完了通知をslackに飛ばす

2. の工程で説明を行なっているので省略します。

masterへpushを行うと、リポジトリのActionsタブから実行ログを見ることができます。

GitHubActionsを使って見ての感想

良い点

  • 作成が簡単
  • 処理の流れが見やすい
  • Dockerとの相性が良い

悪い点

  • ブランチごとにActionsを定義できない
  • 条件分岐が使用できない(失敗したら~~するとか)
  • AWSの複数アカウントに対応できない(Keyを1セットしか登録できない)

現在GitHubActionsはPublicBetaなので今後の機能追加に期待しています。

一覧に戻る