実装と運用

IaC とデリバリー

インフラは Terraform で書き、アプリは Cloud Build でビルドして Artifact Registry に置き、Cloud Deploy で段階的に出します。試験では、手作業を減らし、問題が出たらすぐ戻せる構成が正解になります。

デリバリーの基本形は下の図の流れです。本番へはカナリアかブルーグリーンで少しずつ出し、問題が出たら前のリビジョンに戻します。設問に「デプロイのたびに障害が起きる」「環境ごとに設定がずれる」とあれば、この流れのどこが欠けているかを探します。

GitpushCloud BuildテストとビルドレジストリArtifact RegistryCloud Deploy昇格を管理環境Terraformstate は GCSdev昇格staging承認prod
アプリは同じイメージを dev から prod へ昇格させ、本番の前に承認を挟む。環境そのものは Terraform で作るので、環境ごとの設定がずれない

インフラは Terraform で書き、手作業を残さない

コンソールで作ったリソースは、誰が何をいつ変えたかが残らず、環境がずれて本番だけで障害が起きます。「手順書どおりにコンソールで作る」と「Terraform で定義してパイプラインから適用する」が並んだら後者です。

state ファイルは Cloud Storage のバケットに置きます(backend "gcs")。各自の PC に置くと、2 人が同時に適用したときに state の中身がおかしくなります。変更は terraform plan の結果をプルリクエストでレビューしてから terraform apply します。

実行環境と state の置き場を用意したくなければ Infrastructure Manager を使います。Terraform の構成を受け取って Cloud Build の一時的な環境で適用し、リビジョンと state もサービス側で管理します。

やりたいこと選ぶもの
ほかのクラウドも同じコードで管理するTerraform(state は Cloud Storage)
実行環境と state の管理を任せたいInfrastructure Manager
Deployment Manager の構成を引き継いだInfrastructure Manager へ移行する

Deployment Manager はサポートが終了しています。古い問題集の正解は Terraform か Infrastructure Manager に読み替えます。

Cloud Build でビルドし、Cloud Deploy で昇格させる

Cloud Build は手順を cloudbuild.yaml に書くマネージドの CI です。社内ネットワークの中のリソースに触れるならプライベートプールを使います。Artifact Registry にはイメージのほか npm、Maven、Python のパッケージも置けます。脆弱性スキャンと Binary Authorization はセキュリティの設計で扱います。

Cloud Deploy は、GKE や Cloud Run へのデプロイをデリバリーパイプラインとして定義し、同じリリースをターゲットの順に昇格させます。「どの環境にどのバージョンが出ているかを把握したい」「本番反映に承認を入れたい」とあれば Cloud Deploy です。

デプロイ戦略は、切り替えた瞬間に新版を使う人の数で選ぶ

ローリング新版新版旧版旧版ブルーグリーン旧環境 (待機)新環境 100%カナリア新版 10%旧版 90%
ブルーグリーンは戻すのが速いが、切り替えた瞬間に全員が新版を使う。影響を受ける人を最小にしたいならカナリア

ローリングは追加の費用が少ない代わりに戻すのにも時間がかかり、ブルーグリーンは切り替えの間だけ環境が 2 倍要ります。カナリアは監視の指標がないと進めるか判断できません。

Cloud Deploy のカナリアは、25、50、75 のように割合を並べるとその数だけフェーズを作り、100% の stable フェーズで終わります。各フェーズに検証ジョブを入れ、Cloud Monitoring の指標で次へ進めるかを判断させられます(カナリアデプロイ)。MIG のローリング更新では、一度に置き換える台数と一時的に足す台数を指定します。Cloud Run はリビジョンごとにトラフィックの割合を指定できます。

下の例では、新版のエラー率が 1% を超えたら戻すと決めてあります。

試すカナリアの昇格とロールバック

0.5%
  1. 25%
  2. 50%
  3. 75%
  4. 100%
新版新版への流量 25%旧版

新版のエラー率 0.5% は基準の 1% 以下です。次の 50% へ進めてよい状態です。

テストは種類ごとに置き場所を決める

試験ガイドが挙げるのは単体テスト、結合テスト、負荷テストです。単体テストは Cloud Build の最初に走らせ、失敗したらイメージを作りません。結合テストは staging へのデプロイ後、負荷テストは本番に近い規模の環境でリリースやイベントの前に行います(可観測性と信頼性の運用)。

Google Cloud のサービスに依存するテストには、gcloud のエミュレータ(Bigtable、Spanner、Pub/Sub、Firestore など)を使えば課金されません。

gcloud beta emulators pubsub start --project=test-project

Cloud Code は VS Code と JetBrains の拡張機能で、Cloud Run や GKE へのデプロイを IDE から行えます。

外部に公開する API は Apigee で管理する

パートナーへの API 公開で、キーの発行、パートナーごとのクォータ、利用状況の分析、収益化までを行うなら Apigee です。オンプレミスの API もまとめて管理できます。サーバーレスの社内 API に認証を付けたいだけなら API Gateway で足ります。

試してみる

Cloud Run でカナリアリリースと切り戻しを試します。この規模なら無料枠に収まります。

1 つ目のリビジョンを出します。

gcloud config set run/region asia-northeast1
gcloud run deploy hello \
  --image=us-docker.pkg.dev/cloudrun/container/hello \
  --allow-unauthenticated \
  --set-env-vars=VERSION=v1

2 つ目を、トラフィックを流さずに canary のタグ付きで出します。タグ専用の URL で動作を確かめられます。

gcloud run deploy hello \
  --image=us-docker.pkg.dev/cloudrun/container/hello \
  --set-env-vars=VERSION=v2 \
  --no-traffic --tag=canary

canary に 10% だけ流し、割合を確かめます。

gcloud run services update-traffic hello --to-tags=canary=10
gcloud run services describe hello --format="yaml(status.traffic)"

問題があった想定で全量を 1 つ目に戻します。hello-00001-xxx は revisions list に出た名前に置き換えます。問題がなければ、代わりに --to-latest で新しいリビジョンに全量を流します。

gcloud run revisions list --service=hello
gcloud run services update-traffic hello --to-revisions=hello-00001-xxx=100

後片付けです。

gcloud run services delete hello --quiet

試験で問われる判断

このカリキュラムで作った例です。

「開発者が本番のファイアウォールルールをコンソールで変えて障害が起きた」なら、ルールを Terraform で管理して変更をパイプライン経由に限り、本番での開発者の編集権限を外します。手順書やレビュー会議を増やす選択肢は人の注意に頼ります。

「リリース後にエラー率が上がることがある。影響を受けるユーザーを最小にしたい」ならカナリアです。

「Pub/Sub を使うアプリの単体テストを CI で毎回走らせたいが、本物のトピックは作りたくない」なら Pub/Sub エミュレータです。

理解度チェック

答えを開く前に、自分で考えてください。結果はこのブラウザにだけ残り、間違えた問題は復習のページでまとめて解き直せます。

思い出す

Terraform の state ファイルは、各自の PC ではなくどこに置きますか。そこに置くのはなぜですか。

状況で選ぶ

Cloud Run で動かしている EC サイトで、リリースのあとにエラー率が上がることがときどきあります。新版で問題が起きたときに、エラーを受ける利用者をできるだけ少なくしたいと考えています。新版のエラー率は Cloud Monitoring で見られます。どの出し方を選びますか。

説明する

試験で「手順書どおりにコンソールで作る」と「Terraform で定義してパイプラインから適用する」が並んだら、後者を選ぶのはなぜですか。