本ブログは「Our Commitment to Reliability and Incident Learning」の抄訳となります。
当社のお客様はNew Relicを信頼していただいており、最も重要なアプリケーションとインフラストラクチャのパフォーマンスを理解し、最適化するために日常的に利用していただいています。New Relic One は、テレメトリーデータを一箇所に集約することで、インフラ、クラウドリソース、コンテナ、アプリケーションのパフォーマンスをリアルタイムに把握し、お客様に実行可能な洞察を提供します。
7月29日(木)、New Relicにおいてサービス障害が発生し、米国地域のDCをご利用の多くのお客様が数時間にわたりデータ収集とアラートの使用ができない状態になりました。これは、Kafkaシステムの技術的な障害から始まったものですが、最終的には、通常の運用時にシステムを大規模に稼動させるための自動化や冗長化のプロトコルが原因で悪化しました。世界中のお客様が、製品やサービスの運用に必要な可視性を提供するためにNew Relicを利用していることは承知しています。今回の障害がお客様のビジネスに影響を与えたことを理解しており、その結果、多くのお客様が自社のデプロイメントを停止することを選択し、当社がサービスを復旧させるまでの間、夜遅くまでお客様のチームが厳重な警戒態勢を敷くことになりました。当社のサービス障害は、サービスだけでなく、お客様のビジネスやチームにも影響を与えました。
深くお詫び申し上げるとともに、お客様の信頼を回復するために真摯に取り組んでおります。
先週、エンジニアリングチームは、何が起きたのか、なぜ起きたのかを分析し、どうすればもっと良くなるのかを議論するという、われわれ自身の回顧プロセスに取り組んできました。一連の出来事だけでなく、関連する技術、ツール、プロセスについても検討しました。私たちは、自分たちがどのようにシステムを構築・運用しているのか、失敗した部分も含めて、詳細を共有することをお約束します。この記事では、New Relicを動かしているシステムがどのように機能しているのか、そして今回はどのように機能しなかったのかを説明いたします。
セルアーキテクチャーの概要
NRDBとも呼ばれる、われわれのテレメトリーデータプラットフォームは、時系列のテレメトリーデータのためにゼロから構築された分散型サービスのクラスターです。典型的な大規模クエリは何千ものCPUコアで実行され、何兆ものデータポイントをスキャンして、ミリ秒単位で顧客に回答を返します。テレメトリーデータプラットフォームは、現在、毎分30億以上のデータポイントを取り込み、その規模は指数関数的に拡大しています。
NRDBではセルベースのアーキテクチャを採用しています。これは、各セル間を分離した状態で全体(「セル」)を複製することで、システムの拡張を可能にするアプローチです。このアーキテクチャーはお客様のニーズに合わせてプラットフォームを拡張できることと、および障害隔離による信頼性の向上の両方にメリットがあります。
俯瞰してみると、それぞれのセルでは以下のものを運用しています。
- Kafka クラスター
- インターネットに面したデータ摂取(ingest)サービス
- 取り込まれたトラフィックを処理するデータパイプラインサービスの集合
- NRDB クラスター
セルアーキテクチャーの利点
障害分離したセルを使用することで、1つのセルでの障害の影響を軽減しながら、数十ものNRDBクラスターを同時に運用することができます。セルの数が増えれば増えるほど、障害の影響範囲(お客様への影響)は減少していきます。例えば、2つのセルしかないアーキテクチャでは1つのインシデントが50%の顧客に影響を与える可能性があります。セルが10個の場合は1つのインシデントは10%の顧客に影響を与える可能性があります。セルは必要に応じて段階的に追加されます。
このアーキテクチャのもう一つの利点は、弾力性です。予期せぬトラフィックの急増にも、本番トラフィックを不健全なセルから健全なセルにオンザフライでシフトさせることで、動的に対応することができます。これにより、セルの規模を拡大したり、新しいセルを追加したりしながら、トラフィックを処理し続けることができます。
大規模において複雑性を管理する
セルベースのアーキテクチャは多くの最新アーキテクチャと同様に、スケール、スピード、柔軟性など多くのメリットがあります。その一方で新たな課題もあります。その一つである複雑性を管理するため、Kafkaやインフラ自動化など、多くのツールや手法を活用しています。今回のサービス中断は、システムの信頼性とパフォーマンスを維持するために通常の運用で利用している自動化や冗長化プロトコルの一部が原因で、技術的に孤立した障害が発生したことによるものです。
Kafka
New Relicのアーキテクチャでは、データのストリーミングと処理にApache Kafkaを多用しています。各セルの中心となるのは、Apache Kafka を実行するメッセージブローカーのクラスターです。
通常の運用では、Kafkaは高スループットのデータバスを提供し、すべてのお客様のデータを処理、評価、保存のパイプラインの各段階に運びます。パイプラインのいずれかの段階で問題が発生したり速度が低下したりした場合、Kafkaはバッファとしても機能し、一定量のデータを保持することで、データを廃棄せずにキューに入れることができます。
Kafkaクラスターはデータの損失を防ぐために高度に冗長化されていますが、場合によってはブローカーが応答しなくなることがあります。しかし、そのブローカーはクラスターから削除されていないため、パイプラインのデータがその背後で滞留することになります。このような場合、ブローカを再起動するか、場合によってはブローカをクラスターから削除して新しいインスタンスに置き換え、その新しいインスタンスを既存のストレージに再接続することで再構築する必要があります。ブローカーが応答しないことを検出すると、サービスは自動的にこの処理が行われるように設計されていますが、自動修復に失敗することもあり、その場合は手動で処理を行う必要があります。
コードとしてのインフラストラクチャー
私たちは、コードとしてのインフラストラクチャーを基本原則としており、ソフトウェアサービスに使用しているのと同じプラクティスとツールを使用して、環境のさまざまな階層でリソースをプロビジョニングし、構成を管理しています。
通常の運用では、セルを構築したり、セルにソフトウェアをデプロイしたり、セルのインフラを変更したりする際には、標準的なCI/CDパイプラインを使用して、1つのセルから始めて、次にいくつかのセル、そして最終的にはすべてのセルに変更をゆっくりと展開していきます。また、特定のセルの一部を独立して調整することもできますが、同じ種類のセルはできる限り一貫性を保つようにしています。
しかし、チームがサービスの問題に対応しているときには、特にスケールアップするときには迅速に行動したいものです。そこで、インシデント対応時に使用する一連のツールを用意しており、エンジニアが本番の問題を解決するために迅速な行動をとれるようにしています。これらのツールは、通常のオペレーションと同じコアインフラ上に構築されています。
障害の詳細
7月29日の朝、あるセルのKafkaブローカーが反応しなくなりました。自動システムが正しく作動しなかった最近の同様の問題から、当社のエンジニアリングチームは手動での再起動を開始しました。しかし、実際には自動化されたプロセスも同時に開始されていました。どちらの作業も最終的には安全に終了しましたが、プロセスが競合したことでクラスターがデグレード状態になっている時間が予想以上に長くなり、問題の真の原因についてわからなくなり混乱が生じました。
クラスターがデグレード状態にある間に、未処理のデータのバックログが蓄積され始めました。セルの回復時に古いデータが処理される前に失われないようにするため、対応したエンジニアはインシデント対応ツールの1つを使用してKafkaのデータ保持を延長しました。担当チームはこの時点では気づかなかったのですが、この保持期間の変更によりKafkaブローカーが数時間かけてゆっくりとディスク容量を使い果たしてしまうという事態が発生しました。
保持期間を伸ばす大きさが過去の変更よりも大きかったことで、ある時間経過した時点でディスク容量を使い果たす問題が時限爆弾のようにトリガーされました。保持期間を伸ばす変更自体は以前の障害対応の際も行われていましたが、その時は時限爆弾による問題が発生する前に、トラブルシューティングが完了し、データ処理が再開され、緊急対応が完了していました。しかし今回は、根本的な原因が不明であることと、通常よりも復旧に時間がかかっていたことから、チームは緊急対応を継続し、状況の分析を続けていました。この結果、時限爆弾による問題が発生してしまいました。(抄訳注: この段落はわかりやすさのために、原文の文章構造からかなり変更しています)
前述のように、私たちはインフラの自動化を利用して、セル間の一貫性を確保しています。当社のツールではセルごとの微調整が可能ですが、通常、Kafkaのデータ保持量は環境全体で一貫性を保ちたいと考えています。そのため、影響を受けたセルのデータ保持を延長すると、ツールは元々問題があったセルだけでなく、すべてのセルに変更を適用しました。
最終的には、ディスクの増加により、より多くのブローカーに障害が発生しました。最初は少数のセルでしたが、次第により多くのセルで障害が発生し、結果的にデータ処理システムに広範な障害が発生しました。ディスクスペースの問題が解決しても、Kafkaの問題が広範囲に及んでいたため、サービスの回復には時間がかかりました。
安全層はなぜ動作しなかったか
しかし、なぜこのような大きな混乱が生じたのでしょうか。それを理解するために、上記の一連の出来事と、うまく働かなかった安全機構をもう一度確認してみます。
1. ツール自体が安全ではない変更を適用してしまった。多くの緊急用ツールがそうであるように、このツールも非常にシンプルで、依存関係も限られており、想定外の状況でも仕事ができるように設計されていました。しかし、この場合はシンプルすぎて、保持期間の大幅な増加が潜在的に危険であることを利用者に警告していませんでした。
2. エンジニアが指定すべき設定値を間違えました。エンジニアも人間であり、今回のようなサービス障害は複雑でストレスの多い状況であり、ミスが起こることもあります。これに加えて、このツールはデータ損失のリスクがある状況で日常的に使用されており、すでに何十回も問題なく使用されていたという事実がありました。たとえ安全でなくても、「安全」と思えてしまう状況に陥っていました。
3. この操作を安全だと判断した理由は、通常、トラブルシューティングによる解決が早く、延長する保持期間の設定値が危機的なレベルに達することがなかったためです。このケースでは、チームは根本的な問題を調査するために時間を必要としたため、保持するデータがどんどん増えていきました。
4. ディスク容量が不足し始めたとき、監視システムが警告を発し、チームに問題を知らせました。しかし、そのアラートのタイミングが他の複数のシステムによる関係のない警告を発しているのと重なっていたため、アラートを見逃してしまいました。
5. 最後の安全策として、セルを隔離することでこのエラーがより広範な問題になるのを防ぐことができるはずでした。しかし、同じタイプのすべてのセルに自動的に適用されるため、セルの隔離が意味をなさない状況になりました。つまり、障害隔離した一つだけのセルでおきるはずだった問題が、多くのセルで同時多発し影響を与えました。
今後の方針
私たちは、フォールトトレラントなスケーラブルシステムを実現するために、セルアーキテクチャ、Kafka、コードとしてのインフラストラクチャーに頼って通常運用を行っています。しかし、7月29日に発生した問題では、これらのツールやテクニックが予期せぬ状況で失敗する可能性があることが浮き彫りになりました。
いくつかの重要な教訓があります。
- セルを隔離することは広範な中断に対する最強の防御策です。通常の運用時だけでなく、緊急時に使用するツールにおいても、この隔離を堅持する必要があります。
- 緊急対応ツールは、混沌とした緊急対応下でも安全のための機能を損なうことなく利用できる必要があります。
- 人間の注意力には限界があります。障害対応のプロセスやアラートを常に評価し、エンジニアの注意力が最も緊急性の高い信号に向けられるようにしなければなりません。
今回のサービスインシデントにより、お客様のチームやビジネスにストレスを与えてしまったことを心よりお詫び申し上げます。私たちのシステムの信頼性は、お客様のサービスの健全性とパフォーマンスを維持するために非常に重要であり、お客様は私たちが常に利用可能であることを期待していることを理解しています。私たちは、お客様が差別化されたイノベーションを提供することに集中できるよう、世界クラスのサービスを提供し続けるために、技術、ツール、プロセスを継続的に評価し、改善することを約束します。この公開された回顧録が役に立ち、私たちの経験から学んでいただけることを願っています。
本ブログに掲載されている見解は著者に所属するものであり、必ずしも New Relic 株式会社の公式見解であるわけではありません。また、本ブログには、外部サイトにアクセスするリンクが含まれる場合があります。それらリンク先の内容について、New Relic がいかなる保証も提供することはありません。