こちらはドクターズプライム Advent Calendar 2021の4日目の記事です。昨日3日目の記事はこちら。
こんにちは、ソフトウェアエンジニアのoinumeです。今日はGoogle App Engineのデプロイを速くした話をお届けします。
はじめに
こちらの記事にあるように、弊社のWebアプリケーションのバックエンドはGoで作っています。アプリケーションを動かす環境としてはGoogle App Engine(以下GAE)を使用しており、リクエスト特性に応じて以下の3種類のServiceが存在しています。
- api: フロントエンドから呼ばれるAPI Service
- batch: Cloud Schedulerから呼ばれるバッチ処理向けService
- task: Cloud Tasksから呼ばれる非同期処理向けService
上記の3種類のServiceにデプロイする必要があるため、gcloud app deploy
コマンドを3回実行することになり、1回のデプロイに8分ほど時間がかかっていました。個人的には8分という時間は短いようで長いと感じており、このぐらい待ち時間があるとデプロイを忘れて他の作業(Twitterを見るなど)をしてしまう弊害があります。
また、デプロイの待ち時間が長くなってしまうと、デプロイ頻度の低下につながり、機能追加やバグ修正などのデリバリーサイクルが回りにくくなってしまうという課題もありました。そのため、重い腰をあげてデプロイ速度の改善に取り組みました。具体的にはGitHub Actionsのbuild matrixを使って速度改善したので、その紹介をしたいと思います。
GitHub Actionsのbuild matrix
GAEへのデプロイにはGitHub Actionsを使用しているのですが、GitHub Actionsにはbuild matrixと呼ばれる仕組みがあります。一般的には以下のようにCIで複数のランタイム(Go 1.15, 1.16, 1.17など)でテストを実行するなどの用途で使われることが多いです。
jobs: test: strategy: matrix: go-version: [1.15, 1.16, 1.17] runs-on: ubuntu-latest steps: - name: Install Go uses: actions/setup-go@v2 with: go-version: ${{ matrix.go-version }} - name: Checkout code uses: actions/checkout@v2 - name: Test run: go test ./...
GAEの3種類のSerivceへのデプロイも3回ほぼ同じことをやっていたので、このbuild matrixが使えそうだと気付きました。実際のGitHub ActionsのYAMLを一部抜粋すると、以下のように変更してapi
, batch
, task
のserviceをmatrixとして定義して、3並列でデプロイのjobを実行するようにしています。3並列化されたことにより、デプロイにかかる時間が8分30秒から5分程度になりました。
BEFORE
steps: - name: Check out the repository uses: actions/checkout@v2 with: path: ${{ env.GOPATH }}/src/github.com/${{ github.repository }} <中略> - name: Install App Engine Go SDK run: sudo apt-get install google-cloud-sdk-app-engine-go - name: Initialize Google Cloud SDK uses: google-github-actions/setup-gcloud@master with: project_id: ... service_account_key: ... service_account_email: ... export_default_credentials: true - name: Deploy beer-server to production run: | go mod vendor GO111MODULE=off gcloud app deploy --version $DEPLOY_VERSION --no-promote --quiet ./entrypoint/api/app_prod.yaml GO111MODULE=off gcloud app deploy --version $DEPLOY_VERSION --no-promote --quiet ./entrypoint/task/app_prod.yaml GO111MODULE=off gcloud app deploy --version $DEPLOY_VERSION --no-promote --quiet ./entrypoint/batch/app_prod.yaml
AFTER
strategy: max-parallel: 3 matrix: service: ["api", "batch", "task"] steps: - name: Check out the repository uses: actions/checkout@v2 with: path: ${{ env.GOPATH }}/src/github.com/${{ github.repository }} <中略> - name: Install App Engine Go SDK run: sudo apt-get install google-cloud-sdk-app-engine-go - name: Initialize Google Cloud SDK uses: google-github-actions/setup-gcloud@master with: project_id: ... service_account_key: ... service_account_email: ... export_default_credentials: true - name: Run go mod vendor run: | go mod vendor - name: Deploy beer-server to production run: | GO111MODULE=off gcloud app deploy --version $DEPLOY_VERSION --no-promote --quiet ./entrypoint/${{ matrix.service }}/app_prod.yaml
DIFF
> strategy: > max-parallel: 3 > matrix: > service: ["api", "batch", "task"] 16c20 < - name: Deploy beer-server to production --- > - name: Run go mod vendor 19,21c23,25 < GO111MODULE=off gcloud app deploy --version $DEPLOY_VERSION --no-promote --quiet ./entrypoint/api/app_prod.yaml < GO111MODULE=off gcloud app deploy --version $DEPLOY_VERSION --no-promote --quiet ./entrypoint/task/app_prod.yaml < GO111MODULE=off gcloud app deploy --version $DEPLOY_VERSION --no-promote --quiet ./entrypoint/batch/app_prod.yaml --- > - name: Deploy beer-server to production > run: | > GO111MODULE=off gcloud app deploy --version $DEPLOY_VERSION --no-promote --quiet ./entrypoint/${{ matrix.service }}/app_prod.yaml
最後に
簡単ですが、GitHub Actionsの機能を使うことでデプロイを高速化する手法を紹介しました。この記事が読者の方のCI/CD環境の改善につながれば幸いです。
一緒に働く仲間を募集しています
ドクターズプライムでは「救急車のたらい回しをゼロにする」というビジョンの実現に向けて、病院向けのSaaSプロダクトおよび、医師/病院間の最適なマッチングを提供するマッチングプラットフォームを展開しており、一緒に働く仲間を募集しています。(CI/CDの改善などDevOps領域にも興味があるソフトウェアエンジニアも大募集しています)
私もMeetyを公開しているので、まずはカジュアルにお話ししてみませんか?