複数のサービスレプリカがロードバランサーの後ろで実行されている場合、各インスタンス単位のレート制限では、サービス全体に対するリクエスト数の上限を強制できません。グローバルレート制限は、メッシュ内のすべての Envoy サイドカープロキシ間でリクエスト数を調整するために、中央集約型のサービスを使用します。
Service Mesh (ASM) V1.18.0.131 以降では、サイドカープロキシが注入されたサービスのインバウンドトラフィックに対してグローバルレート制限を設定するためのカスタムリソース (CR) ASMGlobalRateLimiter を提供しています。この CR は、低レベルの Envoy フィルター構成を抽象化した、安定的かつ宣言型の API を提供します。
本トピックでは、以下の 2 つのシナリオについて説明します:
ポートレベルのレート制限:特定のサービスポートへのすべてのリクエストを制限します。
パスレベルのレート制限:特定のサービスポート上の URL パスへのリクエストを制限します。
インスタンス単位のレート制限については、「トラフィック管理センターでのローカルレート制限の設定」をご参照ください。
グローバルレート制限とローカルレート制限の比較
アプローチ | 動作の仕組み | 推奨される用途 |
グローバルレート制限 | 中央集約型の gRPC サービス(Redis をバックエンドに使用)が、すべてのインスタンスにわたってリクエスト数を追跡します。 | レプリカ数に関係なく、サービス全体に対して厳密な上限値を適用する場合。 |
ローカルレート制限 | 各 Envoy サイドカープロキシが、それぞれ独立して制限を適用します。 | 個々のインスタンスを過負荷から保護する場合。外部依存関係は不要です。 |
仕組み
グローバルレート制限は、以下の 3 つのコンポーネントに依存します:
Redis — すべての Envoy サイドカープロキシ間で共有されるリクエストカウンターを格納します。
レート制限サービス — Envoy サイドカープロキシがリクエストを転送する前に照会する gRPC サービスです。Redis 内のカウンターを確認し、許可または拒否の判断を返します。
ASMGlobalRateLimiter CR — ASM コントロールプレーンに適用される宣言型の構成です。ASM はこれを Envoy フィルター構成に変換し、CR の
statusフィールド内にレート制限サービスの構成を生成します。
クライアントリクエスト --> Envoy サイドカープロキシ --> レート制限サービス (gRPC) --> Redis
|
許可または拒否 (HTTP 429)前提条件
ASM インスタンス (V1.18.0.131 以降) に追加済みの ACK マネージドクラスター。詳細については、「ASM インスタンスへのクラスターの追加」をご参照ください。
default名前空間に対して自動サイドカープロキシ注入が有効化されていること。詳細については、「グローバル名前空間の管理」の「自動サイドカープロキシ注入の有効化」セクションをご参照ください。ポート 80 が有効化された、
ingressgatewayという名前の ASM イングレスゲートウェイ。詳細については、「イングレスゲートウェイの作成」をご参照ください。サンプルアプリケーション
sleepおよびhttpbinがデプロイ済みであること。詳細については、「HTTPBin アプリケーションのデプロイ」および「sleep サービスのデプロイ」をご参照ください。
レート制限サービスのデプロイ
レート制限ルールの設定に先立ち、Redis およびレート制限サービスを ACK クラスターにデプロイします。
以下の内容で
ratelimit-svc.yamlというファイルを作成します:ACK クラスター内で以下のコマンドを実行して、サービスをデプロイします:
kubectl apply -f ratelimit-svc.yaml
シナリオ 1:サービスポート上のすべてのリクエストをレート制限する
このシナリオでは、HTTPBin サービスのポート 8000 へのすべてのリクエストを、1 分間に 1 回に制限します。
ワークフローは以下の 3 ステップで構成されます:ASM インスタンス上で ASMGlobalRateLimiter CR を作成し、生成された構成を ACK クラスター内のレート制限サービスに同期させ、検証を行います。
ステップ 1:ASMGlobalRateLimiter CR の作成
global-ratelimit-svc.yamlというファイルを作成します:以下の表では、主なフィールドについて説明します。全フィールドのリファレンスについては、「ASMGlobalRateLimiter フィールドの説明」をご参照ください。
フィールド
説明
workloadSelector対象のワークロードを選択します。
app: httpbinを設定することで、HTTPBin サービスにレート制限を適用します。isGatewayこのルールがイングレスゲートウェイではなくサイドカープロキシワークロードを対象とするため、
falseに設定します。rateLimitServiceレート制限サービスへの接続設定:ホスト名、gRPC ポート (8081)、タイムアウト (5 秒)。
limitレート制限のしきい値。
unit: MINUTEおよびquota: 1は、一致したルートに対して 1 分間に 1 回のリクエストを許可することを意味します。vhostバーチャルホストとのマッチングを行います。
name: '*'とport: 8000を組み合わせることで、HTTPBin サービスのポート 8000 へのすべてのリクエストにルールを適用します。ASM インスタンス内で以下のコマンドを実行して、CR を適用します:
kubectl apply -f global-ratelimit-svc.yaml
ステップ 2:レート制限構成のデータプレーンへの同期
ASM が CR を処理すると、status.config.yaml フィールド内にレート制限サービスの構成が生成されます。この構成を ACK クラスター内のレート制限サービスの ConfigMap にコピーする必要があります。ASM コントロールプレーンと ACK データプレーンが別々のクラスターで実行されるため、この手動による同期が必要です。
ASM インスタンスから生成された構成を取得します:
kubectl get asmglobalratelimiter global-svc-test -o yaml出力内で
statusセクションを特定します:ratelimit-config.yamlファイルを作成します。config.yamlの内容を、statusセクションから正確にコピーし、ConfigMap のdata.config.yamlフィールドに貼り付けます:重要config.yamlの値を、statusセクションから一切変更せずにコピーしてください。変更を行うと、レート制限サービスが構成を拒否します。ConfigMap を ACK クラスターに適用します:
kubectl apply -f ratelimit-config.yaml
検証
sleep Pod から HTTPBin ポート 8000 へ 2 回のリクエストを送信します:
kubectl exec -it deploy/sleep -- shその後、以下を実行します:
curl httpbin:8000/get -v
curl httpbin:8000/get -v2 回目のリクエストの期待される出力:
< HTTP/1.1 429
< x-envoy-ratelimited: true
< x-ratelimit-limit: 1, 1;w=60
< x-ratelimit-remaining: 0
< x-ratelimit-reset: 5
< date: Thu, 26 Oct 2023 04:23:54 GMT
< server: envoy
< content-length: 0
< x-envoy-upstream-service-time: 2
<
* Connection #0 to host httpbin left intact2 回目のリクエストが 429 を返すことで、グローバルレート制限が有効になっていることが確認できます。1 分間に HTTPBin サービスへのアクセスは 1 回のみ許可されます。2 回目のリクエストを送信すると、速度制限がトリガーされ、これはサイドカープロキシが注入されたサービスのインバウンドトラフィックに対してグローバルレート制限が適用されていることを示します。
シナリオ 2:特定のパスへのリクエストをレート制限する
このシナリオでは、HTTPBin ポート 8000 の /headers パスへのリクエストを 1 分間に 1 回に制限しますが、/get などの他のパスには無制限のアクセスを許可します。
構成は ASM のバージョンによって異なります。
ステップ 1:ASMGlobalRateLimiter CR の作成
ご使用の ASM バージョンに合った YAML を選択してください:
以下の表では、このシナリオで使用される追加フィールドについて説明します:
フィールド | 説明 |
| 適用される速度制限パラメーター。 |
| (V1.19.0+) 特定の条件に一致するリクエストに対して、基本のレート制限しきい値を上書きします。各オーバーライドは、独自の |
| 速度制限が適用されるドメイン名およびルート。V1.19.0 より前のバージョンでは、 |
| (V1.19.0 より前) |
ステップ 2:レート制限構成のデータプレーンへの同期
シナリオ 1 と同じ手順に従います:
ASM インスタンスから生成された構成を取得します:
kubectl get asmglobalratelimiter global-svc-test -o yamlconfig.yamlをstatusセクションからコピーし、ConfigMap に貼り付けて ACK クラスターに適用します:kubectl apply -f ratelimit-config.yaml
検証
sleep Pod から
/headersパスへ 2 回のリクエストを送信します:kubectl exec -it deploy/sleep -- shその後、以下を実行します:
curl httpbin:8000/headers -v curl httpbin:8000/headers -v2 回目のリクエストの期待される出力:
< HTTP/1.1 429 Too Many Requests < x-envoy-ratelimited: true < x-ratelimit-limit: 1, 1;w=60 < x-ratelimit-remaining: 0 < x-ratelimit-reset: 5 < date: Thu, 26 Oct 2023 04:23:54 GMT < server: envoy < content-length: 0 < x-envoy-upstream-service-time: 2 < * Connection #0 to host httpbin left intact/headersパスへの 2 回目のリクエストはレート制限されます。HTTPBin サービスの/headersパスへのアクセスは、1 分間に 1 回のみ許可されます。他のパスが影響を受けないことを確認します:
curl httpbin:8000/get -v/getパスへのリクエストは成功します。これは、/headersパスのみがレート制限の対象であるためです。
グローバルレート制限メトリックの監視
Envoy サイドカープロキシは、グローバルレート制限に関する以下のメトリックを公開します:
メトリック | タイプ | 説明 |
| カウンター | グローバル速度制限により許可されたリクエストの総数。 |
| カウンター | グローバル速度制限により、速度制限がトリガーされたと判定されたリクエストの総数。 |
| カウンター | グローバル速度制限への呼び出しに失敗したリクエストの総数。 |
メトリック報告の有効化
サイドカープロキシの
proxyStatsMatcherを構成します。正規表現マッチ を選択し、値を.*ratelimit.*に設定します。詳細については、「サイドカープロキシの構成」の「proxyStatsMatcher」セクションをご参照ください。新しいプロキシ構成を反映させるために、HTTPBin サービスを再デプロイします。詳細については、「サイドカープロキシの構成」の「(任意) ワークロードの再デプロイ」セクションをご参照ください。
グローバル速度制限を構成し、リクエストテストを実行します。詳細については、シナリオ 1 または「トラフィック管理センターでのローカルレート制限の設定」をご参照ください。
以下のコマンドを実行して、HTTPBin サービスのグローバル速度制限メトリックを表示します:
kubectl exec -it deploy/httpbin -c istio-proxy -- curl localhost:15090/stats/prometheus|grep envoy_cluster_ratelimit出力例:
# TYPE envoy_cluster_ratelimit_ok counter envoy_cluster_ratelimit_ok{cluster_name="inbound|80||"} 904 # TYPE envoy_cluster_ratelimit_over_limit counter envoy_cluster_ratelimit_over_limit{cluster_name="inbound|80||"} 3223
Prometheus アラートの設定
Managed Service for Prometheus を使用して、レート制限メトリックを収集し、レート制限が発生した際にアラートをトリガーします。
ACK クラスターを Managed Service for Prometheus の Alibaba Cloud ASM コンポーネントに接続するか、コンポーネントを最新バージョンにアップグレードします。詳細については、「コンポーネントの管理」をご参照ください。
説明すでに自己管理型の Prometheus インスタンスを使用して ASM メトリックを収集している場合は、この手順をスキップしてください。詳細については、「自己管理型 Prometheus インスタンスを使用した ASM インスタンスの監視」をご参照ください。
以下の PromQL およびメッセージテンプレートでカスタムアラートルールを作成します。詳細な手順については、「カスタム PromQL 文によるアラートルールの作成」をご参照ください。このルールは、ローリング 1 分間のウィンドウ内で、任意のサービスが 1 件以上のレート制限リクエストを発生させた場合に発火し、名前空間およびサービス名でグループ化されます。
パラメーター
例の値
PromQL 文
(sum by(namespace, service_istio_io_canonical_name) (increase(envoy_cluster_ratelimit_over_limit[1m]))) > 0アラートメッセージ
グローバルレート制限がトリガーされました。名前空間:{{$labels.namespace}}。サービス:{{$labels.service_istio_io_canonical_name}}。過去 1 分間のレート制限リクエスト数:{{ $value }}
次のステップ
イングレスゲートウェイのレート制限:サイドカープロキシレベルではなく、メッシュのエッジでグローバルレート制限を適用します。詳細については、「イングレスゲートウェイでのグローバルレート制限の設定」をご参照ください。
ローカルレート制限:防御の多層化のために、インスタンス単位の制限と組み合わせて使用します。詳細については、「トラフィック管理センターでのローカルレート制限の設定」をご参照ください。
フィールドリファレンス:細かい制御のための利用可能なすべてのフィールドを確認します。詳細については、「ASMGlobalRateLimiter フィールドの説明」をご参照ください。