レート制限は、クライアントがサーバーに送信できるリクエストの数を、毎分 300 件や毎秒 10 件のように、特定の期間内に制限します。Alibaba Cloud Service Mesh (ASM) で ASMGlobalRateLimiter を使用して、サイドカーがインジェクションされたアプリケーションサービスのインバウンドトラフィックにグローバルレート制限を適用します。
Envoy プロキシは、グローバルレート制限とローカルレート制限の 2 つの方法でレート制限を実装します。このトピックでは、グローバルレート制限のみを扱います。レート制限の概念とローカルレート制限の手順については、「トラフィック管理センターでローカルレート制限を設定」をご参照ください。
このトピックでは、2 つのシナリオを通して、グローバルレート制限をアプリケーションサービスに適用できる粒度を説明します。シナリオ 1 はサービスポート上のすべてのリクエストに適用する場合、シナリオ 2 はそのポート上の特定のパスにアクセスするリクエストのみに適用する場合です。どちらのシナリオでも、同じ ASMGlobalRateLimiter リソース名 (global-svc-test) と同じ ConfigMap (ratelimit-config) を使用します。
前提条件
-
Container Service for Kubernetes (ACK) マネージドクラスターが、バージョン 1.18.0.131 以降の ASM インスタンスに追加されています。手順については、「ASM インスタンスにクラスターを追加する」をご参照ください。
-
Kubernetes クラスターの
default名前空間では、自動サイドカープロキシインジェクションが有効になっています。 詳細については、「自動サイドカープロキシインジェクションを有効にする」をご参照ください。 -
ingressgateway という名前のイングレスゲートウェイが作成され、ポート 80 が有効になります。手順については、「イングレスゲートウェイを作成する」をご参照ください。
-
httpbin および sleep サンプルアプリケーションがデプロイされていること。手順については、「データプレーン上のクラスターへの httpbin アプリケーションのデプロイ」および「データプレーン上のクラスターへの sleep サービスのデプロイ」をご参照ください。
ASM は、バージョン 1.18.0.131 以降で、イングレスゲートウェイおよびサイドカーがインジェクトされたアプリケーションサービスへの受信トラフィックに対するグローバルレート制限の設定をサポートします。 シナリオ 2 が特定のパスをレート制限するために使用する limit_overrides フィールドは、バージョン 1.19.0 以降の ASM インスタンスでのみサポートされます。
レート制限サービスのデプロイ
グローバルレート制限は、データプレーン上のクラスターでレート制限サービスが実行された後にのみ有効になります。レート制限ルールを設定する前に、レート制限サービス、およびその依存先である Redis サービスをデプロイします。
-
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 -
ACK クラスターの kubeconfig コンテキストで、次のコマンドを実行して、レート制限サービス、およびその依存先である Redis サービスをクラスターに作成します。
kubectl apply -f ratelimit-svc.yaml
ASM マネージドのレート制限サービスの使用 (オプション)
この機能は、バージョン 1.25 以降の ASM インスタンスでのみサポートされます。お使いの ASM インスタンスのバージョンが 1.25 より前の場合は、前述の手順に従ってレート制限サービスをデプロイし、レート制限サービスが使用する ConfigMap を手動で更新してください。
ASM 1.25 以降では、ASMMeshConfig を使用して ASM マネージドのレート制限サービスを有効にできます。この方法を使用する場合、ASMGlobalRateLimiter を作成するときに rateLimitService を設定する必要はありません。ASM は、データプレーン上のクラスターに配信されるレート制限サービスを自動的に使用し、グローバルレート制限ルールに基づいてレート制限サービスで使用される ConfigMap を自動的に更新します。
-
レート制限サービスが依存する Redis を準備します。ASM はレート制限サービスをデプロイしますが、Redis はデプロイしません。以前にデプロイした Redis を引き続き使用するか、既存の Redis インスタンスを使用できます。前の手順の
ratelimit-svc.yamlを引き続き使用する場合は、その中の Redis の ServiceAccount、Service、および Deployment のみをデプロイします。ratelimit-configConfigMap、ratelimitService、またはratelimitDeployment はデプロイしないでください。 -
ASM インスタンスの kubeconfig コンテキストで、次のコマンドを実行して ASMMeshConfig/default が存在することを確認します。
kubectl get asmmeshconfig defaultratelimit-service-patch.yamlという名前のファイルを作成します。次の例では、前の手順でdefault名前空間にデプロイされた Redis を使用します。spec: rateLimitService: enabled: true replicas: 1 redis: type: single url: redis.default.svc.cluster.local:6379次のコマンドを実行して、ASMMeshConfig/default の他の設定が上書きされないように、マージパッチを使用してレート制限サービスを有効にします。
kubectl patch asmmeshconfig default \ --type=merge \ --patch-file ratelimit-service-patch.yamlこの設定では、
enabledをtrueに設定する必要があります。replicasは、レート制限サービスのレプリカ数を指定します。redis.typeはsingle、cluster、およびsentinelをサポートします。redis.urlは、データプレーン上のクラスター内のレート制限サービスからアクセス可能な Redis アドレスである必要があります。 -
以降のシナリオで ASMGlobalRateLimiter を作成する場合、
spec.rateLimitServiceフィールドを完全に削除してください。rateLimitService: {}のような空のオブジェクトを設定しないでください。その他のレート制限ルールの設定は変更せずにそのままにしてください。spec.rateLimitServiceを省略した場合、ASM はデフォルトでratelimit.istio-system.svc.cluster.local:8081を使用し、ACK クラスター内のistio-system/ratelimit-service-configConfigMap を自動的に作成または更新します。 この ConfigMap は ASM によって管理されます。 手動で変更しないでください。ACK クラスターの kubeconfig コンテキストで、次のコマンドを実行して、自動生成されたレート制限設定を表示します。
kubectl -n istio-system get configmap ratelimit-service-config -o yaml
以降のシナリオでは、すべての ASM バージョンに対応した手動デプロイ方法を説明します。 ASM マネージドのレート制限サービスを使用する場合は、このセクションで説明するように rateLimitService を省略し、ステータスフィールドから設定をコピーして ConfigMap を手動で更新する手順はスキップしてください。 その他のレート制限ルールの設定および検証方法は同じです。
シナリオ 1:サービスポートのグローバルレート制限の設定
httpbin サービスのポート 8000 にレート制限を適用します。レート制限ルールを作成すると、レート制限は httpbin サービスのポート 8000 に送信されるすべてのリクエストに適用されます。
-
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レート制限の対象となるワークロードに一致します。このシナリオでは、グローバルレート制限は httpbin サービスのワークロードで有効になるため、値は
app: httpbinに設定されます。isGateway設定がゲートウェイに適用されるかどうかを指定します。この例では、値は
falseに設定されています。rateLimitServiceレート制限サービスのドメイン名、ポート、および接続タイムアウト設定。「レート制限サービスのデプロイ」でデプロイされたレート制限サービスについては、この表の後の設定を使用します。
limit有効になるレート制限パラメーターです。
unitはレート制限検出の時間単位を指定し、quotaは 1 単位時間あたりに許可されるリクエストの総数を指定します。この例でunitをMINUTEに、quotaを1に設定すると、一致したルートでは 1 分あたり 1 つのリクエストしか送信できなくなります。超過したリクエストはレート制限されます。vhostレート制限が一致するドメイン名とルート設定。設定をアプリケーションサービスに適用する場合、
nameを'*'に設定し、portをサービスポートに設定します。次の
rateLimitService設定を使用します:host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5 -
ASM インスタンスの kubeconfig コンテキストで、次のコマンドを実行して、httpbin アプリケーションサービスへのインバウンドトラフィックに適用されるグローバルレート制限ルールを作成します。
kubectl apply -f global-ratelimit-svc.yaml -
次のコマンドを実行して、グローバルレート制限ルールの調整済みの設定を取得します。
kubectl get asmglobalratelimiter global-svc-test -o yamlapiVersion: istio.alibabacloud.com/v1 kind: ASMGlobalRateLimiter metadata: name: global-svc-test namespace: default spec: configs: - limit: quota: 1 unit: MINUTE match: vhost: name: '*' port: 8000 name: httpbin isGateway: false rateLimitService: host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5 workloadSelector: labels: app: httpbin 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 -
グローバルレート制限サービスの設定を保持する、
ratelimit-config.yamlという名前のファイルを作成します。 ASMGlobalRateLimiter リソースのstatusフィールド配下にあるconfig.yamlフィールド内の文字列を、ConfigMap のdata配下にある同名のconfig.yamlフィールドにそのまま貼り付けます。 この ConfigMap は、ratelimit-svc.yaml内のratelimit-configConfigMap と同じ名前であるため、貼り付けられた文字列は初期の空の設定 ({}) を置き換えます。apiVersion: v1 kind: ConfigMap metadata: name: ratelimit-config data: 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このサンプルでは前の手順で想定される出力の値を使用していますが、実際には
value内のId値を含め、ご自身の ASMGlobalRateLimiter リソースから返された値を使用してください。 -
ACK クラスターの kubeconfig コンテキストで、次のコマンドを実行して、クラスター内のグローバルレート制限サービスの設定を更新します。
kubectl apply -f ratelimit-config.yaml -
次のコマンドを実行して、sleep アプリケーションで bash セッションを開始します。
kubectl exec -it deploy/sleep -- sh -
次のコマンドを実行して、httpbin サービスに連続して 2 回アクセスします。
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グローバルレート制限の設定では、1 分以内に httpbin サービスへのリクエストが 1 つだけ許可されるため、2 番目のリクエストにはレート制限が適用されます。これで、グローバルレート制限が httpbin サービスのサービスポートへのインバウンドトラフィックで有効になりました。
シナリオ 2:サービスポート上の特定パスのグローバルレート制限の設定
httpbin サービスのポート 8000 にレート制限を適用し、そのレート制限が /headers パスにアクセスするリクエストにのみ有効になるようにします。レート制限ルールを作成すると、httpbin サービスのポート 8000 に送信され、/headers パスにアクセスするすべてのリクエストにレート制限が適用されます。
-
ご使用の ASM バージョンに対応する内容で、
global-ratelimit-svc.yamlという名前のファイルを作成します。1.19.0 より前の ASM バージョン用の 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 route: header_match: - name: ":path" prefix_match: "/headers"ASM バージョン 1.19.0 以降用の 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: SECOND quota: 100000 match: vhost: name: '*' port: 8000 limit_overrides: - request_match: header_match: - name: ":path" prefix_match: "/headers" limit: unit: MINUTE quota: 1次の表では、一部のフィールドについて説明します。すべてのフィールドの説明については、「ASMGlobalRateLimiter のフィールド」をご参照ください。
パラメーター
説明
workloadSelectorレート制限が適用されるワークロードと一致します。このシナリオでは、グローバルレート制限は httpbin サービスのワークロードに適用されるため、値は
app: httpbinに設定されます。isGateway設定がゲートウェイに適用されるかどうかを指定します。この例では、値は
falseに設定されています。rateLimitServiceレート制限サービスのドメイン名、ポート、および接続タイムアウト設定。「レート制限サービスのデプロイ」でデプロイされたレート制限サービスについては、この表の後の設定を使用します。
limit有効にするレート制限パラメーター。
unitはレート制限検出の時間単位を指定し、quotaは 1 単位時間あたりに許可されるリクエストの総数を指定します。 1.19.0 より前のバージョンの ASM インスタンスの場合、この例ではunitをMINUTEに、quotaを1に設定します。これにより、一致したルートでは 1 分あたり 1 つのリクエストしか送信できなくなり、超過したリクエストはレート制限されます。 バージョン 1.19.0 以降の ASM インスタンスの場合、レート制限パラメーターは 1 秒あたり 100,000 リクエストに設定されます。これは、特定の条件を満たすリクエストのレート制限がlimit_overridesフィールドで有効になるため、レート制限がないこととほぼ同等です。vhostレート制限が一致するドメイン名とルート設定です。設定がアプリケーションサービスで有効になる場合、
nameを'*'に設定し、portをサービスのサービスポートに設定します。 1.19.0 より前のバージョンの ASM インスタンスの場合、routeでリクエストのヘッダー一致ルールを設定することもできます。この例では、リクエストのパスに一致する:pathという名前の特別なヘッダーに一致します。つまり、このルールはパスが/headersで始まるすべてのリクエストに一致します。バージョン 1.19.0 以降の ASM インスタンスの場合、リクエストのヘッダー一致ルールはrouteからlimit_overridesフィールドに移動しました。limit_overridesレート制限の上書き設定は、バージョン 1.19.0 以降の ASM インスタンスでのみサポートされています。この設定では、リクエストのさまざまな属性をマッチングさせ、マッチングした特定のリクエストに個別のレート制限設定を適用できます。この例では、
limit_overridesフィールドで、リクエストのパスと一致する特別なヘッダー:pathとのマッチングを指定しています。言い換えると、この上書きは、パスが/headersで始まるすべてのリクエストに一致します。以下の
rateLimitService設定を使用します:host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5 -
ASM インスタンスの kubeconfig コンテキストで、次のコマンドを実行して、httpbin アプリケーションサービスへのインバウンドトラフィックに適用されるグローバルレート制限ルールを作成します。
kubectl apply -f global-ratelimit-svc.yaml -
次のコマンドを実行して、グローバルレート制限ルールの調整済みの設定を取得します。
kubectl get asmglobalratelimiter global-svc-test -o yamlapiVersion: istio.alibabacloud.com/v1 kind: ASMGlobalRateLimiter metadata: name: global-svc-test namespace: default spec: configs: - limit: quota: 100000 unit: SECOND limit_overrides: - limit: quota: 1 unit: MINUTE request_match: header_match: - name: :path prefix_match: /headers match: vhost: name: '*' port: 8000 name: httpbin isGateway: false rateLimitService: host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5 workloadSelector: labels: app: httpbin 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 -
グローバルレート制限サービスの設定を格納する、
ratelimit-config.yamlという名前のファイルを作成します。ASMGlobalRateLimiterリソースのstatusフィールド配下にあるconfig.yamlフィールドの文字列を、ConfigMap のdata配下にある同名のconfig.yamlフィールドにそのまま貼り付けます。この ConfigMap はratelimit-svc.yaml内のratelimit-configConfigMap と同名であるため、貼り付けた文字列によって初期の空の設定 ({}) が置き換えられます。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このサンプルの値は、前のステップで期待される出力のものです。
value内のId値を含め、ご自身の ASMGlobalRateLimiter リソースで返された値を使用してください。 -
ACK クラスターの kubeconfig コンテキストで、次のコマンドを実行して、クラスター内のグローバルレート制限サービスの設定を更新します。
kubectl apply -f ratelimit-config.yaml -
次のコマンドを実行して、sleep アプリケーションで bash セッションを開始します。
kubectl exec -it deploy/sleep -- sh -
以下のコマンドを実行して、httpbin サービスの
/headersパスに連続で 2 回アクセスします。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グローバルレート制限設定では、httpbin サービスの
/headersパスへのリクエストが 1 分間に 1 つしか許可されないため、2 回目のリクエストはレート制限されます。これで、グローバルレート制限が httpbin サービスの/headersパスへのインバウンドトラフィックに適用されるようになりました。 -
次のコマンドを実行して、httpbin サービスの
/getパスにアクセスします。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 intacthttpbin サービスの他のパスに送信されたリクエストは、グローバルレート制限設定の影響を受けず、引き続き正常にアクセスできます。
関連ドキュメント
-
ASMGlobalRateLimiter フィールドの説明については、「ASMGlobalRateLimiter のフィールド」をご参照ください。
-
トラフィック管理センターでローカルレート制限を設定する方法の詳細については、「トラフィック管理センターでローカルレート制限を設定」をご参照ください。
-
イングレスゲートウェイのグローバルレート制限を設定する方法の詳細については、「イングレスゲートウェイのグローバルレート制限を設定」をご参照ください。