すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Service Mesh:サイドカープロキシのインバウンドトラフィックに対するグローバルレート制限の設定

最終更新日:Mar 11, 2026

複数のサービスレプリカがロードバランサーの後ろで実行されている場合、各インスタンス単位のレート制限では、サービス全体に対するリクエスト数の上限を強制できません。グローバルレート制限は、メッシュ内のすべての Envoy サイドカープロキシ間でリクエスト数を調整するために、中央集約型のサービスを使用します。

Service Mesh (ASM) V1.18.0.131 以降では、サイドカープロキシが注入されたサービスのインバウンドトラフィックに対してグローバルレート制限を設定するためのカスタムリソース (CR) ASMGlobalRateLimiter を提供しています。この CR は、低レベルの Envoy フィルター構成を抽象化した、安定的かつ宣言型の API を提供します。

本トピックでは、以下の 2 つのシナリオについて説明します:

  • ポートレベルのレート制限:特定のサービスポートへのすべてのリクエストを制限します。

  • パスレベルのレート制限:特定のサービスポート上の URL パスへのリクエストを制限します。

説明

インスタンス単位のレート制限については、「トラフィック管理センターでのローカルレート制限の設定」をご参照ください。

グローバルレート制限とローカルレート制限の比較

アプローチ

動作の仕組み

推奨される用途

グローバルレート制限

中央集約型の gRPC サービス(Redis をバックエンドに使用)が、すべてのインスタンスにわたってリクエスト数を追跡します。

レプリカ数に関係なく、サービス全体に対して厳密な上限値を適用する場合。

ローカルレート制限

各 Envoy サイドカープロキシが、それぞれ独立して制限を適用します。

個々のインスタンスを過負荷から保護する場合。外部依存関係は不要です。

仕組み

グローバルレート制限は、以下の 3 つのコンポーネントに依存します:

  1. Redis — すべての Envoy サイドカープロキシ間で共有されるリクエストカウンターを格納します。

  2. レート制限サービス — Envoy サイドカープロキシがリクエストを転送する前に照会する gRPC サービスです。Redis 内のカウンターを確認し、許可または拒否の判断を返します。

  3. ASMGlobalRateLimiter CR — ASM コントロールプレーンに適用される宣言型の構成です。ASM はこれを Envoy フィルター構成に変換し、CR の status フィールド内にレート制限サービスの構成を生成します。

クライアントリクエスト --> Envoy サイドカープロキシ --> レート制限サービス (gRPC) --> Redis
                       |
              許可または拒否 (HTTP 429)

前提条件

レート制限サービスのデプロイ

レート制限ルールの設定に先立ち、Redis およびレート制限サービスを ACK クラスターにデプロイします。

  1. 以下の内容で ratelimit-svc.yaml というファイルを作成します:

    ratelimit-svc.yaml

    apiVersion: v1
       kind: ServiceAccount
       metadata:
         name: redis
       ---
       apiVersion: v1
       kind: Service
       metadata:
         name: redis
         labels:
           app: redis
       spec:
         ports:
         - name: redis
           port: 6379
         selector:
           app: redis
       ---
       apiVersion: apps/v1
       kind: Deployment
       metadata:
         name: redis
       spec:
         replicas: 1
         selector:
           matchLabels:
             app: redis
         template:
          metadata:
             labels:
               app: redis
               sidecar.istio.io/inject: "false"
          spec:
             containers:
             - image: redis:alpine
               imagePullPolicy: Always
               name: redis
               ports:
               - name: redis
                 containerPort: 6379
             restartPolicy: Always
             serviceAccountName: redis
       ---
       apiVersion: v1
       kind: ConfigMap
       metadata:
         name: ratelimit-config
       data:
         config.yaml: |
           {}
       ---
       apiVersion: v1
       kind: Service
       metadata:
         name: ratelimit
         labels:
           app: ratelimit
       spec:
         ports:
         - name: http-port
           port: 8080
           targetPort: 8080
           protocol: TCP
         - name: grpc-port
           port: 8081
           targetPort: 8081
           protocol: TCP
         - name: http-debug
           port: 6070
           targetPort: 6070
           protocol: TCP
         selector:
           app: ratelimit
       ---
       apiVersion: apps/v1
       kind: Deployment
       metadata:
         name: ratelimit
       spec:
         replicas: 1
         selector:
           matchLabels:
             app: ratelimit
         strategy:
           type: Recreate
         template:
           metadata:
             labels:
               app: ratelimit
               sidecar.istio.io/inject: "false"
           spec:
             containers:
               # 最新イメージは https://hub.docker.com/r/envoyproxy/ratelimit/tags から取得
             - image: envoyproxy/ratelimit:e059638d
               imagePullPolicy: Always
               name: ratelimit
               command: ["/bin/ratelimit"]
               env:
               - name: LOG_LEVEL
                 value: debug
               - name: REDIS_SOCKET_TYPE
                 value: tcp
               - name: REDIS_URL
                 value: redis:6379
               - name: USE_STATSD
                 value: "false"
               - name: RUNTIME_ROOT
                 value: /data
               - name: RUNTIME_SUBDIRECTORY
                 value: ratelimit
               - name: RUNTIME_WATCH_ROOT
                 value: "false"
               - name: RUNTIME_IGNOREDOTFILES
                 value: "true"
               ports:
               - containerPort: 8080
               - containerPort: 8081
               - containerPort: 6070
               volumeMounts:
               - name: config-volume
                 # $RUNTIME_ROOT/$RUNTIME_SUBDIRECTORY/$RUNTIME_APPDIRECTORY/config.yaml
                 mountPath: /data/ratelimit/config
             volumes:
             - name: config-volume
               configMap:
                 name: ratelimit-config
  2. ACK クラスター内で以下のコマンドを実行して、サービスをデプロイします:

    kubectl apply -f ratelimit-svc.yaml

シナリオ 1:サービスポート上のすべてのリクエストをレート制限する

このシナリオでは、HTTPBin サービスのポート 8000 へのすべてのリクエストを、1 分間に 1 回に制限します。

ワークフローは以下の 3 ステップで構成されます:ASM インスタンス上で ASMGlobalRateLimiter CR を作成し、生成された構成を ACK クラスター内のレート制限サービスに同期させ、検証を行います。

ステップ 1:ASMGlobalRateLimiter CR の作成

  1. global-ratelimit-svc.yaml というファイルを作成します:

    global-ratelimit-svc.yaml

    apiVersion: istio.alibabacloud.com/v1beta1
       kind: ASMGlobalRateLimiter
       metadata:
         name: global-svc-test
         namespace: default
       spec:
         workloadSelector:
           labels:
             app: httpbin
         rateLimitService:
           host: ratelimit.default.svc.cluster.local
           port: 8081
           timeout:
             seconds: 5
         isGateway: false
         configs:
         - name: httpbin
           limit:
             unit: MINUTE
             quota: 1
           match:
             vhost:
               name: '*'
               port: 8000

    以下の表では、主なフィールドについて説明します。全フィールドのリファレンスについては、「ASMGlobalRateLimiter フィールドの説明」をご参照ください。

    フィールド

    説明

    workloadSelector

    対象のワークロードを選択します。app: httpbin を設定することで、HTTPBin サービスにレート制限を適用します。

    isGateway

    このルールがイングレスゲートウェイではなくサイドカープロキシワークロードを対象とするため、false に設定します。

    rateLimitService

    レート制限サービスへの接続設定:ホスト名、gRPC ポート (8081)、タイムアウト (5 秒)。

    limit

    レート制限のしきい値。unit: MINUTE および quota: 1 は、一致したルートに対して 1 分間に 1 回のリクエストを許可することを意味します。

    vhost

    バーチャルホストとのマッチングを行います。name: '*'port: 8000 を組み合わせることで、HTTPBin サービスのポート 8000 へのすべてのリクエストにルールを適用します。

  2. ASM インスタンス内で以下のコマンドを実行して、CR を適用します:

    kubectl apply -f global-ratelimit-svc.yaml

ステップ 2:レート制限構成のデータプレーンへの同期

ASM が CR を処理すると、status.config.yaml フィールド内にレート制限サービスの構成が生成されます。この構成を ACK クラスター内のレート制限サービスの ConfigMap にコピーする必要があります。ASM コントロールプレーンと ACK データプレーンが別々のクラスターで実行されるため、この手動による同期が必要です。

  1. ASM インスタンスから生成された構成を取得します:

    kubectl get asmglobalratelimiter global-svc-test -o yaml

    出力内で status セクションを特定します:

    期待される出力

    status:
         config.yaml: |
           descriptors:
           - key: generic_key
             rate_limit:
               requests_per_unit: 1
               unit: MINUTE
             value: RateLimit[global-svc-test.default]-Id[3833670472]
           domain: ratelimit.default.svc.cluster.local
         message: ok
         status: successful
  2. ratelimit-config.yaml ファイルを作成します。config.yaml の内容を、status セクションから正確にコピーし、ConfigMap の data.config.yaml フィールドに貼り付けます:

    重要

    config.yaml の値を、status セクションから一切変更せずにコピーしてください。変更を行うと、レート制限サービスが構成を拒否します。

    ratelimit-config.yaml

    apiVersion: v1
       kind: ConfigMap
       metadata:
         name: ratelimit-config
       data:
         config.yaml: |
           descriptors:
           - key: header_match
             rate_limit:
               requests_per_unit: 1
               unit: MINUTE
             value: RateLimit[global-svc-test.default]-Id[1492204717]
           domain: ratelimit.default.svc.cluster.local
  3. 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 -v

2 回目のリクエストの期待される出力:

< 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 intact

2 回目のリクエストが 429 を返すことで、グローバルレート制限が有効になっていることが確認できます。1 分間に HTTPBin サービスへのアクセスは 1 回のみ許可されます。2 回目のリクエストを送信すると、速度制限がトリガーされ、これはサイドカープロキシが注入されたサービスのインバウンドトラフィックに対してグローバルレート制限が適用されていることを示します。

シナリオ 2:特定のパスへのリクエストをレート制限する

このシナリオでは、HTTPBin ポート 8000 の /headers パスへのリクエストを 1 分間に 1 回に制限しますが、/get などの他のパスには無制限のアクセスを許可します。

構成は ASM のバージョンによって異なります。

ステップ 1:ASMGlobalRateLimiter CR の作成

ご使用の ASM バージョンに合った YAML を選択してください:

ASM V1.19.0 より前のバージョン

apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMGlobalRateLimiter
metadata:
  name: global-svc-test
  namespace: default
spec:
  workloadSelector:
    labels:
      app: httpbin
  rateLimitService:
    host: ratelimit.default.svc.cluster.local
    port: 8081
    timeout:
      seconds: 5
  isGateway: false
  configs:
  - name: httpbin
    limit:
      unit: MINUTE
      quota: 1
    match:
      vhost:
        name: '*'
        port: 8000
        route:
          header_match:
          - name: ":path"
            prefix_match: "/headers"

V1.19.0 より前のバージョンでは、パスマッチングは match.vhost.route.header_match 内で構成されます。:path パセュドヘッダーは、リクエストパスをプレフィックスでマッチングします。

ASM V1.19.0 以降(推奨)

apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMGlobalRateLimiter
metadata:
  name: global-svc-test
  namespace: default
spec:
  workloadSelector:
    labels:
      app: httpbin
  rateLimitService:
    host: ratelimit.default.svc.cluster.local
    port: 8081
    timeout:
      seconds: 5
  isGateway: false
  configs:
  - name: httpbin
    limit:
      unit: SECOND
      quota: 100000
    match:
      vhost:
        name: '*'
        port: 8000
    limit_overrides:
    - request_match:
        header_match:
        - name: ":path"
          prefix_match: "/headers"
      limit:
        unit: MINUTE
        quota: 1

V1.19.0 以降では、パスベースのマッチングに limit_overrides フィールドを使用します。基本的な limit は高めの値(100,000 リクエスト/秒)に設定され、オーバーライドに一致するリクエストのみがレート制限の対象となります。

以下の表では、このシナリオで使用される追加フィールドについて説明します:

フィールド

説明

limit

適用される速度制限パラメーター。unit は速度制限検出の時間単位を示します。quota は、単位時間あたりに許可されるリクエスト総数を示します。ASM インスタンスが V1.19.0 以降の場合、unitSECOND に、quota100000 に設定されます。これは、一致したルートに対して 1 秒間に 100,000 リクエストを許可することを意味し、実質的に基本ルールでは速度制限が設定されないことを意味します。limit_overrides フィールドを使用して、特定の条件を満たすリクエストの速度制限を構成できます。

limit_overrides

(V1.19.0+) 特定の条件に一致するリクエストに対して、基本のレート制限しきい値を上書きします。各オーバーライドは、独自の request_match および limit を指定します。

vhost

速度制限が適用されるドメイン名およびルート。V1.19.0 より前のバージョンでは、route セクション内でリクエストのヘッダーマッチングルールを構成できます。V1.19.0 以降では、limit_overrides フィールド内でヘッダーマッチングルールを構成します。

route.header_match

(V1.19.0 より前) vhost ルート内で HTTP ヘッダー値に基づくリクエストのマッチングを行います。:path パセュドヘッダーを使用して、URL パスのマッチングを行います。

ステップ 2:レート制限構成のデータプレーンへの同期

シナリオ 1 と同じ手順に従います:

  1. ASM インスタンスから生成された構成を取得します:

    kubectl get asmglobalratelimiter global-svc-test -o yaml

    期待される status 出力 (V1.19.0+)

    status:
         config.yaml: |
           descriptors:
           - descriptors:
             - key: header_match
               rate_limit:
                 requests_per_unit: 1
                 unit: MINUTE
               value: RateLimit[global-svc-test.default]-Id[2613586978]
             key: generic_key
             rate_limit:
               requests_per_unit: 100000
               unit: SECOND
             value: RateLimit[global-svc-test.default]-Id[2613586978]
           domain: ratelimit.default.svc.cluster.local
         message: ok
         status: successful
  2. config.yamlstatus セクションからコピーし、ConfigMap に貼り付けて ACK クラスターに適用します:

    ratelimit-config.yaml

    apiVersion: v1
       kind: ConfigMap
       metadata:
         name: ratelimit-config
       data:
         config.yaml: |
           descriptors:
           - descriptors:
             - key: header_match
               rate_limit:
                 requests_per_unit: 1
                 unit: MINUTE
               value: RateLimit[global-svc-test.default]-Id[2613586978]
             key: generic_key
             rate_limit:
               requests_per_unit: 100000
               unit: SECOND
             value: RateLimit[global-svc-test.default]-Id[2613586978]
           domain: ratelimit.default.svc.cluster.local
    kubectl apply -f ratelimit-config.yaml

検証

  1. sleep Pod から /headers パスへ 2 回のリクエストを送信します:

    kubectl exec -it deploy/sleep -- sh

    その後、以下を実行します:

    curl httpbin:8000/headers -v
    curl httpbin:8000/headers -v

    2 回目のリクエストの期待される出力:

    < 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 回のみ許可されます。

  2. 他のパスが影響を受けないことを確認します:

    curl httpbin:8000/get -v

    期待される出力

    *   Trying 192.168.243.21:8000...
       * Connected to httpbin (192.168.243.21) port 8000 (#0)
       > GET /get HTTP/1.1
       > Host: httpbin:8000
       > User-Agent: curl/8.1.2
       > Accept: */*
       >
       < HTTP/1.1 200 OK
       < server: envoy
       < date: Thu, 11 Jan 2024 06:25:09 GMT
       < content-type: application/json
       < content-length: 431
       < access-control-allow-origin: *
       < access-control-allow-credentials: true
       < x-envoy-upstream-service-time: 7
       <
       {
         "args": {},
         "headers": {
           "Accept": "*/*",
           "Host": "httpbin:8000",
           "User-Agent": "curl/8.1.2",
           "X-Envoy-Attempt-Count": "1",
           "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=be10819991ba1a354a89e68b3bed1553c12a4fba8b65fbe0f16299d552680b29;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/sleep"
         },
         "origin": "127.0.0.6",
         "url": "http://httpbin:8000/get"
       }
       * Connection #0 to host httpbin left intact

    /get パスへのリクエストは成功します。これは、/headers パスのみがレート制限の対象であるためです。

グローバルレート制限メトリックの監視

Envoy サイドカープロキシは、グローバルレート制限に関する以下のメトリックを公開します:

メトリック

タイプ

説明

envoy_cluster_ratelimit_ok

カウンター

グローバル速度制限により許可されたリクエストの総数。

envoy_cluster_ratelimit_over_limit

カウンター

グローバル速度制限により、速度制限がトリガーされたと判定されたリクエストの総数。

envoy_cluster_ratelimit_error

カウンター

グローバル速度制限への呼び出しに失敗したリクエストの総数。

メトリック報告の有効化

  1. サイドカープロキシの proxyStatsMatcher を構成します。正規表現マッチ を選択し、値を .*ratelimit.* に設定します。詳細については、「サイドカープロキシの構成」の「proxyStatsMatcher」セクションをご参照ください。

  2. 新しいプロキシ構成を反映させるために、HTTPBin サービスを再デプロイします。詳細については、「サイドカープロキシの構成」の「(任意) ワークロードの再デプロイ」セクションをご参照ください。

  3. グローバル速度制限を構成し、リクエストテストを実行します。詳細については、シナリオ 1 または「トラフィック管理センターでのローカルレート制限の設定」をご参照ください。

  4. 以下のコマンドを実行して、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 を使用して、レート制限メトリックを収集し、レート制限が発生した際にアラートをトリガーします。

  1. ACK クラスターを Managed Service for Prometheus の Alibaba Cloud ASM コンポーネントに接続するか、コンポーネントを最新バージョンにアップグレードします。詳細については、「コンポーネントの管理」をご参照ください。

    説明

    すでに自己管理型の Prometheus インスタンスを使用して ASM メトリックを収集している場合は、この手順をスキップしてください。詳細については、「自己管理型 Prometheus インスタンスを使用した ASM インスタンスの監視」をご参照ください。

  2. 以下の 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 }}

次のステップ

参考文献