プロダクションレベルのCI/CD、コンテナオーケストレーション、自動フェイルオーバーの実践ガイド
本番環境へのソフトウェアアップデートのデプロイは、本来何事もなく完了するごく普通のプロセスであるべきです。しかし現実には、モノリシックなサーバーの再起動、未処理のデータベースマイグレーション、不適切なロードバランシングによって、サービスの停止、WebSocket切断、502 Gateway Errorなどの障害が頻繁に発生しています。
真のゼロダウンタイムデプロイメント(無停止デプロイ)を実現するには、アプリケーション実行環境の分離、継続的デリバリー(CD)の自動化、そしてダウンタイムゼロのトラフィックルーティングの実装が不可欠です。以下に、Google Kubernetes Engine(GKE)、Artifact Registry、GitHub Actionsを活用し、Google Cloud Platform(GCP)上で本番運用に耐えうるDockerクラスタを構築するための設計ブループリントを示します。
ゼロダウンタイムデプロイメントのアーキテクチャ
flowchart TD
subgraph CI_CD["CI/CD パイプライン"]
GA["GitHub Actions"] -->|Workload Identity 認証| GAR["Artifact Registry"]
GA -->|イメージのビルド & プッシュ| GAR
GA -->|Rolling Update のトリガー| GKE_Master["GKE Control Plane"]
end
subgraph GCP_Cloud["GCP ネットワーク & クラスタ"]
LB["Cloud Load Balancing"]
subgraph GKE_Cluster["GKE Cluster - production"]
subgraph Active_Pods["稼働中の Pods (旧バージョン)"]
Pod1["Pod v1.0<br/>Readiness: 200 OK"]
Pod2["Pod v1.0<br/>Readiness: 200 OK"]
end
subgraph New_Pods["新規作成 Pods (新バージョン)"]
Pod3["Pod v1.1<br/>Readiness: 起動中/検証中"]
Pod4["Pod v1.1<br/>Readiness: 200 OK"]
end
end
end
Client["クライアント / トラフィック"] -->|HTTPS| LB
LB -->|100% のアクティブトラフィックをルーティング| Active_Pods
LB -.->|Readiness Pass 後に順次切り替え| Pod4
GKE_Master -->|preStop sleep 10s & SIGTERM| Active_Pods1. コンテナ化 ベストプラクティス (Dockerfile)
無停止デプロイはコンテナレイヤーの設計から始まります。コンテナは終了シグナル(SIGTERM)を適切にハンドリングし、プロセス終了前に実行中のアクティブなリクエスト処理を正常に完了させる必要があります。
# イメージサイズと攻撃表面(Attack Surface)を最小化するマルチステージビルドnFROM node:20-alpine AS buildernWORKDIR /appnCOPY package*.json ./nRUN npm cinCOPY . .nRUN npm run buildnnFROM node:20-alpine AS runnernWORKDIR /appnENV NODE_ENV=productionnn# クラウドセキュリティ標準に準拠した非rootユーザーでの実行nRUN addgroup u002du002dsystem u002du002dgid 1001 nodejs u0026u0026 adduser u002du002dsystem u002du002duid 1001 appusernCOPY u002du002dfrom=builder /app/dist ./distnCOPY u002du002dfrom=builder /app/node_modules ./node_modulesnCOPY package.json ./nnUSER appusernEXPOSE 3000nn# Node.jsにおけるSIGTERMシグナルのグレースフルハンドリングnCMD [u0022nodeu0022, u0022dist/server.jsu0022]2. Kubernetes デプロイメント設定 (deployment.yaml)
GCPが起動中または終了処理中のコンテナへトラフィックをルーティングするのを完全に防ぐため、Rolling Updates(ローリングアップデート)、Liveness Probes(生存性確認)、および Readiness Probes(準備完了確認) を設定します。
apiVersion: apps/v1nkind: Deploymentnmetadata:n name: isotope-backend-appn namespace: productionnspec:n replicas: 4n strategy:n type: RollingUpdaten rollingUpdate:n maxSurge: 25% # 古いPodを停止する前に、新しいPodを1つ作成n maxUnavailable: 0% # ローリングアウト中も100%の処理能力を維持n selector:n matchLabels:n app: isotope-backendn template:n metadata:n labels:n app: isotope-backendn spec:n containers:n - name: backend-apin image: us-central1-docker.pkg.dev/isotope-blue/app-repo/backend:latestn ports:n - containerPort: 3000n resources:n requests:n cpu: u0022250mu0022n memory: u0022512Miu0022n limits:n cpu: u0022500mu0022n memory: u00221024Miu0022n readinessProbe:n httpGet:n path: /healthzn port: 3000n initialDelaySeconds: 5n periodSeconds: 5n livenessProbe:n httpGet:n path: /healthzn port: 3000n initialDelaySeconds: 15n periodSeconds: 10n lifecycle:n preStop:n exec:n command: [u0022/bin/shu0022, u0022-cu0022, u0022sleep 10u0022] # ロードバランサがPodの規制登録を解除する猶予時間を確保3. CI/CD パイプラインの自動化 (GitHub Actions)
このパイプラインは、Dockerコンテナのビルド、Workload Identity Federationを使用した安全なGCP認証(静的なサービスアカウントキーの保持は不要)、およびGKEでのローリングデプロイの実行を自動化します。
name: Deploy Backend to GCP GKEnnon:n push:n branches: [ main ]nnenv:n PROJECT_ID: isotope-bluen GAR_LOCATION: us-central1n GKE_CLUSTER: isotope-prod-clustern GKE_ZONE: us-central1-an REPOSITORY: app-repon IMAGE: backendnnjobs:n setup-build-publish-deploy:n name: Build and Deploy to GKEn runs-on: ubuntu-latestn steps:n - name: Checkout Coden uses: actions/checkout@v4nn - name: Authenticate to Google Cloudn uses: google-github-actions/auth@v2n with:n workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/github-pool/providers/github-provider'n service_account: 'github-deployer@isotope-blue.iam.gserviceaccount.com'nn - name: Set up Cloud SDKn uses: google-github-actions/setup-gcloud@v2nn - name: Configure Docker for Artifact Registryn run: |-n gcloud auth configure-docker ${{ env.GAR_LOCATION }}-docker.pkg.dev u002du002dquietnn - name: Build and Push Docker Imagen run: |-n IMAGE_TAG=${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.REPOSITORY }}/${{ env.IMAGE }}:${{ github.sha }}n docker build -t $IMAGE_TAG .n docker push $IMAGE_TAGnn - name: Get GKE Credentialsn uses: google-github-actions/get-gke-credentials@v2n with:n cluster_name: ${{ env.GKE_CLUSTER }}n location: ${{ env.GKE_ZONE }}nn - name: Deploy Rolling Update to GKEn run: |-n IMAGE_TAG=${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.REPOSITORY }}/${{ env.IMAGE }}:${{ github.sha }}n kubectl set image deployment/isotope-backend-app backend-api=$IMAGE_TAG -n productionn kubectl rollout status deployment/isotope-backend-app -n production4. 無停止リリースにおける運用チェックリスト
- データベーススキーマのマイグレーション: コードのデプロイを行う前に、必ず後方互換性のあるスキーマ変更(例: 非推奨化する前に新規カラムを追加する等)を先行して実行する。
- グレースフルシャットダウンの処理: バックエンドコード側で
process.on('SIGTERM')をキャッチし、10秒間のpreStopウィンドウ内でアクティブなDBプールやコネクションを正常にクローズできるようにする。 - 無停止ヘルスチェックの実装:
/healthzエンドポイントは、KubernetesのReadiness Probeに対して200 OKを返す前に、クリティカルな依存関係(DB接続、Redisキャッシュなど)が正常であることを確認する。
システム基盤の統合・最適化を実現
ベンダー管理の無駄を排除し、自動拡張する高信頼性システムを構築

Solutions:

