shiichan

Cloudflare のセキュリティスキャンが 10 倍速に!ハード増設ゼロで毎秒 120 スキャン達成!

おつかれさま、しぃちゃんだよ!今日はね、Cloudflare のエンジニアたちがセキュリティスキャンの仕組みを 10 倍速に鍛え上げたっていう、めちゃくちゃ骨太な舞台裏の話を持ってきたよ!ハードウェアを増やさずに、コードとクエリの工夫だけでここまでやっちゃうなんて、しぃちゃんワクワクしちゃう!

Cloudflare Blog blog.cloudflare.com

なにが発表されたの?

これは Cloudflare Blog のエンジニアリング系記事で、同社の Security Insights というシステムをどうやってスケールさせたかを解説したものだよ。

Security Insights は、Cloudflare アカウントを定期的にスキャンして、セキュリティのリスクや設定ミスを見つけてくれる仕組み。裏側では Apache Kafka でイベントを流して、checker と呼ばれる Go 製のマイクロサービスがそれぞれの資産をスキャンし、結果を Postgres が支える内部 API に送る、っていう構成になっているの。

エンジニアリング系の記事だから、発表告知というより「どこが詰まっていて、どう直したか」という技術の深掘りが中心だよ。

今までどうだったの?

前の仕組みには、けっこう大きな悩みが 3 つあったんだって。

  • スキャンが 1〜2 週間に 1 回しか回らなくて、その間のセキュリティの穴に気づけない
  • 無料アカウントでは自動スキャンがオプトイン(自分でオンにする方式)で、多くのアカウントが守られていなかった
  • そもそもインフラが限界気味で、何百万件ものイベントがバックログに溜まり、API はしょっちゅうタイムアウト、プロセスがクラッシュすることもあった

目標はハッキリしていて、スループットを毎秒 10 スキャンから 100 スキャンへ、つまり 10 倍に引き上げること。しかもハードウェアは増やさずに、だよ!

これで何が変わるの?

チューニングの結果、スキャンの頻度がぐっと上がったの。

  • Free: 7 日ごと
  • Pro / Business: 3 日ごと
  • Enterprise: 毎日

しかも全顧客が対象になったから、これまで守りが薄かったアカウントもカバーされるようになったよ。さらに、アカウント・ゾーン・インサイト・インサイト種別といった細かい単位で、その場でスキャンを走らせるオンデマンド機能まで生まれたんだって。

深く潜ってみよう

ここからが本番!ボトルネックをどう潰したか、4 つのポイントを見ていくよ。

Kafka を並列で回す

パーティションを増やすと共有インフラに負担がかかっちゃうから、その代わりに並列処理でさばくことにしたの。checker はメッセージをバッチでまとめて受け取り、1 件ずつ別々の goroutine で処理するようにしたよ。さらに slow lane と fast lane というコンシューマーグループを分けて、処理の遅いメッセージが速いメッセージの足を引っ張らないようにしたんだって。

データベースのクエリをまとめる

元のコードは、インサイト 1 件ごとに INSERT を実行していたの。バッチには最大 50 万件のインサイトが含まれることがあって、そうなると API 1 回の呼び出しで 50 万回もの往復が発生しちゃう。これは重いよね。

そこで、小さめのデータには UNNEST を使って(ミリ秒で完了)、大きなデータには COPY を使う(巨大なセットも数秒で処理)、という 2 段構えに切り替えたよ。

API のレイテンシを解消する

API は Portland と Amsterdam のアクティブ-アクティブ構成だったんだけど、これが 50 ms を超えるレイテンシを生んでいたの。原文いわく、

Our average API call completed in 10 ms in Portland, but almost 3 seconds in Amsterdam!

Portland では平均 10 ms なのに、Amsterdam ではほぼ 3 秒!これがコネクションプールを食いつぶして、タイムアウトの原因になっていたんだって。

そこで、プライマリの Postgres がある Portland に寄せたアクティブ-パッシブ構成に切り替えたら、一晩でレイテンシ問題が解消したよ。

スケジューラを作り直す

元のスケジューラは、スキャンの分布に偏りがあって、大きなアカウントでは遅延が連鎖してしまっていたの。ここも 3 つの工夫で直したんだって。

  • ゾーンごとに独立したタイムスタンプでスケジュールする
  • 既存の last_scheduled_at の値をランダム化して偏りをならす
  • アカウント数やスキャン頻度をもとに 30 分ごとに自動で再計算する、適応的なレート制限を入れる

まとめ

  • Cloudflare が Security Insights のスキャン基盤を、ハード増設なしで 10 倍にスケールさせた舞台裏の話だよ
  • ピーク時には毎秒 120 スキャンを超えて、当初の 10 倍目標もクリア
  • Kafka の並列化、UNNEST / COPY によるクエリのバッチ化、アクティブ-パッシブへの切り替え、スケジューラの作り直しが効いた
  • スキャン頻度は Free が 7 日、Pro / Business が 3 日、Enterprise が毎日に短縮、しかも全顧客が対象に
  • 大規模システムのボトルネックを、増設ではなくコードとクエリの工夫で乗り越えたい、バックエンドやインフラ好きのエンジニアに刺さる 1 本だよ!