レプリカの同期遅延—そして本番環境への打撃
2017年1月、GitLab.comは回復力を確保するために、PostgreSQLのプライマリである db1.cluster.gitlab.com と、ライブレプリカである db2.cluster.gitlab.com に依存していました。高可用性構成において一般的なこのアーキテクチャは、フェイルオーバーのために db2 を同期状態に保つことを目的としていましたが、これは極めて重要であると同時に、しばしば脆い防御策でもありました。
その日の夕方、負荷の急増により db2 の同期が大幅に遅れ、レプリケーションが停止しました。標準的な修正手順は、db2 のデータフォルダを削除し、db1 からすべてをコピーして再初期化することでした。理論上は単純な手順です。
しかし、この再初期化の過程で、エンジニアが誤って rm -rf コマンドを db2 ではなく、本番環境のプライマリである db1 に対して実行してしまいました。コマンドはわずか1〜2秒で停止されましたが、時すでに遅く、約300GBのデータが削除されてしまいました。これは緩やかな破損ではなく、本番環境のライブデータが突如として壊滅的に消去されたのです。この誤ったコマンド一つがもたらした結果は、やがてより深刻な問題を露呈させることになります。
すべてのバックアップは、見かけほど安全ではなかった
GitLabの惨事は、単なる一つのミスからではなく、検証されていない前提の上に築かれた砂上の楼閣から発生しました。組織は堅牢なバックアップ戦略を持っていると信じていましたが、あらゆるレイヤーに致命的な欠陥があることが判明し、検証されていないバックアップは保護ではなく、単なる仮説に過ぎないことが証明されました。
Amazon S3への日次 pg_dump エクスポートに対する信頼は誤りでした。PostgreSQL 9.6 データベースを保護するためのジョブが、なぜか遥かに古い PostgreSQL 9.2 バージョンの pg_dump ツールを使用していたのです。この不一致により、エクスポートはエラーを通知することなく失敗し、S3バケットは空のままとなっていました。
決定的な問題は、誰もこのシステム障害に気づかなかったことです。バックアップジョブの失敗を通知するはずのメールは、認証の問題によりメールサーバーによって一律に拒否されていました。さらに、回復力の基本レイヤーである本番データベースのスナップショットも有効化されていませんでした。LVMスナップショットはステージング環境にしか存在せず、Azure CloudのスナップショットはOSディスクを対象としていたものの、重要なデータベースボリュームは対象外でした。
プライマリデータベースが損壊し、復旧作業中にレプリカも消去されたため、GitLabは「有効な最新のバックアップが存在しない」という恐ろしい現実に直面しました。唯一の復旧手段は、エンジニアが無関係な負荷テストのために取得していた、約6時間前の手動スナップショットでした。この幸運は、エンジニアリングによる解決策ではなく、彼らのバックアップ哲学全体の危うさを浮き彫りにしました。低速なディスクからこのスナップショットをコピーするのに約18時間を要し、これは停止時間全体と一致しており、データ復旧準備を怠ったことの真の代償を浮き彫りにしました。
5,000人の視聴者の前で繰り広げられた復旧作業
GitLabの危機対応は、徹底した透明性の模範でした。エンジニアはGoogle Doc、ソーシャルメディア、YouTubeライブ配信を通じて、リアルタイムの更新情報やトラブルシューティングの状況を公開しました。この決断により、壊滅的な技術的障害は、信頼を問う非常に注目度の高いテストへと変わり、ピーク時には5,000人以上がその様子を見守りました。
非常に時間がかかった修正作業は、低速なストレージディスク上にあった6時間前の手動スナップショットに依存していました。このスナップショットの復元には約18時間を要し、これが停止時間全体となりました。この復旧の遅さは、GitLab.comが長期間にわたって利用不能であったことを意味します。
最終的に、GitLabは約6時間分のデータベースレコードを失いました。これには以下が含まれます:
- 5,000件のプロジェクト
- 5,000件のコメント
- 700件のユーザーアカウント
幸いなことに、リポジトリのデータは別のストレージ上に無傷で残っていました。結果は痛ましいものでしたが、その回復力と誠実さを公に示したことは、大きな敬意を集めました。詳細については、「Postmortem of database outage of January 31 - GitLab」を参照してください。このインシデントは、業界の多くの人々がインシデント対応と徹底した透明性(radical transparency)をどのように捉えるかを根本的に変えました。
この記事が気に入ったら、毎朝同じようなものをメールで受け取れます。
1日1通 · 2クリックで解除 · サードパーティのトラッキングなし
学んだ教訓は、責任の所在と非難の回避
GitLabの事後検証(ポストモーテム)は、スケープゴートを探すのではなく、オーナーシップ(責任の所在)の体系的な欠如を診断しました。中心的な問題はエンジニアのミスではなく、バックアップの信頼性と定期的な復元検証を担当する専任の役割が欠けていたことでした。誰も責任を負っていなかったため、重要な保護措置が形骸化していたのです。
このインシデントは、組織内部の大きな改革を促進しました。GitLabは自動復元テストを導入し、バックアップが存在するだけでなく機能することを保証しました。また、本番環境へのアクセス制限を強化して破壊的な操作を誤って実行しにくくし、データベースの信頼性に対する明確な責任を専任チームに割り当てました。
あらゆるエンジニアリング組織にとって、教訓は明確です。バックアップの整合性に対して特定の責任者を割り当ててください。バックアップ失敗時の検証済み通知チャネルを確立し、見落とされがちなメールだけに頼らないようにしましょう。重要なのは、復元戦略を検証するために定期的に復元テストを行い、偶発的なデータ損失を防ぐための堅牢な保護措置を実装することです。バックアップは、最後に検証された復元テストの結果以上に信頼できるものではありません。
よくある質問
GitLabの2017年のデータベース障害の原因は何ですか?
同期が遅れていたレプリカを修正しようとした際、エンジニアが誤ってレプリカではなく本番データベースのデータを削除してしまいました。
なぜGitLabはバックアップから復元できなかったのですか?
日次エクスポートが、互換性のないPostgresツールバージョンを使用していたために失敗し、失敗通知メールも拒否されていたためです。また、本番環境のスナップショットも利用できませんでした。
GitLabのダウンタイムはどのくらいでしたか?
復旧には約18時間かかりました。その主な理由は、低速なストレージから手動で作成されたスナップショットを復元するのに時間がかかったためです。
GitLabはどれくらいのデータを失いましたか?
GitLabは約6時間分のデータベースデータを失いました。これには約5,000件のプロジェクト、5,000件のコメント、700件のユーザーアカウントが含まれます。
What is the main lesson from the incident?
バックアップは、チームが定期的に復元テストを行い、そのプロセスに対して誰かが責任を負っている場合にのみ信頼できるものです。

