PCD 合格対策

セクション2:アプリケーションの構築とテスト

公式試験ガイド 042426版 — Section 2: Building and testing applications

23%
出題比重
3
サブトピック
~12問
想定問数
🆕大幅追加
2026改訂
🎯 このセクションの核心 2026年4月改訂で AI 駆動開発トピックが大量追加されたセクション。Gemini Cloud Assist / Cloud Workstations / Cloud Code / AI コーディングアシスタント / MCP サーバー が新規キーワード。 Cloud Build → Artifact Registry → Binary Authorization の サプライチェーンセキュリティパイプラインを完全に理解しているかが問われる。

2.1 開発環境のセットアップ

3つの「開発する場所」と特徴比較

ローカル PC + gcloud CLI + Docker + IDE ✓ フル制御 ✓ 環境固定 ✗ 環境差異 ✗ 持出リスク Cloud Shell ブラウザ Terminal 5GB 永続ホーム プリインストール済 ✓ 無料・即起動 ✓ 出先利用 ✗ 週50h 制限 ✗ 20分 idle 切断 Cloud Workstations 🆕 マネージド開発環境 VSCode / IntelliJ ブラウザ 永続 PD / 企業ポリシー強制 ✓ Configuration テンプレ化 ✓ Gemini Code Assist 統合 ✓ VPC 内・データ持出禁 ✗ VM 起動コスト
図1: 3つの開発環境の比較。左から「フル制御だがバラバラ」「お手軽だが制限あり」「マネージド + 企業ポリシー強制」。

Cloud Workstations 深掘り(2026改訂で重要)

2026年改訂で 新規追加された頻出トピック。「企業の標準開発環境を強制する」シナリオで定番解答。

3層構造

Workstation Cluster VPC / リージョン / Private Service Connect Workstation Configuration: python-ml image=python-3.11 + Jupyter, machine=e2-standard-8 PD=200GB, idle=2h, running=8h alice $ vscode PD: 200GB bob $ vscode PD: 200GB stopped PD 保持 Workstation Configuration: go-backend image=go-1.22 + protoc, machine=n2-standard-4 PD=100GB, idle=2h carol $ jetbrains dave $ vscode
図2: Workstation Cluster 内に複数の Configuration(言語別テンプレ)、各 Configuration に複数の Workstation インスタンス(開発者個別)。

3層リソースの役割

レイヤー定義する内容誰が管理
ClusterVPC ネットワーク、リージョン、Private Service Connect 設定セキュリティ / プラットフォーム管理者
ConfigurationOS イメージ(Code OSS / VSCode / IntelliJ ベース)、マシンタイプ、永続ボリュームサイズ、idle/running timeout、起動スクリプトプラットフォーム管理者 / リード
Workstation個別の開発者インスタンス。Configuration から作成され、個別の永続ホームを持つ開発者本人

サポートされる IDE

企業導入のメリット
  1. 環境統一: 「俺の環境で動く」問題が解消(OS / バージョン / 拡張)
  2. セキュリティ: VPC 内でのみ動作、ソース持出禁止、IAM 制御
  3. オンボーディング: 新人が初日からフル環境で作業開始
  4. Gemini Code Assist 統合: AI コード補完が標準で利用可能
  5. スケール: 大規模リポジトリのインデックス・ビルドをローカル PC より高速
Cloud Shell との混同を避ける
Cloud ShellCloud Workstations
用途軽い検証・出先・スキマ時間本格的な日常開発
コスト無料VM 起動時間で課金
制限週50h、20分idleで切断idle/running timeout は管理者が設定
カスタマイズ限定的Configuration で完全カスタム
企業ポリシー強制限定的VPC SC・IAM で強制
公式リファレンス Cloud Workstations overview / Cloud Shell

🆕 Gemini Cloud Assist 深掘り(2026改訂)

2026改訂で明示的にシラバスに加わった AI アシスタント。GCP コンソール、Cloud Code、Cloud Workstations の各所で動作。

🧠 コード生成・修正

「Pub/Sub に publish する Python 関数を書いて」「このコードをリファクタして」 → 即生成・適用

📖 コード理解

選択コードを「説明して」「テスト書いて」「コメント追加して」

🔎 可観測性アシスト

自然言語から Cloud Logging クエリ生成、Cloud Trace の要約、Error Reporting の根本原因推定

⚙️ gcloud / kubectl コマンド提案

「Cloud Run を us-central1 にデプロイ、min-instances=1 で」 → コマンド生成

AI コード生成の注意点
  1. AI 生成コードを盲信しない: ハルシネーション(存在しない API / 引数)の可能性
  2. セキュリティレビュー必須: SQL インジェクション、XSS、シークレットの平文埋め込みなど
  3. ライセンス・コンプライアンス: 生成コードの著作権・特許リスクを社内ポリシーに従って確認
  4. テスト生成は雛形: AI が生成したテストは「エッジケース」をカバーしていないことが多い。人間が追加

🆕 MCP(Model Context Protocol)サーバー(2026改訂)

2026改訂で初出AI モデルが外部リソース(GitHub、DB、社内API)に接続する標準プロトコル。試験で名前を覚えていれば即答可能なトピック。

IDE + AI Tool VSCode + Cloud Code Gemini Code Assist MCP Protocol (JSON-RPC over stdio) MCP Server ツール定義 / リソース提供 - list_tools() - call_tool(name, args) - list_resources() - get_resource(uri) - list_prompts() - get_prompt(name) GitHub API BigQuery Cloud Logging 社内 DB / API
図3: MCP サーバーは AI と外部リソースの間に立つ「翻訳機」。AI ツールは MCP のインターフェイスだけ知っていれば、任意の外部リソースを利用できる。

MCP の概念

PCD 試験で覚えておくこと MCP は「AI が外部にアクセスする標準プロトコル」と一言で覚える。問題文に「AI ツールが社内 DB に安全にアクセス」「AI が GitHub を読む標準的な方法」とあれば MCP サーバーが答え。

gcloud エミュレータでローカル開発

本番 GCP に課金されずに、ローカルでテスト・開発するためのツール群。

サービス起動コマンド環境変数(クライアントが見る)
Pub/Subgcloud beta emulators pubsub start --host-port=localhost:8085PUBSUB_EMULATOR_HOST
Firestoregcloud emulators firestore start --host-port=localhost:8080FIRESTORE_EMULATOR_HOST
Bigtablegcloud beta emulators bigtable start --host-port=localhost:8086BIGTABLE_EMULATOR_HOST
Datastoregcloud beta emulators datastore startDATASTORE_EMULATOR_HOST
Spannergcloud emulators spanner startSPANNER_EMULATOR_HOST
# テストコード(Pub/Sub エミュレータ利用)
import os
os.environ["PUBSUB_EMULATOR_HOST"] = "localhost:8085"

from google.cloud import pubsub_v1
publisher = pubsub_v1.PublisherClient()  # 自動的にエミュレータに接続
topic_path = publisher.topic_path("test-project", "test-topic")
publisher.create_topic(request={"name": topic_path})
publisher.publish(topic_path, b"hello")
エミュレータの限界
  1. 本番との機能差異がある(例: Pub/Sub エミュレータは Ordering Keys / Exactly-once 未対応)
  2. パフォーマンス・スケール挙動は本物と異なる
  3. IAM / quota / billing はエミュレートされない
  4. 本番想定の統合テストは別途(Cloud Build 上で本物の Pub/Sub を使うテストプロジェクト等)必要

2.2 ビルド

Cloud Build YAML の構造

# cloudbuild.yaml の完全構造例
steps:
  # 各ステップは Docker コンテナで実行
  - id: 'lint'
    name: 'python:3.11'              # 実行するコンテナイメージ
    waitFor: ['-']                   # 並列実行(依存なし)
    entrypoint: 'bash'
    args: ['-c', 'pip install ruff && ruff check src/']

  - id: 'unit-test'
    name: 'python:3.11'
    waitFor: ['-']                   # lint と並列
    entrypoint: 'bash'
    args: ['-c', 'pip install -r requirements.txt pytest && pytest tests/']
    env:
      - 'CI=true'

  - id: 'build'
    name: 'gcr.io/cloud-builders/docker'
    waitFor: ['lint', 'unit-test']   # 両方を待つ
    args: ['build',
           '-t', 'us-central1-docker.pkg.dev/$PROJECT_ID/my-repo/app:$SHORT_SHA',
           '-t', 'us-central1-docker.pkg.dev/$PROJECT_ID/my-repo/app:latest',
           '.']

  - id: 'vuln-scan'
    name: 'gcr.io/cloud-builders/gcloud'
    waitFor: ['build']
    entrypoint: 'bash'
    args:
      - '-c'
      - |
        gcloud artifacts docker images scan \
          us-central1-docker.pkg.dev/$PROJECT_ID/my-repo/app:$SHORT_SHA \
          --format=json | tee /workspace/scan.json
        # HIGH/CRITICAL があれば失敗
        ! grep -E '"severity":\s*"(HIGH|CRITICAL)"' /workspace/scan.json

  - id: 'push'
    name: 'gcr.io/cloud-builders/docker'
    waitFor: ['vuln-scan']
    args: ['push', 'us-central1-docker.pkg.dev/$PROJECT_ID/my-repo/app:$SHORT_SHA']

  - id: 'deploy'
    name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: 'gcloud'
    args: ['run', 'deploy', 'my-app',
           '--image', 'us-central1-docker.pkg.dev/$PROJECT_ID/my-repo/app:$SHORT_SHA',
           '--region', 'us-central1',
           '--no-traffic',
           '--tag', 'canary']

# images で push 対象を宣言(自動 push + provenance 生成)
images:
  - 'us-central1-docker.pkg.dev/$PROJECT_ID/my-repo/app:$SHORT_SHA'

# シークレットの宣言
availableSecrets:
  secretManager:
    - versionName: projects/$PROJECT_ID/secrets/SLACK_WEBHOOK/versions/latest
      env: 'SLACK_WEBHOOK'

# ビルドオプション
options:
  machineType: 'E2_HIGHCPU_8'        # 高速ビルド用マシン
  logging: CLOUD_LOGGING_ONLY
  substitution_option: ALLOW_LOOSE

# Substitutions(自動定義 + カスタム)
substitutions:
  _REGION: 'us-central1'
  _ENVIRONMENT: 'staging'

# タイムアウト(デフォルト 10分、最大 24時間)
timeout: '1200s'

自動定義される Substitutions

変数意味
$PROJECT_IDプロジェクト ID
$PROJECT_NUMBERプロジェクト番号(数字)
$BUILD_IDビルドの UUID
$SHORT_SHAコミット SHA の最初の 7文字
$REVISION_ID完全なコミット SHA
$BRANCH_NAMEブランチ名
$TAG_NAMEタグ名
$REPO_NAMEリポジトリ名
$_カスタム名ユーザー定義(必ず _ で始まる)

ビルド時間短縮の5つの戦略(公式推奨)

① マシンタイプを強化

options:
  machineType: 'E2_HIGHCPU_8'   # 8 vCPU 8GB(デフォルト e2-medium の 4倍)
  # 選択肢: E2_HIGHCPU_8 / E2_HIGHCPU_32 / N1_HIGHCPU_8 / N1_HIGHCPU_32
  • デフォルトは e2-medium(1 vCPU、4GB)— 並列ビルドに不向き
  • マシンタイプを E2_HIGHCPU_8 以上にすると Docker レイヤビルドが大幅高速化
  • 料金は時間単位で課金されるが、マシン強化で短時間化 = 結果的に安くなることも多い

② Docker レイヤキャッシュ(--cache-from)

steps:
  # 既存イメージを pull(キャッシュ用)
  - name: 'gcr.io/cloud-builders/docker'
    entrypoint: 'bash'
    args: ['-c', 'docker pull IMAGE:latest || exit 0']

  # cache-from を使ってビルド
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build',
           '--cache-from', 'IMAGE:latest',
           '-t', 'IMAGE:$SHORT_SHA',
           '-t', 'IMAGE:latest',
           '.']
注意 Dockerfile の早い段階のレイヤを変更するとキャッシュが効かない。頻繁に変わるファイル(ソースコード)は Dockerfile の最後の方に COPY する。依存パッケージは早い段階で COPY/RUN。

③ GCS キャッシュ(Docker 以外も対応)

steps:
  # キャッシュ復元
  - name: 'gcr.io/cloud-builders/gsutil'
    args: ['-m', 'cp', '-r', 'gs://cache-bucket/pip-cache', '/workspace/.cache']
    waitFor: ['-']

  # ビルド(キャッシュを使う)
  - name: 'python:3.11'
    entrypoint: 'bash'
    args: ['-c', 'pip install --cache-dir=/workspace/.cache/pip -r requirements.txt']

  # キャッシュ保存
  - name: 'gcr.io/cloud-builders/gsutil'
    args: ['-m', 'cp', '-r', '/workspace/.cache', 'gs://cache-bucket/']

Python の pip、Node.js の npm、Maven の ~/.m2 など、すべて GCS にキャッシュ可。

④ 並列ステップ(waitFor: ['-'])

waitFor: ['-'] は「依存なし、即座に並列開始」を意味する。

並列なし(順次実行)— 12分 lint 2m unit-test 4m build 3m deploy 3m 並列あり(waitFor)— 7分(42% 短縮) lint 2m unit-test 4m (並列) build 3m deploy 3m

⑤ .gcloudignore でアップロードサイズ削減

# .gcloudignore(gitignore と同様の構文)
.git
.github
*.md
docs/
node_modules/
__pycache__/
*.pyc
dist/
build/
vendor/
.env*

Cloud Build はソースを ZIP して GCS にアップロード → ビルダーに転送する。アップロード対象を絞ると転送時間とコストの両方が短縮される。

公式リファレンス Speeding up Cloud Build

Cloud Build でのシークレット利用

# cloudbuild.yaml
availableSecrets:
  secretManager:
    - versionName: projects/$PROJECT_ID/secrets/SLACK_WEBHOOK/versions/latest
      env: 'SLACK_WEBHOOK'      # この名前で参照される環境変数

steps:
  - name: 'gcr.io/cloud-builders/curl'
    entrypoint: 'bash'
    secretEnv: ['SLACK_WEBHOOK']        # step ごとに参照を宣言
    args:
      - '-c'
      - |
        curl -X POST -H 'Content-Type: application/json' \
          -d "{\"text\":\"Build succeeded: $SHORT_SHA\"}" \
          "$$SLACK_WEBHOOK"            # $$ で参照($ は substitution と衝突)
Cloud Build シークレットの落とし穴
  1. $VAR$$VAR の混同: substitution は $VAR、シークレットは $$VAR
  2. args フィールドでのみ参照可: env フィールドや name フィールドでは直接使えない
  3. 非 UTF-8 バイナリは直接利用不可: ファイルに保存してから読む(base64 デコード)
  4. Cloud Build サービスアカウントに権限が必要: roles/secretmanager.secretAccessor を Cloud Build SA に付与
  5. レガシー Cloud Build SA への付与は危険: そのプロジェクトのトリガーを使える全ユーザーがアクセス可能になる。専用 SA + 細粒度 IAM を推奨
公式リファレンス Using secrets in Cloud Build

Artifact Registry 深掘り

Container Registry (gcr.io) の後継。新規プロジェクトでは必須選択。

サポートする形式(フォーマット)

Docker

OCI 互換のコンテナイメージ。最も使われる。

Maven

Java の Maven リポジトリ。社内 jar の共有。

npm

Node.js パッケージ。

Python

PyPI 互換、社内 wheel/tarball 共有。

apt / yum / RPM

OS パッケージリポジトリ。

Go modules

Go の go.mod 用プロキシ。

Helm

Kubernetes Helm チャート。

Generic(汎用)

任意のバイナリアーティファクト。

Container Registry との違い

項目Container Registry (gcr.io)Artifact Registry
形式Docker のみDocker / Maven / npm / Python / apt / Go / Helm / Generic
権限GCS バケットレベルリポジトリレベル(IAM 細粒度)
リージョンマルチリージョン強制リージョン選択可
CMEK非対応対応
VPC SC限定完全対応
脆弱性スキャン対応対応(Artifact Analysis)
状態非推奨(deprecated)推奨

リポジトリ作成

# Docker リポジトリの作成
gcloud artifacts repositories create my-app \
  --repository-format=docker \
  --location=us-central1 \
  --description="Production app images" \
  --kms-key=projects/$PROJECT_ID/locations/us-central1/keyRings/binauthz/cryptoKeys/registry-cmek

# Docker 認証設定
gcloud auth configure-docker us-central1-docker.pkg.dev

# Push
docker push us-central1-docker.pkg.dev/$PROJECT_ID/my-app/image:v1
リージョン戦略
  1. デプロイ先と同じリージョンにリポジトリを置く(pull の latency 削減)
  2. マルチリージョン展開なら 各リージョンにリポジトリを作成し、Cloud Build で全リージョンに push
  3. 環境別(dev/staging/prod)に別リポジトリを作り、IAM で権限分離

Buildpacks による Dockerfile 不要のビルド

Cloud Native Buildpacks をベースにした、ソースコードからコンテナを自動生成する仕組み。

# ソースから直接 Cloud Run へ
gcloud run deploy my-service --source . --region us-central1
# 内部で起きること:
# 1. ソースを ZIP して GCS にアップ
# 2. Cloud Build が起動
# 3. Buildpacks が言語を自動検出(requirements.txt → Python、package.json → Node.js)
# 4. セキュリティパッチ済みベースイメージを選択
# 5. アプリ依存をインストール、最小イメージ生成
# 6. Artifact Registry に push
# 7. Cloud Run にデプロイ
# 8. HTTPS URL を返却

サポートされる言語

⚠️ Buildpacks の制約

  • カスタマイズが Dockerfile より制限
  • OS パッケージ追加には project.toml 等の工夫が必要
  • 特殊な C 拡張のビルドは Dockerfile の方が確実

2.3 テスト

テストピラミッド(Cloud Build 上の実装)

E2E 少数 / 遅い 統合テスト 中数 / 中速 / サービス間 ユニットテスト 多数 / 速い / エミュレータ活用 本物 staging docker-compose pytest / Jest
図4: テストピラミッド。下層ほど数が多く速く、上層ほど少なく遅い。

ユニットテスト

  • 純関数 / クラス単体のテスト
  • 外部依存はモックまたはエミュレータ
  • Cloud Build の早い段階で実行(fail-fast)

統合テスト

  • 複数モジュール / サブシステムを連結
  • Cloud Build 内で docker-compose または docker run で DB を立てる
  • 本物の Pub/Sub テストプロジェクトを使うパターンも

E2E テスト

  • 本物の staging 環境を相手に HTTP で叩く
  • 少数の重要シナリオのみ(ログイン → 注文 → 決済)
  • Cloud Build の後段、デプロイ後に実行

AI コーディングアシスタントを使ったテスト生成

# ユニットテストの雛形を AI に生成させ、人間がエッジケースを補完するパターン

# AI に「order_service.py のテストを書いて」と指示すると…
def test_create_order_success():
    order = create_order(user_id="u1", items=[("p1", 2)])
    assert order.status == "PENDING"
    assert order.total == 200

def test_create_order_empty_items_raises():
    with pytest.raises(ValueError):
        create_order(user_id="u1", items=[])

# 人間がエッジケースを追加(AI が見落としがち)
def test_create_order_negative_quantity_raises():
    with pytest.raises(ValueError):
        create_order(user_id="u1", items=[("p1", -1)])

def test_create_order_inventory_exhausted():
    # 在庫切れシナリオは AI が見落としがち
    with pytest.raises(InventoryError):
        create_order(user_id="u1", items=[("out_of_stock_item", 1)])

サプライチェーンセキュリティ(SLSA)

Section 2 の仕上げトピック。Cloud Build → Artifact Registry → Binary Authorization の流れを完全に理解する。

SLSA レベルとは

SLSA = Supply chain Levels for Software Artifacts。サプライチェーンセキュリティの成熟度を 4段階で表現。

L0 何も保証しない(要件なし) L1 ビルドプロセスが定義済み、provenance 生成 L2 ホストされた CI(Cloud Build)、署名付き provenance L3 ⭐ Cloud Build ビルダー強化、非改ざん性保証 L4 2人承認、完全な再現性 SLSA レベル(高いほど厳密)
図5: SLSA レベルピラミッド。Cloud Build を使うと自動的に L3 相当の provenance が付与される。

Provenance(プロビナンス)とは

このイメージは誰が・どのソースから・どのビルダーで作ったか」のメタデータ証跡。改ざん検出と監査に使う。

{
  "_type": "https://in-toto.io/Statement/v1",
  "subject": [{
    "name": "us-central1-docker.pkg.dev/my-project/my-repo/app",
    "digest": {"sha256": "abc123..."}
  }],
  "predicateType": "https://slsa.dev/provenance/v1",
  "predicate": {
    "buildDefinition": {
      "buildType": "https://cloudbuild.googleapis.com/...",
      "externalParameters": {
        "sourceRepository": "https://github.com/my-org/my-repo",
        "sourceRevision": "abc1234567890"
      },
      "internalParameters": { "projectId": "my-project" },
      "resolvedDependencies": [...]
    },
    "runDetails": {
      "builder": { "id": "https://cloudbuild.googleapis.com/GoogleHostedWorker@v0.3" },
      "metadata": {
        "invocationId": "projects/.../builds/...",
        "startedOn": "2026-05-28T12:00:00Z",
        "finishedOn": "2026-05-28T12:03:42Z"
      }
    }
  }
}

Binary Authorization で provenance を検証

provenance を attestor の署名と組み合わせれば、デプロイ時に「本当に Cloud Build で・本当にこのリポジトリのこのコミットから作られたか」を検証できる。

Artifact Analysis(脆弱性スキャン)

# 手動スキャン
gcloud artifacts docker images scan IMAGE_URL

# Cloud Build 内で実行 + HIGH/CRITICAL があれば失敗
gcloud artifacts docker images scan IMAGE_URL --format=json | \
  python -c "
import json, sys
data = json.load(sys.stdin)
high_critical = [v for v in data['response']['scan']['discoveryOccurrence']['vulnerability']
                 if v['severity'] in ('HIGH', 'CRITICAL')]
if high_critical:
    print(f'Found {len(high_critical)} HIGH/CRITICAL vulnerabilities')
    sys.exit(1)
"
完全なサプライチェーンセキュアパイプライン
  1. Cloud Build: SLSA L3 provenance 自動生成
  2. Artifact Analysis: 脆弱性スキャン → HIGH/CRITICAL でビルド失敗
  3. Cloud KMS: attestor 用の署名鍵を CMEK で管理
  4. attestation 作成: ビルド成功時に Cloud Build で attestor 署名
  5. Binary Authorization: デプロイ時に attestation を検証
  6. Security Command Center: 全体の脅威を統合可視化
サプライチェーンの典型的アンチパターン
  1. :latest タグでデプロイ」 → ロールバック不能、provenance 追跡困難
  2. ローカル Docker で push」 → provenance 不在、信頼できない
  3. Container Registry を使い続ける」 → 非推奨、機能制限
  4. Binary Auth を ALWAYS_ALLOW で運用」 → 効果ゼロ。最低でも DRYRUN_AUDIT_LOG_ONLY で監査
  5. SA Key で Cloud Build を呼ぶ」 → SA Key 漏洩でサプライチェーン全体が崩壊

🚨 事故ケース集(postmortem 形式)

ビルド・テスト・サプライチェーンの脆弱性は 本番への侵入経路になります。Cloud Build / Artifact Registry / Binary Authorization / Cloud Workstations / Buildpacks で典型的に起きる事故パターンを紹介します。
CASE 2.1 Cloud Build SEV-CRITICAL

Cloud Build で echo $SECRET したらビルドログに平文露出 → ログ閲覧権限者全員が知り得る状態に

▼ 症状

セキュリティ監査でビルドログを抽出 → DB パスワード、サードパーティ API キーが平文で記録されていた。過去6ヶ月分のログに残存。

▼ 原因
  • デバッグ時に追加した echo "Connecting with $DB_PASSWORD" がそのまま残った
  • Cloud Build は secretEnv で渡したシークレット値はマスクするがecho で stdout に出力するとログに残る
  • ビルドログ閲覧権限(roles/cloudbuild.builds.viewer)を持つ多数の開発者がアクセス可能
▼ 影響

過去6ヶ月でログを閲覧した可能性のある社内 12名 + 外部委託 4名がシークレットを知り得た状態。全シークレットをローテーション + Cloud Audit Logs で閲覧履歴調査。

▼ 復旧手順
  1. 全シークレット即時ローテーション(DB パスワード、API キー、Webhook URL)
  2. 該当ビルドログを Log Bucket レベルで削除(retention policy 確認)
  3. Cloud Audit Logs で過去のログ閲覧履歴を調査
  4. Slack / Email で関係者に開示状況を共有
▼ 予防策
  • シークレットを絶対に echo / print しない。ステップ内で参照したら直接アプリに渡す
  • Lint ルールで echo \$SECRET パターン検知
  • Cloud Build の logging: CLOUD_LOGGING_ONLY で GCS への二重保存を防ぐ
  • ビルドログ閲覧権限は最小化、ローテーション
  • 機密データに対する DLP スキャナをログに適用
CASE 2.2 Artifact Registry / デプロイ運用 SEV-HIGH

:latest タグでデプロイ運用 → 障害時にロールバック不能、原因追跡も困難

▼ 症状

本番で 500 エラーが多発し始めたため、「前の安定版に戻したい」と判断。しかし Cloud Run が見ている my-app:latest が「現在の壊れた版」を指しているため、「前のバージョン」を特定できない。デプロイ履歴も :latest なので、どのコミットの版か分からない。

▼ 原因
  • Cloud Build で docker tag my-app:latest のみ作成、SHA タグなし
  • Cloud Run のデプロイで --image=my-app:latest 指定
  • 結果、Cloud Run リビジョンの履歴を見ても全部 my-app:latest で、どの SHA かわからない
  • Artifact Registry でも :latest常に最新を指す可動タグ。過去版は別タグがないと特定困難
▼ 影響

ロールバック判断から実施までに 40分(本来 1分)。SLA 違反 + 顧客苦情多数。

▼ 復旧手順
  1. Artifact Registry のイメージ履歴から、SHA digest と push 時刻で「前の版」を特定
  2. SHA digest 指定で Cloud Run にロールバック:gcloud run deploy --image=my-app@sha256:abc...
  3. 運用ルールを変更し、全ビルドで $SHORT_SHA タグを必須化
▼ 予防策
  • :latest タグでデプロイしない。必ず $SHORT_SHA やセマンティックバージョン
  • Cloud Run のロールバックは「リビジョン管理」で行う:gcloud run services update-traffic --to-revisions=PREVIOUS=100
  • Artifact Registry の retention policy で過去版を一定期間保持
  • Cloud Build でイメージにビルド時のメタデータ(コミット SHA、ブランチ、ビルド ID)をラベル付与
CASE 2.3 Binary Authorization SEV-CRITICAL

Binary Auth を本番でいきなり ENFORCED にしたら、未署名の既存イメージが軒並みデプロイ拒否

▼ 症状

Binary Authorization のポリシーを REQUIRE_ATTESTATION + ENFORCED_BLOCK_AND_AUDIT_LOG に変更したら、それ以降すべてのデプロイが拒否。緊急のホットフィックスもデプロイできなくなる。

▼ 原因
  • これまでの本番イメージには attestation 署名が一切なかった
  • 新ポリシーで「署名必須」にしたため、既存・新規問わず全イメージが拒否
  • 導入前のテスト(DRYRUN モード)を経ずに本番に適用
  • Cloud Build から attestation を作成する CI パイプラインも整備されていなかった
▼ 影響

デプロイ完全停止 2時間。緊急のセキュリティパッチ適用もできない状態に。CI/CD 系の整備に丸2日を追加で要した。

▼ 復旧手順
  1. 緊急で Binary Auth のポリシーを ALWAYS_ALLOW に戻し、デプロイを復活
  2. Cloud Build の YAML に gcloud container binauthz attestations sign-and-create ステップを追加
  3. テスト環境で DRYRUN_AUDIT_LOG_ONLY で検証 → すべて成功するまで待つ
  4. 本番に再展開(DRYRUN → ENFORCED は段階的に)
▼ 予防策
  • Binary Authorization 導入は必ず DRYRUN モードからenforcementMode: DRYRUN_AUDIT_LOG_ONLY
  • DRYRUN で監査ログを 1〜2 週間観察 → 違反ゼロを確認してから ENFORCED に
  • Cloud Build パイプラインに attestation 自動作成を組み込んでから有効化
  • break-glass 用の手順を事前に文書化(緊急時の bypass 方法)
CASE 2.4 Container Registry → Artifact Registry SEV-MEDIUM

Container Registry (gcr.io) を使い続けていたら EOL アナウンスでデプロイパイプライン全停止

▼ 症状

Container Registry の機能制限(pull/push の一部 API が deprecated)が発生し、Cloud Build パイプラインが軒並み失敗。Cloud Run も pull が遅延。

▼ 原因
  • Google が公式に「Container Registry を非推奨化、Artifact Registry に移行を推奨」と発表していたが、リソースを割けず先延ばし
  • Container Registry は内部的に GCS バケットを使う構造のため、機能拡張が制限
  • 機能制限のタイミングで運用パイプラインが影響を受ける
▼ 影響

緊急移行作業 1週間。CI/CD パイプライン、運用スクリプト、ドキュメントを全置換。Helm chart や Kubernetes manifest の image レジストリ URL も全更新。

▼ 復旧手順
  1. gcloud artifacts repositories create でリージョナルリポジトリ作成
  2. gcloud artifacts docker upgrade migrate で既存 gcr.io イメージを移行
  3. Cloud Build YAML / Kubernetes manifests のイメージ URL を us-central1-docker.pkg.dev/... に置換
  4. 段階的にデプロイ → 動作確認
▼ 予防策
  • GCP の公式 deprecation announcements を RSS / Slack 通知で受信
  • 「非推奨化したサービスを使い続けない」のテクニカルガバナンスポリシー
  • 新規プロジェクトでは必ず Artifact Registry
  • 定期的な技術スタックの monitor / refresh(年次の Tech Debt レビュー)
CASE 2.5 Artifact Analysis SEV-CRITICAL

Artifact Analysis の CRITICAL 警告を無視してデプロイ → 既知の脆弱性経由でサーバ侵入

▼ 症状

Cloud Run インスタンスから不審な外部通信(マイニング pool への接続)を検知。SCC でアラート発火。

▼ 原因
  • ベースイメージに含まれる古いライブラリに CVE-XXXX-XXXX(CRITICAL)あり
  • Artifact Analysis のスキャン結果でフラグが立っていたが、「動作には問題ない」と判断してデプロイ
  • その CVE は RCE(リモートコード実行)可能 → 攻撃者が侵入
  • 侵入後、マイニングプログラムをダウンロードして実行
▼ 影響

侵入されたインスタンスを介して他コンテナへの横展開を試みられた(VPC Firewall で防御済み)。フォレンジック調査 1週間。Cloud Run の請求が異常増加した期間の費用は不正利用申告で免除。

▼ 復旧手順
  1. 侵入されたリビジョンを即座にロールバック + 全インスタンス停止
  2. 脆弱なベースイメージ更新(最新セキュリティパッチ適用)
  3. Buildpacks 採用に切り替え、ベースイメージの自動更新を有効化
  4. SCC で侵入経路と横展開有無を確認
▼ 予防策
  • Cloud Build パイプラインで HIGH/CRITICAL 脆弱性があればビルド失敗 させる
  • Binary Authorization のポリシーで「脆弱性スキャン Pass」を必須化(vulnerability-attestor)
  • ベースイメージはセキュリティパッチが自動適用される Buildpacksを採用
  • 定期的なイメージ再ビルド(毎週 cron で同じソースから再ビルド → パッチ適用版が自動生成)
  • SCC で脆弱性アラートを Slack に通知し、72時間以内対応の SLO
CASE 2.6 Buildpacks SEV-MEDIUM

Buildpacks のベースイメージが自動更新 → C 拡張のバイナリ互換性が壊れて起動失敗

▼ 症状

Cloud Build は成功するが、Cloud Run へのデプロイ後にコンテナが起動直後にクラッシュ。Cloud Logging に ImportError: libpython3.x.so.1.0: undefined symbol

▼ 原因
  • Buildpacks がベースイメージを python:3.11-slim から python:3.12-slim に自動更新
  • pre-built C 拡張(numpy, pandas, psycopg2-binary)が Python 3.11 向けにビルドされていた
  • 3.12 で ABI 互換性なし → import 時にクラッシュ
▼ 影響

本番リリース 30分後にユーザー影響が顕在化、緊急ロールバック。リリース計画 2日延期。

▼ 復旧手順
  1. 前リビジョンに即時ロールバック
  2. runtime.txt または project.toml で Python バージョンを 3.11 にピン留め
  3. requirements.txt のバージョンも具体的に固定(numpy==1.26.4
  4. 3.12 移行用の別ブランチで時間をかけて検証
▼ 予防策
  • Buildpacks 利用時はランタイムバージョンを明示的にピン留め
  • 本番リリース前に staging で Buildpacks のビルド出力を検証
  • 言語バージョンの自動更新を許容する場合は、変更ログを Slack 通知
  • クリティカルな依存(C 拡張)は requirements.txt で厳密バージョン指定
🎯 セクション2 事故ケースの学び ビルドパイプラインの脆弱性は本番セキュリティの「最も外側の防御線」です。「シークレットがログに残る」「未署名イメージがデプロイされる」「脆弱性スキャンを無視」「latest タグ運用」が頻発する事故パターン。試験では「サプライチェーンセキュリティを強化する」「ロールバックを容易にする」設計選択が問われます。

セクション2 試験戦略まとめ

🎯 23%を確実に取るためのポイント
  1. Container Registry は非推奨、Artifact Registry が標準(最頻出の引っかけ)
  2. Cloud Shell / Cloud Workstations / Cloud Code の使い分け(特に企業ポリシー要件 → Workstations)
  3. 🆕 Gemini Cloud Assist / MCP / AI コーディングアシスタント の名前を確実に覚える
  4. Cloud Build シークレット = Secret Manager + availableSecrets + secretEnv + $$VAR
  5. 並列ステップ = waitFor: ['-']
  6. SLSA L3 = Cloud Build 標準、provenance + attestation + Binary Authorization の流れ
  7. Buildpacks = Dockerfile 不要、--source . でデプロイ
問題文のキーワードと正解
  • 新規プロジェクトでイメージリポジトリ」 → Artifact Registry
  • 企業の標準開発環境を強制」 → Cloud Workstations
  • AI が外部リソースに接続」 → MCP サーバー
  • 改ざんイメージのデプロイ阻止」 → Binary Authorization
  • ビルド証跡 / 真贋検証」 → provenance(SLSA L3)
  • Dockerfile を書かずデプロイ」 → gcloud run deploy --source .(Buildpacks)
  • Cloud Build でビルド時間短縮」 → マシン強化 + 並列 + キャッシュ + .gcloudignore
  • PR ごとに自動テスト」 → Cloud Build の Pull Request トリガー
📘 基礎 (MD) 🔧 応用 (MD) 🎯 要点と暗記 (MD)
← セクション1 セクション3 デプロイ →