デプロイ後に何が起きるのか?パイプラインはまだ終わっていない

パイプラインがグリーンになったのを確認した。アーティファクトが本番環境にデプロイされ、エラーメッセージは一つも出なかった。チームは安堵の息をつき、次のタスクに移る。しかし、ここで厄介な疑問が浮かぶ。アプリケーションは実際にユーザーにとって正しく動作しているのだろうか?

私は、デプロイ成功を祝った直後、1時間後に新機能がユーザーログインを静かに壊していることに気づいたチームを何度も見てきた。デプロイログにはエラーはなかった。サーバーは動作していた。しかし、誰もサインインできなかった。パイプラインはジョブが完了したと見なしたが、実際の問題はユーザーが苦情を言い始めるまで気づかれなかった。

この「デプロイが成功した」と「デプロイが機能している」の間のギャップこそが、デプロイ後検証が存在する理由です。これは、技術的に成功したデプロイと、実際に価値を提供するデプロイを分けるステップです。

デプロイ後検証の3つのレイヤー

デプロイ後検証は、パイプラインが新しくデプロイされたバージョンをターゲット環境で直接チェックする段階です。これらのチェックは自動化され、プログラム的に実行される必要があり、誰かが自分のラップトップから手動で実行するものではありません。それぞれ異なる目的を持つ、3つの一般的なタイプがあります。

以下のフローチャートは、これら3つのレイヤーがどのように連携して動作し、チェックが失敗した場合に自動ロールバックまたはアラートを発動するかを示しています。

flowchart TD A[本番環境にデプロイ] --> B[ヘルスチェック] B -->|成功| C[スモークテスト] B -->|失敗| D[ロールバック / アラート] C -->|成功| E[シンセティックモニタリング] C -->|失敗| D E -->|成功| F[デプロイ成功とマーク] E -->|失敗| G[アラート / 調査]

ヘルスチェック:アプリケーションは生きているか?

ヘルスチェックは最も基本的な検証です。これは一つの質問に答えます。サービスが実行中で、リクエストに応答しているか? 通常、これは専用のエンドポイント(/health/status など)で、アプリケーションが生きている場合にHTTP 200コードを返します。

しかし、ここに落とし穴があります。ヘルスチェックは、アプリケーションが完全に停止していないことだけを教えてくれます。アプリケーションが正しく動作しているかどうかは教えてくれません。サービスは、破損したデータを提供したり、応答が遅かったり、重要な操作で静かに失敗したりしていても、200を返すことができます。ヘルスチェックは必要ですが、最低限の基準であり、ゴールではありません。

スモークテスト:コア機能は動作するか?

スモークテストはさらに深く掘り下げます。アプリケーションの最も重要な機能をカバーする、シンプルなシナリオを実行します。eコマースサイトの場合、スモークテストはホームページを開き、商品を検索し、カートにアイテムを追加するかもしれません。データベースの場合は、主要なテーブルにアクセス可能で、基本的なクエリが実行できることを確認します。インフラストラクチャの場合は、ロードバランサーが応答し、SSL証明書がまだ有効であることを検証します。

ここでのキーワードは「シンプル」です。スモークテストは完全なリグレッションスイートではありません。コア機能のハッピーパスをテストします。スモークテストが成功すれば、アプリケーションが根本的に壊れていないという合理的な確信が得られます。失敗した場合は、ユーザーよりも先に何か問題があることを知ることができます。

以下は、重要なAPIエンドポイントをチェックし、レスポンスが200でない場合にゼロ以外のコードで終了する、最小限のbashスモークテストです。

#!/bin/bash
set -euo pipefail

# スモークテスト: ログインエンドポイントが200を返すことを確認
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" https://myapp.com/api/login)

if [ "$RESPONSE" -ne 200 ]; then
  echo "スモークテスト失敗: ログインエンドポイントが $RESPONSE を返しました"
  exit 1
fi

echo "スモークテスト成功: ログインエンドポイントが200を返しました"

シンセティックモニタリング:パフォーマンス基準を満たしているか?

シンセティックモニタリングは、実際のユーザー行動をスケジュールに従ってシミュレートします。デプロイ後に一度だけ実行されるヘルスチェックやスモークテストとは異なり、シンセティックモニタリングは継続的に実行されます。しかし、デプロイ後、パイプラインはシンセティックチェックをトリガーして、新しいバージョンが依然としてパフォーマンス基準を満たしていることを確認できます。

例えば、重要なAPIエンドポイントの応答時間を測定するシンセティックチェックがあるとします。デプロイ後に応答時間が500msを超えた場合、エンドポイントが正しいデータを返していても、パイプラインはそれをフラグする必要があります。シンセティックモニタリングは、ヘルスチェックやスモークテストが見逃すようなパフォーマンス低下をキャッチします。

検証が失敗した場合の対処

デプロイ後検証が失敗した場合、パイプラインは即座に行動する必要があります。最も一般的な対応はロールバックです。環境を以前の正常なバージョンに戻します。しかし、ロールバックだけが選択肢ではなく、常に最善とは限りません。

カナリアデプロイを使用している場合、パイプラインは新しいバージョンへのトラフィックルーティングを停止し、すべてのユーザーを古いバージョンに戻すことができます。ブルーグリーンデプロイを使用している場合、パイプラインはトラフィックを古いバージョンが実行されている環境に切り替えることができます。具体的なアクションはデプロイ戦略に依存しますが、原則は同じです。被害を止め、サービスを復旧することです。

どのようなアクションを取るにせよ、失敗は証拠として記録されなければなりません。パイプラインは、ヘルスチェック、スモークテスト、シンセティックモニタリングのログを、タイムスタンプとテスト対象のアーティファクトバージョンとともに保存する必要があります。この証拠は、後で何が問題だったかを調査する際に重要になります。これがなければ、推測するしかありません。

チームがこのステップをスキップする理由

デプロイ後検証は、しばしばオプションとして扱われたり、完全にスキップされたりします。理由は様々です。一部のチームは、デプロイ前のテストを過信しています。他のチームは、ヘルスチェックで十分だと考えています。多くのチームは、迅速に動くプレッシャーを感じ、検証をスローダウンと見なしています。

しかし、検証をスキップすると、ブラインドスポットが生まれます。デプロイ前のテストは、本番環境と完全に一致することのないステージング環境で実行されます。設定の違い、データ量の違い、インフラストラクチャの違いにより、ステージングでのテスト合格は、本番環境でのテスト合格を保証しません。デプロイ後検証は、それらのギャップに対するセーフティネットです。

デプロイ後検証の実践的なチェックリスト

初めてデプロイ後検証を設定する場合の、最小限の出発点は以下の通りです。

  • データベース接続、キャッシュ接続、重要な外部依存関係をチェックする /health エンドポイントを追加する
  • 最も重要なユーザージャーニーをカバーする3〜5つのスモークテストを作成する
  • 主要なAPIまたはページの応答時間を測定するシンセティックチェックを少なくとも1つ設定する
  • いずれかの検証ステップが失敗した場合に、自動的にロールバックをトリガーするようにパイプラインを設定する
  • すべての検証結果をタイムスタンプとバージョン番号とともに保存する

この最小限のセットから始めて、特定のコンテキストで何が壊れるかを学びながら拡張してください。

デプロイ成功の真の尺度

デプロイが完了するのは、アーティファクトがサーバー上にあるときではありません。新しいバージョンが正しく動作し、基準を満たしているという証拠があるときです。デプロイ後検証は、その証拠を提供するものです。

それがなければ、盲目的にデプロイしていることになります。それがれば、デプロイがいつ本当に成功し、いつ静かに失敗したかを正確に知ることができます。その知識は、ユーザーの苦情に反応することと、誰も気づく前に問題をキャッチすることの違いです。