ざっくりGCP料金計算

Cloud SQLのフェイルオーバーに8分かかって障害になった話

HAを設定していれば安心ではなかった。フェイルオーバー中の挙動を一度も検証していなかった。

「DBに繋がらない」が続いた8分間

HA(高可用性)構成のCloud SQLを本番で使っていた。「フェイルオーバー時は自動で切り替わるから安心」という認識で、HAを有効にしてコストが2倍になることを受け入れて運用していた。ところがある日、実際にフェイルオーバーが発生して、その認識がいかに甘かったかを思い知った。

プライマリインスタンスが存在するゾーンでGCPのインフラ問題が発生し、自動フェイルオーバーがトリガーされた。GCPのドキュメントには「フェイルオーバーは通常60秒以内」と記載されている。しかし実際にかかった時間は約8分だった。その間、アプリケーションはDBへの接続を確立できず、エラーレートが急上昇し、一部の機能が完全に使えない状態になった。

なぜ8分かかったのか、なぜアプリが粘れなかったか

「通常60秒以内」はあくまで目安で、GCPのインフラ障害の規模や状況によっては大幅に超えることがある。問題はアプリケーション側の設計にもあった。DBへの接続失敗からリトライを続ける最大時間を30秒に設定していた。30秒でリトライが尽きると「DBエラー」としてユーザーにエラーレスポンスを返す設計だったので、フェイルオーバーが8分かかる状況では大量のエラーが発生した。リトライ設定を10分に延ばしていれば、フェイルオーバー完了後に自動で回復できた。

さらにフェイルオーバーが完了した後も、しばらくDBへの接続が安定しなかった。アプリが持っていたコネクションプールの接続がフェイルオーバー前のプライマリを向いており、古い接続が残り続けていた。Cloud SQLはフェイルオーバー後もIPアドレスは変わらない仕様だが、コネクションプールの設定によっては古い接続が生き残ってしまう。

フェイルオーバーテストは定期的にやるべきだ

改善策としてアプリのDB接続リトライ設定を最大10分に変更し、コネクションプールのmax_lifetimeを短く設定して古い接続が早めに破棄されるようにした。Cloud SQL Auth Proxyを経由した接続に切り替えたことで、フェイルオーバー時の接続切り替えもより確実になった。最も大きな教訓は「HAを設定したことへの過信」だ。GCPのコンソールからは手動でフェイルオーバーをトリガーできる機能がある。HAを設定した直後に実際にフェイルオーバーを発生させてアプリへの影響を確認しておくべきだった。以降はHAを有効にしたすべてのインスタンスで、本番反映前にフェイルオーバーテストを実施することをルール化した。