本日、Tiered Cacheシステムの変更により、ステータスコード530で、ユーザーの一部のリクエストが失敗しました。その影響は、合計で6時間近くも続きました。ピーク時には、すべてのリクエストの約5%が失敗したと推定されます。 システムの複雑さとテストに盲点があったため、この変更をテスト環境にリリースしたときには、このことに気がつきませんでした。
この失敗は、場所をまたいでキャッシュ可能なリクエストの処理方法の副次的影響が原因でした。一見すると、少し前に、リリースを開始した別のシステムが原因のエラーのように見えました。問題を引き起こした原因を正確に特定するために、当社のチームは何度も試行錯誤を繰り返しました。特定されると、ロールバックを迅速に処理し、87分で完了しました。
申し訳ございませんでした。このようなことが二度と起こらないように、対策を講じています。
背景
Cloudflareの製品のひとつに、コンテンツ配信ネットワーク(CDN)があります。Webサイトのアセットをグローバルにキャッシュするために使用されます。しかし、データセンターは、必ずしもアセットをキャッシュするわけではありません。新規、期限切れの場合やパージされた場合などです。 そのような場合、ユーザーがそのアセットをリクエストすると、CDNはWebサイトのオリジンサーバーから新しいコピーを取得する必要があります。しかし、ユーザーがアクセスしているデータセンターは、オリジンサーバーからまだかなり離れている可能性があります。このことは、お客様にとってさらなる問題を提起します。アセットがデータセンターにキャッシュされないたびに、オリジンサーバーから新しいコピーを取得する必要があります。
Cacheヒット率を向上させるために、Tiered Cacheを採用しました。Tiered Cacheを使用して、CDNのデータセンターを、エンドユーザーに近い「下位層」とオリジンに近い「上位層」の階層に分類しています。下位層でキャッシュミスが発生すると、上位層をチェックします。上位層にアセットの新しいコピーがある場合、リクエストに応えてそれを提供することができます。これによりパフォーマンスが向上し、下位層のデータセンターにキャッシュされていないアセットを取得するために、Cloudflareがオリジンサーバーにアクセスしなければならない回数が減少します。
インシデントのタイムラインと影響
08:40 UTCに、バグを含むCDNコンポーネントのソフトウェアリリースを徐々にロールアウトし始めました。このバグは、Tiered Cache、Cloudflare Images、Bandwidth Allianceのいずれかが設定されたサイトにユーザーがアクセスしたときにトリガーされました。このバグが原因で、一部のお客様は、HTTPステータスコード530のエラーが返されました。データセンターのローカルキャッシュから直接提供が可能なコンテンツは影響を受けませんでした。
欠陥のあるコンポーネントがデータセンターのサブセットにリリースされた後、530で、断続的に増加しているとのお客様の報告を受け、調査を開始しました。
リリースが残りのデータセンターへグローバルにロールアウトし始めると、530の急激な増加がアラートをトリガーし、さらにお客様からの報告も増え、インシデントが宣言されたのです。
ステータスコード 530 で返されるリクエスト
17:03 UTCにデータセンターでリリースをロールバックすることで、不適切なリリースが原因であったことを確認しました。ロールバック後、530エラーの減少を確認しました。この確認後、グローバルなロールバックの加速が始まり、530が減少し始めました。UTC 18:04にTiered Cacheの上位層として構成されたすべてのデータセンターでリリースを元に戻すと、影響は終了しました。
タイムライン:
2022-10-25 08:40:リリースは、データセンターの小さなサブセットにロールアウトされ始めました。
2022-10-25 10:35:個々の顧客アラートが発生し、500件のエラーコードの増加を示しています。
2022-10-25 11:20: 調査後、単一の小さなデータセンターが問題の原因として特定され、チームがそこで問題を調査する間、生産から削除されました。
2022-10-25 12:30: コードを変更するデータセンターが増えるにつれ、問題がより広範囲に広がり始めます。
2022-10-25 14:22: 530エラーは、リリースが最大のデータセンターに徐々にロールアウトし始めるにつれて増加します。
2022-10-25 14:39: より多くのお客様がエラーの増加の報告があったため、複数のチームが調査に関わるようになりました。
2022-10-25 17:03: アトランタでCDNリリースがロールバックされ、根本原因が確認されました。
2022-10-25 17:28:すべてのHTTPリクエストの約5%で、影響がピークに達し、ステータスコード530をともなうエラーとなりました。
2022-10-25 17:38: 多くのお客様の上位層として機能を果たす大規模データセンターで、ロールバックの加速が続いています。
2022-10-25 18:04: すべての上位層でロールバックが完了しました。
2022-10-25 18:30: ロールバックが完了しました。
調査の初期段階では、指標としては、内部のDNSシステムの問題であるということ、同時にリリースがロールアウトされていたということです。次の項で示すように、それは障害の原因ではなく、副次的影響のものでした。
Tiered Cacheに分散トレースを追加すると問題が生じました
パフォーマンス向上のために、サービスのさまざまな部分に監視コードを定期的に追加しています。監視コードは、さまざまなコンポーネントの実行を可視化し、改善できるボトルネックの特定に役立ちます。当社のチームは最近、Tiered Cacheのロジックにさらに分散トレースを追加しました。Tiered Cacheエントリーポイントコードは以下の通りです:
* 前:
* 後:
function _M.go()
-- code to run here
end
上記のコードは、既存のgo()関数をtrace_fn()でラップします。trace_fn()は、go()関数を呼び出し、その実行時間を報告します。
local trace_fn = require("opentracing").trace_fn
local function go()
-- code to run here
end
function _M.go()
trace_fn(ngx.ctx, "tiered_cache_rewrite", go)
end
しかし、opentracingモジュールに関数を挿入するロジックは、すべてのリクエストで制御ヘッダーをクリアにします。
通常、これらの制御ヘッダーからデータを抽出してから、リクエストの処理方法のルーティン部分としてそれらをクリアします。
require("opentracing").configure_module(conf,
-- control header extractor
function(ctx)
-- Always clear the headers.
clear_control_headers()
--
しかし、内部のTiered CacheTrafficは、下位階層からの制御ヘッダーがそのまま渡されることを想定しています。ヘッダーのクリアと上位層の使用という組み合わせは、リクエストのルーティングに重要な情報を利用できないことを意味していました。影響を受けるリクエストのサブセットでは、オリジンサーバーのIPアドレスの内部DNSルックアップで解決するホスト名がありませんでした。その結果、クライアントに530のDNSエラーが返されました。
改善とフォローアップのステップ
再発防止のために、バグの修正に加え、今後このような問題を検出、防止に役立つ一連の変更点を確認しました。
リリース計画の早い段階で、Tiered Cacheの上位層として構成された大規模なデータセンターを含めます。これにより、グローバルリリースの前に、同様の問題にいち早く気づくことができるようになります。
受入試験の範囲を拡大し、様々なTiered Cacheトポロジーを含むより幅広い構成を含めます。
リクエストの完全なコンテキストを持たず、制御ヘッダーに追加のホスト情報が必要な状況において、より積極的にアラートを出します。
このようなエラーで当社のシステムが正しく早期に機能停止することを確認し、開発およびテスト中に問題を特定するのに役立ちました。
まとめ
Tiered Cacheをご利用の多数のお客様に影響を与えるインシデントを経験しました。欠陥のあるコンポーネントを特定した後、問題を迅速にロールバックし、修正できました。このため、サービスにアクセスしようとしたお客様やエンドユーザー様に混乱を招いてしまい、深くお詫び申し上げます。
今後、このような事態の発生を防止する改善策を、早急に講じる予定です。