🎯 Deep Dive — Cloud Load Balancing 運用 / 事故 / コスト / SRE

本番運用で踏むパターン、コスト構造、肥大化、SRE が必ず設定すべきアラートを集約。LB は「動いて当たり前」と思われがちですが、設計次第で レイテンシ・コスト・障害伝播 が劇的に変わります。

🚨 重大事故ケース 10 件

#1 「Global LB なのに 1 リージョン障害で全断」 — Single Region Backend

状況: Global External Application LB を採用したが、backend MIG が asia-northeast1 のみ。当該リージョン障害で全リクエストが backend_connection_closed_before_data_sent_to_backend でエラー。

原因: Global LB の 「グローバル冗長」とは、フロントエンド(Anycast IP/エッジ) であってバックエンドではない という勘違い。

影響: SLA 計算上は GCP の "regional zonal outage" だが、ビジネスは全停止 (RTO/RPO 違反)。

復旧: 緊急で別リージョンに MIG を作り backend service に追加。LB は自動でフェイルオーバー。

再発防止:

  • Global LB の backend は 必ず 2 リージョン以上に分散
  • backend service の locality_lb_policyWATERFALL_BY_REGION 等で fail-open 設定
  • Connectivity Tests を CI で実行し、リージョン障害シミュレーション

#2 「ヘルスチェックは Green、実トラフィックは 502」 — HC と実 path の乖離

状況: Application LB のヘルスチェックは /healthz で 200。しかし /api/v1/order へのリクエストは 502 Bad Gateway。

原因: HC エンドポイントは軽量で常に 200 を返すが、実 endpoint は DB 接続切れで失敗。HC は LB ↔ backend の到達性のみを検証するため、アプリ層の半分壊れ (broken middleware) を検出できない。

影響: ロード分散がガラガラの backend にも流れ続け、502 が急増。

復旧: HC を /healthz/deep に切替え、DB ping を含める。circuit breaker (envoyfilter) で半壊 backend を即遮断。

再発防止:

  • 「HC は本物の依存チェーン (DB, キャッシュ, 外部 API) を含める」
  • Outlier detection を backend service で有効化 (連続 5xx で eject)
  • SLO アラート: backend_5xx_rate > 1% で 5 分以内通知

#3 「Cloud Armor で本物のユーザを大量に block」 — preconfigured WAF の False Positive

状況: Cloud Armor を有効化した翌朝、ログイン成功率が 60% → 12%に急落。Cloud Armor ログを見ると sqli-stable ルールが大量ヒット。

原因: ユーザ生成データ (パスワードリセットメール本文等) に SQL キーワード SELECT, OR 1=1 が含まれ、preconfigured rule (Sensitivity 4) が誤検知。

影響: 数時間で売上 1500 万円の損失、サポート問い合わせ急増。

復旧: Sensitivity を 4 → 2 に下げる + 当該 URL path を例外化 (request.path.matches('/account/.*'))。preview mode で 7 日間運転して評価する手順に。

再発防止:

  • WAF ルールは 必ず preview mode (--preview) で 7-14 日 観察してから enforce
  • Cloud Armor Adaptive Protection の "suggested rules" を活用
  • 誤検知率 (false positive %) を SLO に組み込む

#4 「Backend Connection Pool 枯渇で random 502」 — max_connections_per_endpoint 設定ミス

状況: Application LB の backend MIG (10 VMs) が、ピーク時 30% のリクエストで 502。各 VM の CPU は 40%、メモリは 50%。

原因: backend service の max_connections_per_endpoint=100 がデフォルト。実 RPS は VM あたり 600。connection pool 枯渇で LB が即 502 を返した。

影響: ピーク 1 時間で error budget の 4 週間分を一晩で消費。

復旧: max_connections_per_endpoint を 800 に拡張、balancing_mode=RATE + max_rate_per_endpoint=500 に変更。

再発防止:

  • backend の balancing_mode と max_* の組み合わせを必ず本番ロード試験で検証
  • キャパシティ planning: VM 数 × max_rate_per_endpoint = ピーク RPS × 1.5
  • Cloud Monitoring metric: backend_utilization > 80% でアラート

#5 「Global LB の TLS 証明書 expire で全断」 — Managed Cert の DNS 設定漏れ

状況: Google-managed SSL certificate を採用したが、ドメインの DNS A record が古い IP を指したまま。証明書のリフレッシュ時に Domain Validation (HTTP-01) が失敗、再発行されず期限切れ。

原因: Managed certificate は再発行時に ターゲットドメインが LB の VIP を解決できることが必須。DNS が古いと失敗する。

影響: 朝 6 時から HTTPS でアクセス不可、ユーザは TLS 警告画面。

復旧: DNS を修正 + 手動で managed cert 再発行コマンド。

再発防止:

  • Certificate Manager に切替え、複数ドメインを一元管理
  • Cloud Monitoring の certmanager.googleapis.com/certificate/expiration_seconds を 30/14/7 日でアラート
  • DNS と LB のリンケージを Terraform で管理し、drift detection

#6 「Cloud CDN cache poisoning」 — Vary ヘッダ忘れで全ユーザに同じ private データ配信

状況: 認証済みユーザ向けに個別 dashboard を返す API を Cloud CDN 配下に。ある日「他人のデータが表示される」苦情多発。

原因: Backend が Cache-Control: public, max-age=3600 を返し、しかも Vary: Authorization が無かった。CDN が最初の応答 (ユーザ A のデータ) を全ユーザに配信。

影響: 個人情報漏洩、GDPR/個人情報保護法インシデント、IR レポート 30 ページ。

復旧: 緊急 cache invalidation (全パス) + Backend で Cache-Control: private, no-store 強制。

再発防止:

  • Cloud CDN を有効化するときは キャッシュキー設計を必ずレビュー (include_query_string, include_protocol, include_host, include_named_cookies)
  • 個人化レスポンスは private + no-store
  • CDN は 静的アセットのみに絞るのが安全

#7 「Internal Passthrough LB の next-hop で 非対称ルーティング」 — Source NAT 忘れ

状況: NVA (multi-NIC) の前段に Internal Passthrough LB を置き next-hop-ilb 指定。VM → NVA → DB の往路は通るが、復路 (DB → NVA → VM) が NVA を経由せず直接 VM に返り、TCP セッション切断。

原因: Passthrough LB は 送信元 IP を保持するため、DB は VM の IP を見て直接返す。NVA が non-stateful なら大丈夫だが、stateful FW として動かしているとセッション table mismatch で drop。

影響: HTTPS が時々切れる、TCP RST の嵐。

復旧: NVA で SNAT 有効化 (egress を NVA IP に書き換え)。または対称ルーティング設計 (DB 側からも next-hop-ilb 経由)。

再発防止:

  • Passthrough LB を NVA next-hop に使う設計では 必ず対称経路を設計する
  • VPC Flow Logs の connection.tcp.flags で非対称検出
  • NVA を Active/Passive にし、対称ルーティングをシンプル化

#8 「LB の 5xx 急増は backend ではなく target_proxy の MaxStreams」 — gRPC で発生

状況: gRPC で運用していたサービスで、Application LB から upstream_max_stream_duration_reached エラーが多発。

原因: HTTP/2 の SETTINGS_MAX_CONCURRENT_STREAMS がデフォルト 100。長時間ストリーミング gRPC で枯渇。

影響: Stream error で SLO 違反、SRE が backend を疑って3時間ロス。

復旧: backend service の max_stream_duration を伸ばし、connection を 5 分ごとに再生成する設計に。

再発防止:

  • gRPC streaming は 必ず timeout/retry/keep-alive を明示
  • Application LB の HTTP/2 backend service オプションを確認
  • 監視: https/backend_connection/closed_after_partial_response を SLI に

#9 「External Passthrough NLB の anycast IP が突然到達不可」 — Network Tier 設定ミス

状況: External Passthrough NLB を構築。Test 環境では動いていたが、本番化後にアジア圏のユーザだけ到達不可。

原因: Network Tier を STANDARD で作成したため、Anycast ではなく リージョン限定 (us-central1) の IP。アジアユーザは Public Internet 経由でレイテンシ + パケロス。

影響: p99 latency が 100ms → 800ms、SLO 違反。

復旧: Premium Tier で再作成 (IP も変わるため DNS TTL 短縮の事前準備が必要)。

再発防止:

  • "グローバル" 要件があれば Premium Tier 必須を IaC で強制
  • Cloud Monitoring の https/latencies を地域別に export
  • Synthetic Monitor (uptime check) を 5 リージョンから走らせる

#10 「Serverless NEG で Cloud Run に大量 502」 — Cloud Run の concurrency 上限

状況: Application LB + Serverless NEG (Cloud Run) 構成。ピーク時に LB が 502 を返す。Cloud Run のメトリクスは concurrency 80, CPU 50%。

原因: Cloud Run の max_instances がデフォルト 100、concurrency=80 のため、最大 8000 リクエスト/秒。これを超えると 429 を返し、LB が 502 に変換。

影響: エラー率 8%、20 分間継続。

復旧: max_instances=500 に緩和、min_instances=10 で cold start 削減。

再発防止:

  • Cloud Run の max_instances を必ず明示設定 (default のままにしない)
  • Application LB の "5xx" だけでなく Cloud Run の request_count{response_code_class="4xx"} も SLI に
  • 負荷試験で min/max instances の限界点を測定

💰 Cloud Load Balancing のコスト構造

LB は「データ転送 + ルールデータ処理 + 転送料」の 3 階建て。サービスを跨ぐ請求項目で混乱が生まれやすいので、メンタルモデルを固める。

項目単位目安単価 (us, 2026 想定)注意点
Forwarding rule (External, first 5)per hour$0.025/hour ($18/月) × N5 rule 超過分は per-rule で増加
Inbound data processingper GB$0.008 - $0.012/GBbackend へ送られるデータ全量
Network Egress (Internet)per GB地域差 $0.08〜$0.23/GBPremium Tier で高、Standard Tier で安
Cloud Armor (per policy)per policy + per request$5/policy/月 + $0.75/1M reqManaged protection plus は別料金 (org 単位 $3000/月〜)
Cloud CDN cache fillper GB (egress to cache)$0.04 - $0.20/GBcache miss 多いと無駄高 (high cache hit ratio が重要)
SSL Cert (Managed)無料$0Certificate Manager の数量上限に注意
頻出ミス: 「LB 料金が高い」と感じる場合の 8 割は egress (network) 料金。LB 自体ではなく外向き転送量。

典型的なコスト内訳 (中規模 SaaS, 月100TB egress)

Forwarding rule × 3                              $54
Data processing (300TB inbound)                  $2,400
Egress (100TB Premium Tier, mixed regions)       $11,000  ← 81%
Cloud Armor (1 policy, 500M req)                 $380
Cloud CDN (60TB cache egress)                    $4,800
SSL cert (managed, 5 ドメイン)                   $0
─────────────────────────────────────────────────
合計                                              ~$18,634/月

📈 コスト肥大化パターン 6 種

P1

不要 Forwarding rule の積み残し

過去の A/B test や、削除予定のサービスの rule が残存。月$18 × 30個 = $540 を払い続ける。「使われていない rule」検出は手動でしか無理。

対策: Network Analyzer の "Unused resources" を月次で確認、Tags で owner を付与し orphan を排除。

P2

Egress を Premium Tier のまま放置

内部バッチ (BigQuery export 等) の egress も Premium で出ている。Standard Tier なら 30-50% コスト減。

対策: 内部バッチは Standard Tier LB or PSC 経由に。compute.googleapis.com/network_tier を Org Policy で強制も可。

P3

Cloud CDN cache hit ratio 低下

URL パラメータ (e.g., ?ts=...) や Vary ヘッダの過剰使用で cache miss が 80% 超。cache fill ばかり走り、CDN コストが直接配信より高くつく。

対策: cache key 設計を見直し、include_query_string=false に。Cloud Logging で jsonPayload.cacheStatus 分析。

P4

Inter-region traffic の見落とし

Global LB 採用で「ユーザは最寄りリージョンに行く」と思ったら、実は backend が us-central1 しか無く、東京ユーザのレイテンシ + リージョン間 egress (これも課金) が大量発生。

対策: backend を地理分散 + locality_lb_policy 設定 + preferred_backend 設定。

P5

Cloud Armor の preview mode 放置

WAF を preview で運用して enforce せず、誤検知だけログに溜まり、Logging コストが月 $5000 に。Cloud Armor 自体の rule cost も増。

対策: preview は 14 日でリミット、不採用ルールは削除。Logging の sampling rate 設定。

P6

SSL 証明書の野良増殖

テスト用に作った Google-managed 証明書が 200個。Cert Manager の上限に当たり、本番 cert 発行できない事故も。

対策: Certificate Manager で集約管理、Terraform で lifecycle 制御、未使用 cert は 30 日で削除。

🚀 最適化テクニック 10 選

  1. Network Tier の使い分け: ユーザ向けは Premium、内部バッチ・ログ転送は Standard で 30-50% カット。
  2. Cloud CDN を貪欲に: 静的アセット (画像/JS/CSS) は cache hit ratio 95%+ を SLO に。HTML はカスタムキャッシュキー設計で。
  3. Negative caching: 404/503 のキャッシュも有効化、backend を守る (5xx storm 対策)。
  4. Container-native LB (Standalone NEG): GKE で kube-proxy を bypass、レイテンシ -30%、conntrack 枯渇を回避。
  5. Outlier detection: backend service で consecutive_errors=5, interval=30s 設定で半壊 backend を eject。
  6. Circuit breaker: max_connections / max_pending_requests / max_requests / max_retries を明示、cascading failure を抑制。
  7. HTTP/3 (QUIC) 有効化: Application LB で QUIC 有効、mobile ユーザの p95 改善。
  8. Connection draining: connectionDraining.drainingTimeoutSec=300 を明示、デプロイ時の 502 を撲滅。
  9. Anycast IP の固定: Premium Tier 前提で global IP を予約、DNS への影響を最小化。
  10. Adaptive Protection auto-deploy: ML 提案ルールを preview → enforce パイプラインで自動化、DDoS 対応を 5 分以内に。

🔔 監視アラート設計 (Cloud Monitoring)

SLI (Service Level Indicator) 定義

SLI定義SLO 目安
Availability2xx-3xx / (2xx-3xx + 5xx)99.95%
Latency (p99)backend_latencies (request_method=GET)< 500ms
Saturationbackend_utilization (mean)< 70%
Error budget burn rate(1 - availability) / (1 - SLO)1x baseline

Multi-window multi-burn-rate alert (推奨)

# Fast burn: 1時間で 月予算の 2% を消費
- burn_rate >= 14.4 over 1h AND 5m   → PagerDuty Page (Sev2)

# Medium burn: 6時間で 月予算の 5% を消費
- burn_rate >= 6   over 6h AND 30m   → Slack #network-sre (Sev3)

# Slow burn: 3日で 月予算の 10% を消費
- burn_rate >= 1   over 3d AND 6h    → Issue 起票 (Sev4)

必須アラート 10 件

シグナルメトリック閾値
5xx bursthttps/request_count{response_code_class="500"}> 1% for 5m
p99 latencyhttps/backend_latencies> 1s for 10m
backend utilizationhttps/backend_request_count / target_size> 85% for 5m
HC failurebackend_health/unhealthy_count>= 1 for 2m
SSL cert expirycertmanager.googleapis.com/.../expiration_seconds< 30 days
Cloud Armor block ratearmor.googleapis.com/.../denied_requests> 2× baseline
CDN hit ratio drophttps/frontend_tcp_rtt + cache hit metric< 80% for 30m
QUIC handshake failurehttps/frontend_tcp_rtt> 200ms p99 for 10m
Forwarding rule countresource countquota 80%
Connection dropshttps/backend_connection_closed_before_data_sent_to_backend> 0.1% for 5m

📖 Runbook: 「LB で 5xx 急増」 1 ページ対応フロー

1. Cloud Monitoring で対象 backend service を特定 (3 min)
2. Network Topology / Connectivity Tests で backend 到達性確認 (5 min)
3. Cloud Logging で 5xx の "statusDetails" を分析:
   - backend_connection_closed_before_data_sent_to_backend → backend down
   - response_sent_by_backend → backend がエラーを返している
   - backend_timeout → backend が遅い (scale up / HC 確認)
   - failed_to_pick_backend → HC 全滅 (firewall? backend service config?)
4. 並行して Cloud Armor logs に "denied" 急増がないか確認 (WAF FP の可能性)
5. 緊急対処:
   - 全 backend HC 失敗 → backend 再起動 or LB の HC 検証 endpoint 確認
   - 特定 backend のみ → backend を drain (capacity_scaler=0 で一時退去)
   - WAF FP → 該当 rule を preview mode に戻す
6. Post-mortem:
   - 障害時間、エラー予算消費、根本原因、再発防止策をテンプレに沿って