デプロイは正常動作を確認して初めて完了する
あるチームが新しいバージョンを本番環境にプッシュした。パイプラインはグリーン。デプロイログにエラーはない。全員が安堵の息をつき、次のタスクに移る。2時間後、顧客から「チェックアウトページが壊れている」とサポートにメールが届く。チームは慌てて調査し、ロールバックし、翌日は原因究明に費やすことになる。
このシナリオはよくある話だ。多くのチームは、新しいバージョンが本番サーバーで起動した瞬間にデプロイが完了したと見なす。しかし実際には、そのバージョンがユーザーにとって本当に正常に動作しているかどうかを確認して初めて、デプロイは完了する。
本番環境はクリーンルームではない
新しいバージョンが本番環境に投入されると、ステージングでは決して完全には再現できない環境に置かれる。実際のユーザーは実際のデータ、実際のトラフィックパターン、実際のデバイス構成をもたらす。どのテスト環境も予測しなかったことが起こる。
ステージングで1000行のデータに対して問題なく動作していたクエリが、本番の100万行のデータでは低速になるかもしれない。後方互換性があるように見えたAPIの変更が、6ヶ月間更新されていないモバイルクライアントを壊すかもしれない。デザインレビューでは素晴らしかった新機能が、ユーザーを混乱させて誰もクリックしなくなるかもしれない。
これらは失敗ではない。シグナルである。問題は、あなたのチームがそれらをキャッチできる体制にあるかどうかだ。
重要なシグナル
優れたチームは、ユーザーが問題を報告するのを待たない。本番環境からシグナルを取得する自動化システムを構築する。最も有用なシグナルはいくつかのカテゴリに分類される。
エラー率の変化。 デプロイ直後にエラー率が急上昇した場合、何かが壊れている可能性が高い。全エンドポイントで5%の増加があれば、即座にロールバックすべきだろう。ほとんど使われていないエンドポイントでの0.1%の増加は、次回リリースで修正すべきバグかもしれない。
応答時間の劣化。 応答が遅くなることは、データベースのボトルネック、非効率なクエリ、リソース競合を示唆することが多い。このシグナルは特に重要だ。ユーザーはすぐに不満を言わないかもしれないが、サービスから離脱し始めるからだ。
トランザクション量の低下。 完了したトランザクションが突然減少する場合、ユーザーがエラーに遭遇している、フローで行き詰まっている、あるいは単に諦めている可能性がある。このシグナルは検出が難しい。現在のトラフィックを過去のベースラインと比較する必要があるからだ。
各シグナルは異なる意味を持つ。鍵となるのは、どのシグナルに即座に対応すべきで、どのシグナルは待機できるかを知ることだ。
以下は、エラー率に基づいてロールバックの判断を自動化する実践的な例である。
#!/bin/bash
# デプロイ後のヘルスチェック: エラー率を問い合わせ、5%超でロールバック
THRESHOLD=5.0
DEPLOY_ID=$(curl -s "https://monitoring.example.com/api/v1/deploy/latest" | jq -r '.id')
ERROR_RATE=$(curl -s "https://monitoring.example.com/api/v1/query?query=error_rate{deploy_id=$DEPLOY_ID}" | jq -r '.data.result[0].value[1]')
if (( $(echo "$ERROR_RATE > $THRESHOLD" | bc -l) )); then
echo "エラー率 $ERROR_RATE% がしきい値 $THRESHOLD% を超えました。ロールバック中..."
kubectl rollout undo deployment/my-app
exit 1
else
echo "エラー率 $ERROR_RATE% は許容範囲内です。デプロイを確認しました。"
fi
シグナルから根本原因へ
シグナルを検出したら、次のステップは根本原因の特定だ。コードのバグか?設定の不一致か?データの問題か?インフラの問題か?その答えによって、誰がどのように修正するかが決まる。
以下のフローチャートは、デプロイからシグナル検出、根本原因分析、アクションに至る流れを示している。
ここで多くのチームが行き詰まる。エラーの急増を見て、すぐにコードが悪いと思い込む。しかし、コードは問題なく、ステージングと本番で設定値が異なることが原因の場合もある。データベーススキーマのマイグレーションは正しく実行されたが、マイグレーション完了前にアプリケーションコードがデプロイされた場合もある。
成熟したチームは、目の前の問題を修正するだけではない。その問題を引き起こしたプロセス自体も修正する。データベースマイグレーションが問題を引き起こしたなら、パイプラインにマイグレーションチェックを追加する。ステージングと本番の設定がずれていたなら、それらを同一にする。特定の種類の変更が繰り返し問題を起こすなら、デプロイチェックリストを更新して早期にキャッチできるようにする。
フィードバックが意思決定を改善する
本番環境からのフィードバックは、バグ修正のためだけではない。チームが自身の判断を評価するのにも役立つ。デプロイ前に設定した準備基準を覚えているだろうか?それらは実際に問題を防いだだろうか?それとも、その基準がカバーしていなかったシナリオで重大な問題がすり抜けたのだろうか?
本番環境からの実際のデータを使って、チームはデプロイ基準を調整できる。どのチェックが効果的で、どのチェックが誤った安心感を与えているかを判断できる。パターンを特定できる。例えば、データベース関連のインシデントはすべて金曜日のデプロイで発生しているなら、金曜日にはデータベース変更のデプロイをやめる。設定関連のインシデントはすべて特定のチームメンバーが休暇のときに発生しているなら、バックアップレビューアを追加する。
これこそが、デプロイプロセスが時間とともに改善される方法だ。本に書かれたベストプラクティスに従うのではなく、自社の本番データから学ぶことで改善される。
フィードバックの速さが重要
フィードバックがチームに早く届くほど、迅速に対応できる。そのため、デプロイ後の検証は重要なプラクティスである。エラーが蓄積されるのを待つのではなく、チームは新しいバージョンが最初の数分または数時間で正常に動作しているかを積極的に確認する。
デプロイ後の検証にはいくつかの形態がある。
- デプロイ直後に本番エンドポイントに対して実行する自動スモークテスト。
- エラー率、応答時間、スループットの前後スナップショットを比較するメトリクス比較。
- 最初の数分間のトラフィックで異常なパターンを探すログ分析。
さらに進んだチームはカナリアデプロイを実行する。新しいバージョンがごく一部のトラフィックのみを処理する。シグナルが良好ならトラフィックを徐々に増やす。シグナルが悪化したらカナリアを自動ロールバックする。このアプローチは影響範囲を限定しつつ、実際の本番フィードバックを得られる。
フィードバックにはシステムが必要
フィードバックを収集しても、それを管理するシステムがなければ無意味だ。チームには、シグナルを収集し、ノイズをフィルタリングし、アクションに優先順位を付ける方法が必要である。グラフで埋め尽くされたダッシュボードだけでは不十分だ。システムはチームがより良い意思決定を行うのを支援しなければならない。
これは、各シグナルに明確なしきい値を定義することを意味する。「エラー率が5分間以上2%を超えたら、オンコールエンジニアにページングする」「重要なエンドポイントの応答時間が2倍になったら、次のスプリントのチケットを作成する」。しきい値がなければ、すべてのシグナルが緊急に見え、チームは誤報の追跡に疲弊してしまう。
また、明確なエスカレーションパスを持つことも意味する。すべてのシグナルに同じ対応が必要なわけではない。自動ロールバックをトリガーするシグナルもあれば、チケットを発行するシグナルもある。デプロイプロセスの変更を議論するためのミーティングをトリガーするシグナルもある。システムはこれらの区別を明確にすべきだ。
本番フィードバックのための実践的チェックリスト
以下は、あなたのチームが本番環境から有用なフィードバックを得られているかを評価するための短いチェックリストである。
- デプロイのたびに、エラー率、応答時間、トランザクション量の変化に対する自動アラートはあるか?
- デプロイ前に、これらのメトリクスのベースライン値を把握しているか?
- 「後で調査」と「今すぐロールバック」を区別する明確なしきい値はあるか?
- デプロイ後に本番環境でスモークテストを実行しているか?
- デプロイインシデントをレビューして、パイプラインと基準を改善しているか?
- 本番環境からのフィードバックが、パイプラインの構築方法を変えたことはあるか?
これらのうち2つ以上に「いいえ」と答えた場合、あなたのチームはデプロイ後に手探りで進んでいることになる。
デプロイの本当の終わり
デプロイは、新しいバージョンが起動した時点で終わりではない。チームが新しいバージョンが正常に動作していることを確認した時点で終わりである。その確認は、シグナルを取得し、ノイズをフィルタリングし、アクションを促進するフィードバックシステムから得られる。それらのシステムがなければ、すべてのデプロイはギャンブルである。システムがあれば、すべてのデプロイは学習の機会となり、次回のデプロイをより安全にする。