はじめに
ある日の早朝、普段は毎秒 200 件ほどを処理していたログイン API に、突然毎秒 4 万件のリクエストが押し寄せました。データベースのコネクションプールは一瞬で枯渇し、正常なユーザーは 504 Gateway Timeout に直面しました。トラフィックを追跡すると、数千の IP から同じエンドポイントへ同じペイロードが繰り返し送信されていました。典型的な L7 アプリケーション層攻撃でした。
こうした状況でまず思い浮かぶ防御線はアプリケーションコードです。しかしアプリケーションがリクエストを受け取ったということは、すでにコネクションが確立され、TLS ハンドシェイクが終わり、ワーカースレッドが占有されたということです。つまりコストはすでに発生しているのです。本当の防御は、リクエストが高価なリソースに到達する前、できるだけ外側で行われなければなりません。Kubernetes 環境では、その外側の境界がまさに **Ingress 層**です。
この記事では、Ingress 層でレートリミットをどう構成するか、分散環境で正確なカウントがなぜ難しいか、そして L3/L4 のボリューメトリック攻撃と L7 のアプリケーション攻撃をどのように異なる層で分離して防御するかを、実践的なコードとともに整理します。2026 年現在、Ingress API は事実上凍結(frozen)され、Gateway API が後継標準として定着しているため、両 API の関係とマイグレーションの観点も併せて確認していきます。
レートリミットの基本原理
なぜ L7 で制限するのか
ネットワーク防御は OSI 層ごとに役割が異なります。以下の表は、各層が何を見て何を防げるのかを整理したものです。
| 層 | 見える情報 | 防げるもの | 防げないもの |
| --- | --- | --- | --- |
| L3 (IP) | 送信元・宛先 IP | IP 単位の遮断、geo 遮断 | 正常 IP を偽装したボットネット |
| L4 (TCP/UDP) | ポート、コネクション状態 | SYN フラッド、コネクション数制限 | HTTP パス単位の細かい制御 |
| L7 (HTTP) | メソッド、パス、ヘッダー、クッキー | エンドポイント別 RPS、ユーザー別クォータ | 大容量ボリューメトリックフラッド |
要点は、**各層が最も得意とするものを防ぐべき**という点です。毎秒数百ギガビットのボリューメトリック攻撃を L7 Ingress で防ごうとすると、パケットがクラスタネットワークまで入り込み帯域を食いつぶした後でようやく遮断されます。逆に、特定のログインエンドポイントに毎秒 5 回制限といった細かいルールは、L3/L4 機器では表現できません。
トークンバケットとリーキーバケット
レートリミットアルゴリズムの二大柱はトークンバケット(token bucket)とリーキーバケット(leaky bucket)です。
[トークンバケット] [リーキーバケット]
補充レート r ──> ( バケット容量 b ) リクエスト ──> ( キュー容量 b ) ──> 流出レート r ──> 処理
│ │
リクエスト到着時にトークン 1 個消費 キューが満杯ならリクエスト破棄(drop)
トークンがなければ拒否(reject) 一定速度でのみ流出する
- **トークンバケット**: 平均速度 r を維持しつつ、バケット容量 b 分の瞬間バーストを許容します。短いスパイクを自然に吸収します。
- **リーキーバケット**: 出力速度を厳格に平滑化します。バーストを吸収せず、一定速度でのみ流出させます。
ingress-nginx のレートリミットは内部的に nginx の `limit_req`(リーキーバケットに近いモデル)と `limit_conn` を使います。burst パラメータで少しのバーストを許容する方式です。
ingress-nginx アノテーション詳解
ingress-nginx は Ingress リソースのアノテーションでレートリミットを宣言します。最もよく使われる 4 つを整理します。
| アノテーション | 意味 | 単位 |
| --- | --- | --- |
| limit-rps | 毎秒の許容リクエスト数 | requests per second |
| limit-rpm | 毎分の許容リクエスト数 | requests per minute |
| limit-connections | 同時コネクション数の制限 | connections |
| limit-burst-multiplier | burst 許容倍率(デフォルト 5) | multiplier |
次はログインエンドポイントを保護する Ingress の例です。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auth-ingress
namespace: production
annotations:
nginx.ingress.kubernetes.io/limit-rps: "5"
nginx.ingress.kubernetes.io/limit-burst-multiplier: "2"
nginx.ingress.kubernetes.io/limit-connections: "10"
信頼できる内部レンジは制限から除外
nginx.ingress.kubernetes.io/limit-whitelist: "10.0.0.0/8,192.168.0.0/16"
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /auth/login
pathType: Prefix
backend:
service:
name: auth-service
port:
number: 8080
ここで `limit-rps: 5` と `limit-burst-multiplier: 2` を併用すると、実際の burst 容量は毎秒 10 件まで許容されます。つまり平均 5 RPS を維持しつつ、瞬間的には 10 件まで通過させ、それ以上は 503 Service Temporarily Unavailable で拒否します。
キー(key)は何で取られるのか
ingress-nginx のデフォルトのレートリミットキーはクライアント IP です。しかしプロキシ・ロードバランサーの背後にいる場合は、実際のクライアント IP を正確に識別する必要があります。このとき鍵となる設定が ConfigMap の信頼設定です。
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
信頼するプロキシレンジ(例: クラウド LB の CIDR)
proxy-real-ip-cidr: "130.211.0.0/22,35.191.0.0/16"
use-forwarded-headers: "true"
compute-full-forwarded-for: "true"
`use-forwarded-headers` を有効にすると、X-Forwarded-For ヘッダーの IP をクライアントとして使います。ただしこのヘッダーはクライアントが偽造できるため、必ず信頼レンジ(`proxy-real-ip-cidr`)を併せて指定する必要があります。そうしないと、攻撃者がリクエストごとに偽の X-Forwarded-For 値を入れてカウンターを回避できます。
グローバル上限とカスタムレスポンス
すべての Ingress に共通で適用するデフォルト上限は ConfigMap で設定します。
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
limit-rate: "0" # レスポンス帯域制限(バイト/秒)、0 は無制限
limit-req-status-code: "429" # デフォルトの 503 の代わりに 429 Too Many Requests を返す
limit-conn-status-code: "429"
レートリミット拒否時のデフォルトレスポンスコードは 503 ですが、クライアントがバックオフ(backoff)を明確に認識できるよう `429 Too Many Requests` に変えるのが一般的です。可能であれば `Retry-After` ヘッダーも併せて返すのが望ましいです。
Traefik / Kong / APISIX の比較
ingress-nginx が最も広く使われますが、運用環境や要件によって別のコントローラーを選ぶこともあります。レートリミットの観点で比較すると以下のようになります。
| 項目 | ingress-nginx | Traefik | Kong | APISIX |
| --- | --- | --- | --- | --- |
| 設定方式 | アノテーション | Middleware CRD | Plugin (KongPlugin) | Plugin / Route |
| アルゴリズム | リーキーバケット系 | スライディングウィンドウ平均 | 固定/スライディングウィンドウ | トークン/リーキーバケットなど多様 |
| 分散カウント | デフォルト非対応(per-pod) | デフォルト非対応 | Redis 対応 | Redis クラスタ対応 |
| キーのカスタマイズ | 限定的 | ソース基準 | consumer/IP/header | 変数ベースで柔軟 |
| 拒否レスポンスコード | 設定可能 | 設定可能 | 429 デフォルト | 設定可能 |
Traefik Middleware
Traefik は Middleware CRD でレートリミットを宣言します。
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: api-ratelimit
namespace: production
spec:
rateLimit:
average: 100 # 平均毎秒 100 リクエスト
burst: 50 # 瞬間 50 バーストを許容
period: 1s
sourceCriterion:
ipStrategy:
depth: 1 # X-Forwarded-For の末尾から 1 番目の IP を使う
Kong Plugin
Kong は KongPlugin リソースで宣言し、Redis をバックエンドに指定すると分散カウントが可能になります。
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: rate-limiting-redis
namespace: production
plugin: rate-limiting
config:
minute: 60
policy: redis
redis_host: redis.production.svc.cluster.local
redis_port: 6379
fault_tolerant: true
APISIX Route
APISIX は limit-req、limit-conn、limit-count プラグインを提供し、Redis クラスタを通じたグローバルカウントをサポートします。
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: api-route
namespace: production
spec:
http:
- name: limited
match:
hosts:
- api.example.com
paths:
- /api/*
backends:
- serviceName: api-service
servicePort: 8080
plugins:
- name: limit-count
enable: true
config:
count: 200
time_window: 60
rejected_code: 429
policy: redis
redis_host: redis.production.svc.cluster.local
redis_port: 6379
分散環境のカウント問題
ここからが実務で最も足を引っ張られる地点です。Ingress コントローラーは通常、複数のポッド(replica)で稼働しています。各ポッドが自分のメモリにカウンターを持っていると、全体の上限は意図した値の倍数になってしまいます。
[ クライアントトラフィック ]
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ ingress pod1 │ │ ingress pod2 │ │ ingress pod3 │
│ メモリカウンター│ │ メモリカウンター│ │ メモリカウンター│
│ 上限 100 │ │ 上限 100 │ │ 上限 100 │
└──────────────┘ └──────────────┘ └──────────────┘
意図した上限: 100 RPS → 実際の許容: 最大 300 RPS (ポッド数 x 100)
In-memory 方式の特性を整理すると以下のようになります。
| 方式 | 精度 | レイテンシ | 障害耐性 | 運用の複雑さ |
| --- | --- | --- | --- | --- |
| In-memory (per-pod) | 低い(ポッド数だけ倍増) | 最速 | 高い | 低い |
| Redis 中央カウンター | 高い | ネットワーク 1 ホップ追加 | Redis 障害に脆弱 | 高い |
ingress-nginx のデフォルト実装は per-pod メモリ方式なので、上限を設定する際は **レプリカ数で割って** 設定すると意図したグローバル上限に近づきます。例えばグローバル 300 RPS を望み、ポッドが 3 個ならポッドあたり 100 RPS に設定する形です。ただし HPA でポッド数が変わるとグローバル上限も追随して変わる点に注意が必要です。
正確なグローバルカウントが必要なら、Redis のような中央ストアをバックエンドに使う Kong、APISIX を選ぶか、ingress-nginx の前段に別途レートリミットゲートウェイを置く構成を検討します。Redis を使う際は次の設定が重要です。
- アトミックカウント: INCR + EXPIRE または Lua スクリプトで race condition を排除
- fault tolerant モード: Redis 障害時にリクエストを止めるか(fail-closed)通すか(fail-open)決める
- キー有効期限: ウィンドウ単位でキーが正確に失効するようスライディング/固定ウィンドウを選択
- レイテンシ予算: Redis 往復が p99 レイテンシに与える影響を計測
fail-open と fail-closed はトレードオフです。Redis が落ちたとき、fail-open は可用性を守るものの攻撃に晒され、fail-closed は安全ですが正常トラフィックまで止めます。ログイン・決済のような機微なエンドポイントは fail-closed、一般的な参照 API は fail-open を推奨します。
ホワイトリストと地域(geo)制御
すべてのトラフィックを同じように制限してはいけません。信頼できるパートナー、内部モニタリング、ヘルスチェックは除外すべきです。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: partner-api
namespace: production
annotations:
nginx.ingress.kubernetes.io/limit-rps: "20"
ホワイトリストレンジはレートリミットを回避
nginx.ingress.kubernetes.io/limit-whitelist: "203.0.113.0/24,198.51.100.10/32"
spec:
ingressClassName: nginx
rules:
- host: partner.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: partner-service
port:
number: 80
地域遮断は GeoIP モジュールで実装します。ingress-nginx は nginx の GeoIP2 モジュールを通じて国コードベースの制御をサポートします。
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
use-geoip2: "true"
特定の国だけ許可または遮断するポリシーは server-snippet で記述
ただし GeoIP 遮断は VPN・プロキシで容易に回避されるため、単独防御ではなく補助シグナルとして活用するのが現実的です。正常なユーザーがまったくいない地域から来る攻撃的トラフィックを 1 次的にふるい落とす用途に適しています。
L3/L4 DDoS と L7 防御の分離
最もよくある設計ミスは、すべての DDoS を Ingress 一か所で防ごうとすることです。ボリューメトリック攻撃(L3/L4)とアプリケーション攻撃(L7)は防御位置そのものが異なるべきです。
[インターネット]
│
▼
┌──────────────────────────────────────────────┐
│ クラウドエッジ (CDN / Anycast / スクラビング) │ <- L3/L4 ボリューメトリック防御
│ - SYN フラッド、UDP アンプ、大容量パケットを吸収 │ (AWS Shield, Cloud Armor など)
└──────────────────────────────────────────────┘
│ (正常に近いトラフィックのみ通過)
▼
┌──────────────────────────────────────────────┐
│ Ingress 層 (ingress-nginx / Gateway) │ <- L7 アプリケーション防御
│ - エンドポイント別 RPS、コネクション制限、WAF ルール │ (レートリミット、ボット遮断)
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ アプリケーション (サービス/ポッド) │ <- ビジネスロジッククォータ
│ - ユーザー別クォータ、冪等性、サーキットブレーカー │
└──────────────────────────────────────────────┘
各層の役割分担を表に整理すると以下のようになります。
| 攻撃タイプ | 例 | 防御位置 | ツール |
| --- | --- | --- | --- |
| ボリューメトリック (L3/L4) | SYN フラッド、UDP アンプ | クラウドエッジ | Shield, Cloud Armor, スクラビング |
| プロトコル (L4) | コネクション枯渇、slowloris | エッジ + Ingress | コネクション制限、タイムアウト |
| アプリケーション (L7) | HTTP フラッド、キャッシュバスティング | Ingress + アプリ | レートリミット、WAF |
クラウドエッジでボリューメトリックを吸収すれば、Ingress まで到達するトラフィックはすでにかなり精製された状態です。この段階で Ingress は L7 ルールだけに集中できます。逆にエッジ保護なしで Ingress 単独で数百ギガビットを受けると、ノードの NIC 帯域と conntrack テーブルが先に崩れます。
slowloris のような低速攻撃は別途注意が必要です。少ない帯域でコネクションだけを長く占有する攻撃なので、次のようにタイムアウトを短く設定して防御します。
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
client-header-timeout: "10"
client-body-timeout: "10"
keep-alive-requests: "100"
worker-shutdown-timeout: "30s"
ボットトラフィック対応
DDoS の相当数はボットネットが引き起こします。ボットと正常ユーザーを区別するシグナルはいくつかあります。
[ボット識別シグナル]
- User-Agent の欠落または異常なパターン
- クッキー/セッションを維持しないステートレスな繰り返しリクエスト
- JavaScript チャレンジを通過できない
- TLS フィンガープリント(JA3/JA4)が既知のボットツールと一致
- 異常に均一なリクエスト間隔(人間にはジッターがある)
Ingress 層では、単純な User-Agent 遮断やヘッダー検証程度が可能です。server-snippet で空の User-Agent を拒否する例です。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: bot-protect
namespace: production
annotations:
nginx.ingress.kubernetes.io/server-snippet: |
if ($http_user_agent = "") {
return 403;
}
if ($http_user_agent ~* "(curl|wget|python-requests|scrapy)") {
return 403;
}
spec:
ingressClassName: nginx
rules:
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
ただし User-Agent は簡単に偽造されるため、精巧なボットには効果が限定的です。JavaScript チャレンジや JA3/JA4 フィンガープリンティングのような高度なボット管理機能は通常 CDN・WAF 層(クラウドエッジ)で処理し、Ingress は 1 次フィルターの役割を担うのが合理的です。
負荷シナリオで見る動作
設定値を決める際は、具体的なシナリオで検証する必要があります。以下は普段 200 RPS、上限 300 RPS(burst 含め 600)の API に 3 つの状況が発生したときの動作です。
| シナリオ | 入力トラフィック | 通過 | 拒否(429) | ユーザー体感 |
| --- | --- | --- | --- | --- |
| 正常ピーク | 280 RPS | 280 | 0 | 正常 |
| マーケティングスパイク | 550 RPS (10 秒) | 約 600(バースト吸収後に平滑化) | 一部 | わずかに遅延 |
| L7 フラッド | 40000 RPS | 300 | 39700 | 正常ユーザーは保護される |
3 つ目のシナリオがレートリミットの存在理由です。4 万 RPS が入ってきてもバックエンドには上限分だけ伝わり、残りは Ingress で 429 として切り落とされるので、データベースとアプリケーションは保護されます。拒否されたリクエストの処理コストは、バックエンド処理コストに比べて無視できるほど小さいです。
負荷テストは実際のデプロイ前に必ず実施します。次は簡単な検証コマンドの例です。
hey で同時 200、合計 20000 リクエストを発射
hey -z 30s -c 200 https://api.example.com/api/items
拒否率を確認するためレスポンスコード分布を集計
hey -z 30s -c 500 https://api.example.com/auth/login \
| grep -A20 "Status code distribution"
Gateway API との関係
2026 年現在、Ingress API は新機能追加が止まった凍結状態であり、後継標準は **Gateway API** です。Gateway API は役割分離(インフラ運用者 / クラスタ運用者 / アプリ開発者)、プロトコル拡張性、表現力のあるルーティングを目標に設計されています。
| 観点 | Ingress | Gateway API |
| --- | --- | --- |
| 標準の状態 | 凍結 (frozen) | 活発に発展中 |
| リソース | Ingress 単一 | GatewayClass / Gateway / HTTPRoute など |
| 役割分離 | 弱い | 明示的(RBAC フレンドリー) |
| レートリミット | 実装のアノテーション | ポリシーアタッチメント + 実装拡張 |
| トラフィック分割 | アノテーション | 重みベースの標準フィールド |
ただしレートリミットは Gateway API の標準仕様に完全には含まれておらず、実装ごとのポリシー(policy attachment)や拡張フィルターで提供されることが多いです。したがってマイグレーション時には、使っている実装がレートリミットをどの方式で公開しているかを確認する必要があります。
ingress-nginx は 2025 年を境に事実上メンテナンス(maintenance)モードに入り、セキュリティ脆弱性対応中心に運用される傾向です。新規クラスタを設計するなら、Gateway API ベースの実装(例: Envoy Gateway、Traefik の Gateway 対応、Cilium Gateway など)を優先的に検討するのが長期的に安全です。次は簡単な HTTPRoute の例です。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-route
namespace: production
spec:
parentRefs:
- name: prod-gateway
hostnames:
- api.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-service
port: 8080
運用とチューニング
可観測性の確保
レートリミットは有効にして終わりではありません。どれだけ拒否されているか、拒否されたトラフィックが攻撃なのか正常ユーザーなのかを絶えず観測する必要があります。
[観測指標]
- 429/503 レスポンス比率(全体に対する)
- 拒否されたリクエストの IP/パス/User-Agent 分布
- バックエンドの p50/p95/p99 レイテンシ変化
- Ingress ポッドの CPU/メモリ/コネクション数
- upstream 5xx 比率(上限が効果的か判断)
Prometheus で ingress-nginx メトリクスを収集すれば、`nginx_ingress_controller_requests` の status ラベルで 429 比率を追跡できます。拒否率が急に跳ね上がれば、攻撃か、上限が厳しすぎるかのどちらかです。
段階的な適用
レートリミットを本番にいきなり強くかけると、正常ユーザーが遮断されるリスクがあります。次の順序を推奨します。
1. 観測モード: 上限を非常に高く設定し拒否なしでメトリクスのみ収集
2. ベースライン把握: 普段のピーク RPS、p99、正常なバーストパターンを分析
3. 保守的な適用: 普段のピークの 3〜5 倍を上限に設定
4. 漸進的な強化: 拒否率とユーザー影響を見ながら上限を調整
5. エンドポイント差別化: ログイン/決済は厳格、静的参照は緩く
よくある落とし穴とトラブルシューティング
実務で繰り返し遭遇する落とし穴を整理します。
[落とし穴 1] X-Forwarded-For 未設定
→ すべてのリクエストが LB の IP 1 つにカウントされ全体が一斉に遮断される
→ proxy-real-ip-cidr と use-forwarded-headers を必ず併せて設定
[落とし穴 2] per-pod カウントをグローバルと誤解
→ 上限 100 なのにポッド 3 個で実際は 300 まで許容される
→ レプリカ数で割って設定するか中央カウンター(Redis)を導入
[落とし穴 3] ヘルスチェック/プローブがレートリミットに引っかかる
→ kubelet プローブやモニタリングが 429 を受けてポッドが落ちる
→ 内部レンジを whitelist に追加
[落とし穴 4] 拒否コードを 503 のまま放置
→ クライアントがサーバー障害と誤認し無限リトライ → 悪循環
→ 429 + Retry-After でバックオフを誘導
[落とし穴 5] L7 でボリューメトリックを防ごうとする
→ パケットがノードまで入り NIC/conntrack が先に飽和
→ ボリューメトリックはクラウドエッジで吸収
[落とし穴 6] 上限を低く設定しすぎる
→ 正常ピークでも 429 が発生しユーザー離脱
→ 観測モードでベースラインからまず計測
デバッグコマンド
問題が疑われるときに素早く確認できるコマンドです。
Ingress コントローラーのログから limiting 関連メッセージを確認
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller | grep -i limit
実際に適用された nginx 設定を確認(生成された limit_req ゾーンを検証)
kubectl exec -n ingress-nginx deploy/ingress-nginx-controller -- \
cat /etc/nginx/nginx.conf | grep -A3 limit_req_zone
特定 IP から見えるレスポンスコード分布を素早く点検
for i in $(seq 1 20); do
curl -s -o /dev/null -w "%{http_code}\n" https://api.example.com/auth/login
done | sort | uniq -c
運用チェックリスト
デプロイ前の最終点検リストです。
[ ] エンドポイント別に上限を差別化して設定したか(ログイン厳格、参照緩く)
[ ] X-Forwarded-For 信頼レンジ(proxy-real-ip-cidr)を正確に指定したか
[ ] 拒否レスポンスを 429 + Retry-After に設定したか
[ ] ヘルスチェック/モニタリング/内部レンジを whitelist に入れたか
[ ] per-pod vs Redis カウント方式を意図どおり選択したか
[ ] レプリカ数変動(HPA)がグローバル上限に与える影響を考慮したか
[ ] L3/L4 ボリューメトリック防御をクラウドエッジに配置したか
[ ] slowloris 対策にタイムアウトを短く設定したか
[ ] 429/503 比率とバックエンドレイテンシをダッシュボードで観測中か
[ ] 負荷テストで上限の動作を事前検証したか
[ ] Gateway API マイグレーション経路を検討したか
おわりに
レートリミットと DDoS 緩和の核心は、**層ごとに適切な位置で適切な攻撃を防ぐこと**です。ボリューメトリック攻撃はクラウドエッジで、アプリケーション層の濫用は Ingress で、ビジネスルール違反はアプリケーションで防ぐべきです。どこか一つの層にすべての責任を寄せれば必ず崩れます。
分散環境のカウント問題は特に静かに人を欺きます。per-pod メモリカウントをグローバル上限と勘違いすると、設定した値の数倍までトラフィックが漏れ出ます。正確性が重要なら中央カウンターを導入しつつ、Redis 障害時の fail-open/fail-closed ポリシーを明確に定めておく必要があります。
最後に、2026 年の方向性は明確です。Ingress API は凍結され、ingress-nginx はメンテナンスモードに入り、Gateway API が後継標準として定着しつつあります。今運用中の ingress-nginx 設定をしっかり整えつつ、新規設計では Gateway API ベースの実装とそのレートリミットモデルを積極的に検討されることをお勧めします。
参考資料
- Kubernetes Ingress の概念: https://kubernetes.io/docs/concepts/services-networking/ingress/
- Gateway API 公式ドキュメント: https://gateway-api.sigs.k8s.io/
- ingress-nginx アノテーションリファレンス: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/
- ingress-nginx レートリミットガイド: https://kubernetes.github.io/ingress-nginx/examples/customization/custom-configuration/
- Traefik Rate Limit ミドルウェア: https://doc.traefik.io/traefik/middlewares/http/ratelimit/
- Kong Rate Limiting プラグイン: https://docs.konghq.com/hub/kong-inc/rate-limiting/
- Apache APISIX limit-count プラグイン: https://apisix.apache.org/docs/apisix/plugins/limit-count/
- AWS Shield ドキュメント: https://docs.aws.amazon.com/waf/latest/developerguide/shield-chapter.html
- Google Cloud Armor ドキュメント: https://cloud.google.com/armor/docs/security-policy-overview
- nginx limit_req モジュール: https://nginx.org/en/docs/http/ngx_http_limit_req_module.html
현재 단락 (1/366)
ある日の早朝、普段は毎秒 200 件ほどを処理していたログイン API に、突然毎秒 4 万件のリクエストが押し寄せました。データベースのコネクションプールは一瞬で枯渇し、正常なユーザーは 504 G...