【やってみた】Google Cloud(GCP)のCloud Buildを使用してCloud Runをブルーグリーンデプロイしてみる!

Google Cloud

2023.11.24

Topics

はじめに

こんにちは、最近運動不足で体力の衰えを感じているyasujunです。
今回はGoogle CloudのCloud Buildを使ってマネージドコンテナサービスであるCloud Runをブルーグリーンデプロイしていこうと思います。
CI/CDを使うことでデプロイ前に第三者からのコードチェックが挟まるのでより安全に高速にデプロイすることができます。

今回やること

  • Google Cloud上にCI/CD環境を構築する
  • Cloud Runをデプロイしてみる
  • Cloud Runの設定内容とコンテンツを変更してデプロイする
  • Cloud Runをブルーグリーンデプロイする

事前に準備しておくこと

  • GitHubアカウント
  • Gitツールのインストール(本記事ではGitHub Desktopを使用)
  • Google Cloud上での各種APIの有効化
  • Google Cloud上での適切な権限の割り振り

Google Cloud上にCI/CD環境を構築する

まずは適当なコンテナをCloud Build経由でサクッとCloud Runにデプロイしてみます。
CI/CD環境のイメージはこんな感じです。

処理の流れは下記の通りです。
1. 開発者Aがdevブランチにファイルをpushし、mainブランチにプルリクエストを申請する
2. 開発責任者Bがコードをレビューし、問題が無ければプルリクエストを許可してmainブランチにマージする
3. Cloud BuildがGitHubのmainブランチが更新CI/CDされたのをトリガーに、CloudBuild.yamlファイルに従いデプロイする
4. Dockerfileをビルドし、Artifact RegistryにDockerイメージをpushする
5. Cloud BuildはArtifact RegistryからDockerイメージをpullしてCloud Runにデプロイする

CI/CD環境を構築するまでの流れ

  1. GitHub上でCloud Build連携用のリポジトリを作成する
  2. Cloud BuildからGitHubにリポジトリを連携する
    3.Artifact Registryを作成する
  3. Cloud Buildでトリガーを作成する

1. GitHub上でCloud Build連携用のリポジトリを作成する

お好みで「リポジトリ名」を入力する
(ここではCloud Buildrepoと命名し、リポジトリはできれば「プライべート」で設定する)

他はお好みで設定し「リポジトリの作成」を選択する

リポジトリができたので、ブランチを切るために適当なファイルを作成

適当なファイル名と内容を書き、「変更をコミット」を選択

ファイル作成後、「すべてのブランチを表示」を選択する

「新しい支店」を選択する

「新しい支店名」に「dev」を入力してソースを「主要(main)」を選択し、「新しいブランチを作成する」を選択する


「Code」を選択し、HTTPSのURLをコピーする

GitHub DesktopのFileから「Clone repository…」を選択

Repository URL or GitHub username and repository内に先ほどコピーしたdevブランチのURLをペーストして、「Clone」を選択する

2. Cloud BuildからGitHubにリポジトリを連携する

トリガーの画面から「リポジトリを接続」を選択する

ソースコード管理プロバイダをGitHubを選択し、続行を選択する

トリガーは作成せずに完了を選択する

3. Artifact Registryを作成する

Artifact Registryの画面に行き、「リポジトリを作成」を選択する

名前をお好みで選択し、形式をdockerに選択

リージョンもお好みで選択

作成を選択する

4. Cloud Buildでトリガーを作成する

トリガーの画面から「トリガーを作成」を選択する

トリガー名をお好みで入力する

リポジトリを先ほど連携したリポジトリに選択する

ブランチをメインにして作成を選択する
※デフォルトでイベントはpushがトリガーとなっているため、イベントの説明は割愛する

下記のように作成されたトリガーが表示される

Cloud Runをデプロイしてみた

これでCI/CD環境の作成は完了です。
ここからは作成したCI/CDを使って、実際にCloud Runにコンテナをデプロイしてみます!

デプロイまでの流れ

  1. ファイルをGitHubのdevブランチにアップロードする
  2. GitHub上でプルリクエスト申請をする
  3. mainブランチ側から承認してマージする
  4. デプロイ開始
  5. デプロイ確認

まず、下記ファイルを用意します。

Dockerfile

FROM nginx:latest
RUN echo "Hello" > /usr/share/nginx/html/index.html

設定内容
– Nginxコンテナを使用、ドキュメントルートにHelloファイルを作成する処理が書かれている

CloudBuild.yaml

steps:
  - name: "gcr.io/cloud-builders/docker"
    args: ["build",'--no-cache', "-t", 'asia-northeast1-docker.pkg.dev/[プロジェクト名]/yasujun-test/nginx:latest', "."]
    id: BUILD_nginx_CONTAINER
    waitFor: ["-"]
 
  - name: "gcr.io/cloud-builders/docker"
    args: ["push", 'asia-northeast1-docker.pkg.dev/[プロジェクト名]/yasujun-test/nginx:latest']
    id: PUSH_nginx_CONTAINER
    waitFor:
      - BUILD_nginx_CONTAINER
 
  - name: "gcr.io/google.com/cloudsdktool/cloud-sdk"
    entrypoint: gcloud
    args:
      [
      'run',
      'deploy',
      'yasuda-nginx',
      '--image' , 'asia-northeast1-docker.pkg.dev/[プロジェクト名]/yasujun-test/nginx:latest',
      '--region' , 'asia-northeast1',
      '--port' , '80',
      '--cpu' , '1',
      '--memory', '1Gi',
      '--max-instances', '1',
      '--allow-unauthenticated',
      ]
    id: DEPLOY_nginx
    waitFor:
      - PUSH_nginx_CONTAINER
 
options:
  dynamic_substitutions: true

設定内容
– dockerfileの内容をビルドして、Artifact RegistryにDockerイメージをプッシュする
– GcloudコマンドでCloud Runの設定内容を読み込ませてデプロイする

1. ファイルをGitHubのdevブランチにアップロードする

現在がdevブランチであることを確認し、デプロイテスト用のpushするファイルを選択してコミットする

右上の「push origin」を選択する

2. GitHub上でプルリクエスト申請をする

GitHubのdevブランチ上でプルリクエストエストを作成する

「Create pull request」を選択する

3. mainブランチ側から承認してマージする

差分を確認し、「Marge pull request」を選択する

「Confirm marge」を選択する

4.デプロイ開始

Cloud Buildの画面に行き、ステータスがぐるぐる回っているビルドIDを選択する

この画面から進行中のデプロイプロセスが見れる

うまくデプロイできれば下CI/CD記画面のようになる

5. デプロイ確認

Cloud Runの画面に行き、動いているコンテナを選択する

URLが表示されるのでクリックする

Docker上で記載したHelloが出力されている

Coud Runの設定内容とコンテンツを変更してデプロイする

Cloud Runをデプロイしてみた と同じ要領で設定内容やコンテンツを変えてデプロイすることもできます。
早速下記の構成ファイルを使ってデプロイしてみましょう!
Dockerfile

FROM nginx:latest
COPY ./index.html /usr/share/nginx/html/index.html

設定内容
– Nginxで表示するコンテンツをindex.htmlファイルに指定する

index.html

<html>
<head>
  <style>
    h1 {
      color: red;
    }
  </style>
</head>
<body>
  <h1>DeployUpdate</h1>
</body>
</html>

設定内容
– 赤文字のH1見出しを使って「Cloud Buildテスト」と表示させる

cloudbuild.yaml

steps:
  - name: "gcr.io/cloud-builders/docker"
    args: ["build",'--no-cache', "-t", 'asia-northeast1-docker.pkg.dev/[プロジェクト名]/yasujun-test/nginx:latest', "."]
    id: BUILD_nginx_CONTAINER
    waitFor: ["-"]

  - name: "gcr.io/cloud-builders/docker"
    args: ["push", 'asia-northeast1-docker.pkg.dev/[プロジェクト名]/yasujun-test/nginx:latest']
    id: PUSH_nginx_CONTAINER
    waitFor:
      - BUILD_nginx_CONTAINER

  - name: "gcr.io/google.com/cloudsdktool/cloud-sdk"
    entrypoint: gcloud
    args:
      [
      'run',
      'deploy',
      'yasuda-nginx',
      '--image' , 'asia-northeast1-docker.pkg.dev/[プロジェクト名]/yasujun-test/nginx:latest',
      '--region' , 'asia-northeast1',
      '--port' , '80',
      '--cpu' , '2',
      '--memory', '1Gi',
      '--max-instances', '2',
      '--allow-unauthenticated',
      ]
    id: DEPLOY_nginx
    waitFor:
      - PUSH_nginx_CONTAINER

options:
  dynamic_substitutions: true

設定内容
– 1コンテナのCPUコア数を2に変更
– コンテナの最大数を2に変更

上記ファイルを使ってデプロイしてみる

GitHubデスクトップで変更,作成した3ファイルをcommit&pushする

GitHub上で、devブランチからメインブランチへマージする

ビルド進行中・・・

デプロイ完了後、Cloud Runで確認すると最大インスタンス数とCPU上限が変わっているのが分かる

URLを押すとコンテンツ内容も変化している

Cloud Runをブルーグリーンデプロイしてみる

Cloud Runはブルーグリーンデプロイをすることが可能です。
新しいコンテナをデプロイ時に、現状動いているコンテナからパーセント単位で新しいコンテナにトラフィック量を流すことができます。
また、デプロイ時にyamlファイル内に’–no-traffic’を設定することで、パブリックに外部公開せずに開発者だけがプレビューのような形でコンテンツを確認することができます。
https://cloud.google.com/blog/ja/products/serverless/cloud-run-now-supports-gradual-rollouts-and-rollbacks

ブルーグリーンデプロイ手順

  1. 現在稼働しているコンテナにタグをつける
  2. 新しいコンテナもタグ付けして、トラフィックを通させない状態でデプロイしてWEBページを確認する
  3. WEBページに問題が無ければ新しいコンテナに現状のコンテナのトラフィックを流す

現在稼働しているコンテナにタグをつける

Cloud Runの画面から「リビジョン」を選択する

リビジョンのURL(タグ)の「+」ボタンを押す

フォームが出てくるのでお好みで入力し保存する(ここではblueと入力する)

タグ設定後、埋め込みリンクが出てくるので選択する

先ほどと同様のWEBページが見れることを確認

新しいコンテナもタグ付けして、トラフィックを通させない状態でデプロイしてWEBページを確認する

新しいコンテナにも旧コンテナ同様にタグをつけてデプロイする。
下記のファイルをデプロイしてWEBページを確認してみよう。
Dockerfile

FROM nginx:latest
RUN echo "NewPage!!" > /usr/share/nginx/html/index.html

設定内容
– Nginxコンテナを使用、アクセスするとNewPage!!と出力される

cloudbuild.yaml

steps:
  - name: "gcr.io/cloud-builders/docker"
    args: ["build",'--no-cache', "-t", 'asia-northeast1-docker.pkg.dev/[プロジェクト名]/yasujuntest2/nginx:latest', "."]
    id: BUILD_nginx_CONTAINER
    waitFor: ["-"]

  - name: "gcr.io/cloud-builders/docker"
    args: ["push", 'asia-northeast1-docker.pkg.dev/[プロジェクト名]/yasujuntest2/nginx:latest']
    id: PUSH_nginx_CONTAINER
    waitFor:
      - BUILD_nginx_CONTAINER

  - name: "gcr.io/google.com/cloudsdktool/cloud-sdk"
    entrypoint: gcloud
    args:
      [
      'run',
      'deploy',
      'yasuda-nginx',
      '--image' , 'asia-northeast1-docker.pkg.dev/[プロジェクト名]/yasujuntest2/nginx:latest',
      '--region' , 'asia-northeast1',
      '--port' , '80',
      '--cpu' , '1',
      '--memory', '1Gi',
      '--max-instances', '2',
      '--allow-unauthenticated',
      '--tag','green',
      '--no-traffic',
      ]
    id: DEPLOY_nginx
    waitFor:
      - PUSH_nginx_CONTAINER

options:
  dynamic_substitutions: true

設定内容
– 1コンテナのCPUコア数を1に変更
– タグをblueに設定
– このリビジョンにアクセスさせない

上記をデプロイ後、Cloud Runを見ると下記のようにアクティブなリビジョンが増えている
外部からのトラフィックは0%だが、埋め込みリンクを押すと自分だけ見ることができる

外部公開してないとURLが「タグ名–コンテナのURL」になる

WEBページに問題が無ければ新しいコンテナに現状のコンテナのトラフィックを流す

最後に外部公開してないコンテナに半分だけトラフィックを流す
下記のファイルをデプロイする

steps:
  - name: "gcr.io/google.com/cloudsdktool/cloud-sdk"
    entrypoint: gcloud
    args:
      [
      'run',
      'services',
      'update-traffic',
      'yasuda-nginx',
      '--to-tags' , 'blue=50',
      '--to-tags' , 'green=50',
      '--region' , 'asia-northeast1',
      ]
    id: DEPLOY_nginx
options:
  dynamic_substitutions: true

設定内容
– blueタグの(旧)コンテナのトラフィックを50%に設定
– greenタグの(新規)コンテナのトラフィックを50%に設定

上記をデプロイ後、Cloud Runを見ると下記のように2つのリビジョンでトラフィックが50%になっている
試しにリンクを踏んでみる

最初にgreenタグの付いたwebコンテナが表示された

もう一度、ブラウザを更新するとblueコンテナが表示された(F5を押しまくって遊ぼう!)

最後に

今回はGoogle CloudのCloud Buildを使ってCloud Runを様々な形でデプロイしました。
セキュリティや管理アカウント、ブランチの保護を設定しない素組み状態ではありますがこんなに簡単に作れます。
ぜひ参考にしてくれればうれしいです。

yasujun

インフラの勉強と趣味の武道をバランス良く両立していきたいエンジニアです。 よろしくお願いいたします!

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら