Kubernetes APIサーバーの死角:DoS攻撃から見るクラスタ生存戦略
KubernetesのAPIサーバー(kube-apiserver)は、クラスタの心臓部だ。ここに異常が起きれば、ノードのスケジュールも、シークレットの取得も、Podのライフサイクル管理もすべてが停止する。多くのエンジニアが「認証さえ通せば安全」と高を括っているが、現実は甘くない。APIサーバーは本質的に「計算資源を消費するゲートウェイ」であり、その設計の根幹には、設計者が想定しきれなかったリソース枯渇のトリガーが潜んでいる。
本稿では、APIサーバーを標的としたDoS攻撃のメカニズムを紐解き、アーキテクチャレベルでいかにしてこの「心臓停止」を防ぐか、その防御の要諦を論じる。
—
1. なぜAPIサーバーは「叩かれる」のか:通信プロトコルとメモリの脆弱性
APIサーバーへのDoS攻撃の核心は、単なるパケットフラッドではない。もっと悪質なのは、kube-apiserverのメモリを枯渇させる「リスト&ウォッチ」操作や、非効率なシリアライズ処理だ。
メモリを食い潰す「巨大オブジェクト・リクエスト」
Kubernetes APIは通常、JSONまたはProtobufで通信する。攻撃者が巧妙なのは、APIサーバーが持つ「キャッシュ」を意図的に無効化し、バックエンドのetcdから大量のデータをフェッチさせ、それをメモリ上でシリアライズさせる負荷だ。特に、巨大なCRD(Custom Resource Definition)や、数万単位のラベルを持つオブジェクトを大量に作成・クエリするだけで、APIサーバーのGoランタイムはGC(ガベージコレクション)のループに陥り、CPU使用率を100%に張り付かせる。
2. 実践的防御:ResourceQuotaとLimitRangeの限界と真価
多くの現場ではResourceQuotaを「気休め」程度に考えている。しかし、これはAPIサーバーの保護という観点では、必須のガードレイルだ。
APIサーバーを守るための設定例
単にPodのリソースを制限するだけでなく、ネームスペース単位でAPIリクエストの爆発を防ぐ必要がある。以下は、悪意ある、あるいは無知な開発者によるリソースの乱用を防ぐための推奨設定だ。
# namespace-limit.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: critical-resource-limit
namespace: sensitive-app
spec:
hard:
# 同時に存在できるPod数を制限し、APIサーバーへの監視負荷を抑える
pods: "50"
# リクエストの総量を制限し、枯渇を防ぐ
requests.cpu: "10"
requests.memory: 20Gi
# 特に重要なのがこれ。APIの負荷となるオブジェクト作成を制限する
count/services: "20"
count/secrets: "10"
しかし、これだけでは足りない。真のプロフェッショナルは、APIServiceの優先順位と公平性(API Priority and Fairness: APF)を調整する。
—
3. APFによるトラフィック制御:APIサーバーの「免疫系」
Kubernetes 1.18以降で導入されたPriorityAndFairnessは、APIサーバーをDoSから守るための最も強力な武器だ。これは、リクエストを分類し、優先度の低いリクエストを「待機(Queue)」させる仕組みである。
以下の設定は、特定のサービスアカウントがAPIサーバーを占有するのを防ぐための構成例だ。
# flow-schema.yaml
apiVersion: flowcontrol.apiserver.k8s.io/v1beta3
kind: FlowSchema
metadata:
name: restrict-low-priority-traffic
spec:
priorityLevelConfiguration:
name: limited-priority # 制限をかける優先度グループ
matchingPrecedence: 500
rules:
- subjects:
- kind: ServiceAccount
serviceAccount:
name: untrusted-app
namespace: default
resourceRules:
- verbs: ["list", "watch"] # 特に重いこれらの操作を制限する
resources: ["*"]
namespaces: ["*"]
この設定により、untrusted-appがどれだけ激しくAPIを叩こうとも、APIサーバーはシステムコンポーネント(kube-schedulerやkube-controller-manager)の通信を阻害することなく、安全にリクエストをキューイングできる。
—
4. 次世代への備え:AIと耐量子暗号の視点から
今、私たちが直面しているのは単なるDoSではない。生成AIによる自動化された攻撃コード生成や、暗号解読技術の進化に伴う通信の脆弱性だ。
- プロンプトインジェクションへの防御: もしAPIサーバーの背後でLLMが動いているなら、入力はすべて「コード」として扱うこと。
kubectlの実行結果をそのままLLMに投げているシステムがあれば、今すぐ隔離すべきだ。 - 通信の堅牢性: TLS 1.3の完全な強制は当然として、将来的な量子計算機による暗号解読を考慮し、サービスメッシュ(Istio等)を用いたポスト量子暗号(PQC)への移行パスをアーキテクチャ設計に組み込んでおくべきだ。
結びに代えて
Kubernetesは「設定の塊」だ。しかし、その設定が「何を守り、何を拒絶するか」を理解していないアーキテクトは、クラスタを自ら脆弱性に晒しているのと同じである。
APIサーバーへのDoSを防ぐことは、単なるインフラの安定化ではない。それは、システムという名の要塞において、唯一の門番を誰にも屈服させないという、エンジニアとしての矜持そのものである。
次にクラスタをデプロイする際、kubectl applyの前に一度自問してほしい。「このAPIリクエストの連鎖は、私のシステムを殺すか?」と。その問いこそが、最強の防御の第一歩となる。
コメント