インフラ停止テストを実際にやってみた
クラウド環境(特にPaaS中心のシステム構成)でシステムを運用していると、
- 冗長構成だし大丈夫
- フェイルオーバーも設定している
- 障害時も自動で切り替わるはず
……と思いがちですが、「実際に障害が起きたらどうなるか」を本当に確認できていますか?
今回は、いわゆるカオスエンジニアリングのような大掛かりなことはせず、
「インフラを意図的に止めてみる」だけの、簡易的なインフラ停止テスト をやってみたので、
その結果と学びを共有します。
やってみて分かったこと
今回のインフラ停止テストで得られた学びは以下です。
- 簡易的なテストでも十分に価値がある
- 「冗長構成」「自動切替」を過信するのは危険
- 実際に止めてみないと分からないことが多い
特別なツールや大掛かりな準備をしなくても、
簡単に試してみるだけでも、システムの弱点は見えてくる と感じました。
なぜインフラ停止テストをやったのか
これまでのサービス運用の中で、
- 冗長構成を組んでいたのに片系の障害発生時に処理が止まる
- 想定外の障害シナリオでサービスが不安定化
といった、「設計通りのはずなのに動かない」場面に何度か遭遇しました。
原因を突き詰めていくと、
- 設計書上では問題なさそう
- 机上レビューでも特に問題はなし
- PaaSのリソースは障害時は自動で切替・復旧する
それでも 実際の障害時には想定外の挙動をする というケースが多いことに気づきました。
だったら、
「実際に止めてみて、どう動くかを見るしかない」
という結論に至り、今回のテストを実施しました。
今回のテストの目的
目的はシンプルです。
- Azure 上でリソースを意図的に停止し、システム全体の実挙動を把握する
- 机上・設計レビューだけでは検知できない問題を抽出する
ポイントは、完璧なテストを目指さないこと。
- 限られたリソース内で実施するため本格的なカオステストはやらない
- 網羅性のある重厚なテストを目指すのではなく定期的に継続的に実施できるレベルのテストにする
- まずは「やってみる」
このスタンスで進めました。
テスト対象にしたAzureリソース
今回テストしたのは、以下の4つです。
アプリケーションはAKS(Azure Kubernetes Service)上で稼働していて、一旦そこは対象外。
主に以下のデータストアとの接続周りを最初の対象としました。
- Azure Cache for Redis
- Azure Database for PostgreSQL
- Azure Cosmos DB
- Azure Event Hubs
再現した障害パターン
以下のような障害シナリオを、疑似的に 再現しました。
- ネットワーク不調による一時的な接続断
- PaaSリソースのプライマリ/セカンダリの停止
- Redisのキャッシュ全消失
あくまで簡易的ですが、「現場で起きそうなこと」を意識しています。
疑似的な再現方法
| No | リソース | 事象 | 再現方法 |
|---|---|---|---|
| 1 | Redis | 接続断 | AKSでPORT遮断 |
| 2 | Redis | プライマリ停止 | プライマリ再起動 |
| 3 | Redis | セカンダリ停止 | セカンダリ再起動 |
| 4 | Redis | キャッシュ全消失 | キャッシュフラッシュ |
| 5 | PostgreSQL | 接続断 | プライマリ再起動 |
| 6 | PostgreSQL | プライマリ停止 | DB停止 |
| 7 | PostgreSQL | レプリカ停止 | DB停止 |
| 8 | PostgreSQL | 両系停止 | 両方停止 |
| 9 | Cosmos DB | 接続断/停止 | AKSでPORT遮断 |
| 10 | Event Hubs | 接続断/停止 | AKSでPORT遮断 |
「このくらいなら自分の環境でもできそう」と思えるレベル感を意識しています。
もちろんこの方法が「事象を正確に再現している」という保証はありません。
簡易的にできることからやっていく、を優先しています。
検証結果①:Redis / Cosmos DB / Event Hubs
まずは比較的わかりやすかったリソースから。
Redis
- 接続断中はエラーになるが、復旧後は自動回復
- キャッシュ消失時も、数秒のエラーで収束
- プライマリ/セカンダリ再起動の影響はほぼ無し
Cosmos DB / Event Hubs
- 一時的な接続断・停止でもサービス影響なし
- 非同期処理が効いていて、挙動は安定
このあたりは 想定通りで安心できる結果 でした。
期待通りであったこと、これも確認の成果の1つです。
検証結果②:PostgreSQLで問題発覚
一方で、PostgreSQLは想定外の挙動がありました。
フェイルオーバーが起きない・・・
- プライマリ停止時、アプリケーションの接続先がレプリカに切り替わらない
- アプリケーションは切り替え可能な設計&実装のつもりだった
Podヘルスチェック設計の落とし穴
- アプリケーションが稼働するPodの生存判定が「プライマリDBへの疎通」前提
- プライマリ停止時にPodがLBから切り離される
- 結果として、期待通りフェイルオーバーが起きていたとしても、サービス継続できない
見えてきた改善ポイント
PostgreSQL周りは、優先的に改善すべき点が明確になりました。
- レプリカ切替ロジックの見直し
- Podのヘルスチェックをプライマリ依存から脱却
これにより、DB障害時でも処理継続できる可能性が高まります。
おわりに
深く考えてから完璧なテストをするよりも、
まず止めて、どう動くかを見る
この一歩が、システムの信頼性向上につながると思います。
「これくらいなら自分のプロジェクトでもできそう」
そう思った方の参考になれば嬉しいです。