【テクニカル・上級編】 Kubernetes APIサーバーのDoS攻撃対策とレート制限 – インフラ・ネットワーク & クラウドセキュリティ防御ガイド

Kubernetes APIサーバーを「底なし沼」にしないために:レート制限の深層

KubernetesのAPIサーバー(kube-apiserver)は、クラスターの心臓部だ。しかし、多くのエンジニアはこの心臓が「リクエストの洪水」に対してどれほど脆弱であるかを直視できていない。APIサーバーへのDoS攻撃は、単にサービスを落とすだけでなく、etcdのI/Oを飽和させ、クラスター全体のコンセンサスを破壊し、最悪の場合はリカバリー不能な状態に陥らせる。

今日は、教科書的な設定の話は端折り、攻撃者がAPIサーバーのどこを突こうとしているのか、そして我々がどう防衛すべきか、そのアーキテクチャの急所を掘り下げる。

1. なぜ API Server は「リクエストの洪水」に弱いのか

攻撃者が狙うのは、kube-apiserverのメモリ消費と、その背後にあるetcdへのI/O負荷の非対称性だ。

APIサーバーは、リクエストの認証・認可・検証を行う過程で、大量のメモリを消費する。特に、複雑なJSONパッチや巨大なCustom Resource Definition(CRD)の投入は、シリアライズ処理中にCPUサイクルとメモリを浪費させる。もし攻撃者が、認証済みのServiceAccountを奪取し、短時間に数万リクエストを投げ込んだらどうなるか。APIサーバーがOOM(Out of Memory)キラーに殺され、コントロールプレーンが沈黙する。これは、パッチが適用されていない古いカーネルのメモリ管理の不備を突くよりも、はるかに効率的な「ロジックの破壊」だ。

2. MaxRequestsInFlight:物理的なゲートキーパー

まず基本となるのが MaxRequestsInFlight だ。これはAPIサーバーが同時に処理できるリクエストの最大数を物理的に制限する。

# kube-apiserver の起動引数設定例
--max-requests-inflight=400        # 非変更系(GET/LIST)の同時リクエスト上限
--max-mutating-requests-inflight=200 # 変更系(POST/PUT/PATCH/DELETE)の同時リクエスト上限

この値の選定は「勘」ではなく、「クラスター内のコントローラー数 × 期待される同時接続数」の統計データに基づかなければならない。ここで重要なのは、「変更系(Mutating)のリクエストをいかに厳格に制限するか」だ。GETリクエストはキャッシュが効くこともあるが、POST/PATCHは確実にetcdへの書き込みを伴う。ここを絞ることで、DoS発生時にも「クラスターを破壊する書き込み」を遮断し、コントロールプレーンの死守が可能になる。

3. API Priority and Fairness (APF) による粒度の高い制御

MaxRequestsInFlight は「全体の上限」という粗い網でしかない。現代のセキュリティ設計では、PriorityLevelConfiguration と FlowSchema を活用した「API Priority and Fairness (APF)」の実装が必須だ。

APFは、リクエストをカテゴリ(User, ServiceAccount, Controllerなど)ごとに分類し、キューイングと公平なリソース配分を行う。

# 特定のServiceAccountに対するレート制限の適用例
apiVersion: flowcontrol.apiserver.k8s.io/v1beta3
kind: FlowSchema
metadata:
  name: restricted-service-account
spec:
  priorityLevelConfiguration:
    name: limited-priority # 制限をかける優先度クラス
  matchingPrecedence: 500
  rules:
  - resourceRules:
    - apiGroups: ["*"]
      resources: ["*"]
      verbs: ["*"]
    subjects:
    - kind: ServiceAccount
      serviceAccount:
        name: untrusted-app # 制限したい対象のSA
        namespace: default

このように、信頼の置けないワークロードには個別の FlowSchema を適用し、リソース消費を厳格に切り離す。もし特定のワークロードが暴走しても、他のクリティカルなコントローラー(CoreDNSやCNIプラグインなど)には影響を及ぼさない「防波堤」を築くのが、チーフホワイトハッカーの矜持だ。

4. セキュリティアーキテクトが考慮すべき「盲点」

APIサーバーの防御において、私が特に注意を払っているのは以下の2点だ。

  • Watchリクエストの爆発: 攻撃者は、単なるリクエストではなく、大量の watch を仕掛けてくる。これはAPIサーバーに常時接続を強要し、メモリを握りつぶす手法だ。--max-mutating-requests-inflight だけでは防げない。必ず kube-apiserver のメトリクスを監視し、apiserver_request_total の verb="watch" が急増していないかアラートを飛ばすべきだ。
  • 通信プロトコルの脆弱性: 多くのKubernetesクラスターが依然としてHTTP/2のストリーム多重化に依存している。HTTP/2のプロトコル特性を突いた「Stream Multiplexing DoS」は、ファイアウォール越しでも侵入可能だ。APIサーバーの前段に置くロードバランサー(あるいはIngress Controller)で、リクエストヘッダーのサイズ制限と、接続あたりの最大ストリーム数を絞ることが、低レイヤの生存戦略となる。

結びに:防御は「静的な設定」ではなく「動的な適応」

我々が守るべきは、設定ファイルの中身ではない。刻々と変化する脅威のコンテキストだ。

APIサーバーの要塞化は、一度設定して終わりというものではない。生成AIの台頭により、今後はプロンプトインジェクションを通じてAPIサーバーを悪用する攻撃も現実味を帯びてくる。APIサーバーのログをAIで解析し、正常なトラフィックパターンから外れた「異常なAPIコール」をリアルタイムで検知するガードレイルの構築。それが、次世代のセキュリティアーキテクトが取り組むべき「泥臭い最前線」だ。

君たちのクラスターは、今この瞬間も、静かに攻撃を受けていないか? メトリクスを疑い、ログを疑い、そして何より、自分たちが設定した「制限値」が本当に適切なのか、常にプロトコルレベルで再評価してほしい。セキュリティは、疑い続けることの積み重ねに他ならないのだから。

コメント

タイトルとURLをコピーしました