fltech - 富士通研究所の技術ブログ

富士通研究所の研究員がさまざまなテーマで語る技術ブログ

GitHub ActionsでBlue-Green Deploymentを組んでみた

f:id:fltech:20200820135338p:plain

はじめに

こんにちは、サイバーフィジカル融合基盤プロジェクトのです。主にインフラ周りを担当しています。 GitHub Actionsが昨年11月にGAになってだいぶ経ちました。すでに本番投入している方も多いのではないでしょうか。2020年6月にGitHub Actionsを組んでみたので、紹介したいと思います。

今回、GCP上に組んでいる開発中の推薦エンジンシステムをリリースするタイミングで、Blue-Green Deploymentに組み替え、GitHub Actionsを使ってCDを実現し、継続的に開発できるようにしました。

GitHub Actionsを使った1番の理由は、GitHubだけでCI/CDまで完結するからです。我々もAtlassian Confluence/JIRA、CircleCIなどを使って複数のツールを組み合わせてビルドパイプラインを組んでいますがブラウザのタブが増えてしまうのをなんとかしたいと考えていました。GitLabであれば統合的なビルドパイプラインが簡単に組めて良いのですが、使い慣れたGitHubからは離れられませんでした。そこに登場したActions、しかもFreeプランから使えるので使わないわけにはいかないですね!GitHub Marketplaceにも多くのActionsが公開されており、パブリッククラウドや各種SaaSとのインテグレーションが簡単にできることも決め手となりました。

Blue-Green Deploymentの概要

リリース前の構成

簡略化していますが、リリース前は以下のように構成で組んでいました。

f:id:fltech:20200820135144p:plain
リリース前の構成

夜間バッチで推薦エンジンを動かし、学習済みモデルをメモリキャッシュに反映させ、差分をDBを更新し、WebAPIから使えるようにしています。WebAPIは学習エンジンの処理時間にかかわらず動作するため、冗長構成にせずともSLI/SLOを満たせる構成になっています。 参考までに我々の推薦エンジンで設定しているSLI/SLOは以下になります。

  • 可用性(HTTP Success Rate)2xx応答数/総アクセス数99.99%以上

リリース後の構成

リリース後は、並行して開発を継続して行うために、CDを任意なタイミングで実施する必要が出てきました。リリース前の構成のみで実現しようとすると、WebAPIで必要な情報が取れなくなる時間が延び結果的にSLI/SLOを満たせなくなる可能性が出てきました。そのため、Blue-Green Deploymentを採用して、開発環境を別途用意して、切り替えのタイミングで本番環境のデータと同期するように構成を変更しました。

構成は、以下のように組みました。

f:id:fltech:20200820135245p:plain
リリース後の構成

クライアントのエンドポイントを固定にするため、Cloud Functionsの前段にCloud Endpointsを設け、本番環境・開発環境を固定して、後段のBlue-Green環境への接続を切り替えることで実現しました。

Cloud Endpointsを二重に設けている理由は、openapi-functions.yamlx-google-backendでバックエンドを指定するのですが、Cloud ConsoleでCloud Runの奥深くを探さないと、バックエンドで指しているCloud Functionsがわからず、視認性が悪いためこのような方法を取りました。

Cloud EndpointsのExtensible Service Proxy(ESPv1)で、Cloud Run上に展開し、Blue-Greenの切り替えは接続先を示す環境変数ENDPOINTS_SERVICE_NAMEを切り替えることで実現しました。この方法であれば、Cloud Endpointsを再度展開する必要がなく、Cloud Runの環境変数を更新するだけで完了するため、切り替えにかかる停止時間を短くすることができます。

※ESPv2ではこのやり方はできなくなっているようですので、素直にx-google-backendが異なるBlue/Greenのyamlを別々に用意して切り替える方が良いかもしれません。

Blueのopenapi-functions.yamlを以下に示します。

swagger: '2.0'
info:
  title: Cloud Endpoints + GCF
  description: Recommend blue
  version: 1.0.0
host: recommend-blue-hogehoge-uc.a.run.app
schemes:
  - https
produces:
  - application/json
paths:
  /spot_recommend:
    post:
      summary: recommend blue
      operationId: recommend_blue
      x-google-backend:
        address: https://asia-northeast1-hogehoge-project.cloudfunctions.net/recommend_blue
      responses:
        '200':
          description: A successful response
          schema:
            type: string

Blue/GreenのCloud EndpointsのENDPOINTS_SERVICE_NAMEは自分自身を指し、x-google-backendに実際のCloud Functionsを指すことで実現します。

Prod/DevのCloud EndpointsのENDPOINTS_SERVICE_NAMEにBlue/Greenを指し、x-google-backendにはダミーのアドレスを指します。

GitHub Actionsを使ってBlue-Green Deploymentの実現

GitHub Actionsは、PushやPull Requestをトリガーに自動で動かすことが一般的ですが、repository_dispatchを使うことで任意のタイミングで手動でトリガーすることができます。 CIとは異なり、CDでコケたときは人手が必要になることがあり、Blue-Greenの切り替えなどCDに関わる操作は、以下のようにGitHub ActionsでAPI化してHTTP POSTすることで手動で実現しました。

f:id:fltech:20200820135338p:plain
GitHub Actionsを使ったBlue-Green Deployment
Blue-Green Deploymentに必要なワークフローは5つで、開発環境に対して推薦エンジンやWebAPIの展開を任意のタイミングで行い、切り替えのタイミングでDBの更新、キャッシュの同期を行って、最後にBlue-Greenの切り替えを行います。

Blue-Green切り替えのワークフローを以下に示します。

name: Blue/Green Dispatch
on:
  repository_dispatch:
    branches: [ master ]
    types: [ bg-dispatch ]
jobs:
  dispatch:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout the repository
        uses: actions/checkout@v2
      - name: GCP Authenticate
        uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
        with:
          version: '298.0.0'
          project_id: ${{ secrets.GCP_PROJECT_ID }}
          service_account_email: ${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }}
          service_account_key: ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}
      - name: Dispatch Cloud Run
        run: |
          gcloud components install beta --quiet
          gcloud beta run services update recommend-prod --update-env-vars=ENDPOINTS_SERVICE_NAME=recommend-${{ github.event.client_payload.prod }}-hogehoge-uc.a.run.app --project ${{ secrets.GCP_PROJECT_ID }} --platform managed --region ${{ secrets.GCP_REGION }}
          gcloud beta run services update recommend-dev --update-env-vars=ENDPOINTS_SERVICE_NAME=recommend-${{ github.event.client_payload.dev }}-hogehoge-uc.a.run.app --project ${{ secrets.GCP_PROJECT_ID }} --platform managed --region ${{ secrets.GCP_REGION }}

client_payloadでパラメータを渡せるようになっているので、${{ github.event.client_payload.prod }}に本番環境、${{ github.event.client_payload.dev }}に開発環境をそれぞれBlue/Greenを指定しています。 GCPへの接続はマーケットに公開されている公式のActionsを使いました。 GitHub ActionsのSecretsはRepositoryまたはOrganizationに保存することができ、GitHub Actionsからは${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }}のように参照することで秘匿化しています。

リクエストに{"event_type": "bg-dispatch", "client_payload": {"prod": "green", "dev": "blue"}}を付加することで、本番環境をGreen、開発環境をBlueに切り替えることができるようになります。

終わりに

GitHub Actionsを使ってGCPで組んだ推薦エンジンをリリースに合わせてBlue-Green Deploymentを実現しました。 費用負担もなく手軽に使い始めることができ、柔軟にCDも組めるので、まだ導入をしていない方は試してみてはいかがでしょうか。