使用 Envoy 設定 Google Cloud Armor 頻率限制
本頁說明如何使用 Cloud Armor,為服務網格設定全域伺服器端速率限制。您可以使用這項功能,對服務的所有傳入流量套用公平分享速率限制,有助於公平分享服務的可用容量,並降低惡意或行為異常的用戶端造成服務過載的風險。如要進一步瞭解頻率限制,請參閱頻率限制總覽。
為 Envoy 設定 Google Kubernetes Engine (GKE)
事前準備
開始前,請務必啟用下列 API:
container.googleapis.com
compute.googleapis.com
trafficdirector.googleapis.com
networkservices.googleapis.com
meshconfig.googleapis.com
monitoring.googleapis.com
您可以使用下列 Google Cloud CLI 指令啟用所有 API:
gcloud services enable \ container.googleapis.com \ compute.googleapis.com \ trafficdirector.googleapis.com \ networkservices.googleapis.com \ meshconfig.googleapis.com \ monitoring.googleapis.com
接著,建立本文中使用的環境變數:
export PROJECT_ID=PROJECT_ID export PROJECT_NUMBER="$(gcloud projects describe "${PROJECT_ID}" --format="value(projectNumber)")" export CLUSTER=CLUSTER export ZONE=ZONE export MESH_NAME=MESH_NAME export MESH_URI=projects/${PROJECT_NUMBER}/locations/global/meshes/${MESH_NAME}
將下列變數換成專案中的資訊:
- 將
PROJECT_ID
替換為您的專案 ID - 將
ZONE
替換為您打算建立 GKE 叢集的區域 - 將
CLUSTER
替換為叢集名稱 - 將
MESH_NAME
替換為網格名稱
建立 GKE 叢集
使用下列指令,在上一節指定的可用區中建立 GKE 叢集:
gcloud container clusters create "CLUSTER" \ --zone="ZONE" \ --scopes="cloud-platform" \ --tags="allow-envoy-health-checks" \ --enable-ip-alias
取得新叢集的憑證:
gcloud container clusters get-credentials "CLUSTER" \ --zone="ZONE"
啟用自動插入功能
使用下列指令,將
MutatingWebhookConfiguration
資源套用至叢集。建立 Pod 時,系統會叫用叢集內許可控制器,並指示受管理 Sidecar 注入器將 Envoy 容器新增至 Pod。cat <<EOF | kubectl apply -f - apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: labels: app: sidecar-injector name: td-mutating-webhook webhooks: - admissionReviewVersions: - v1beta1 - v1 clientConfig: url: https://meshconfig.googleapis.com/v1internal/projects/PROJECT_ID/locations/ZONE/clusters/CLUSTER/channels/rapid/targets/${MESH_URI}:tdInject failurePolicy: Fail matchPolicy: Exact name: namespace.sidecar-injector.csm.io namespaceSelector: matchExpressions: - key: td-injection operator: Exists reinvocationPolicy: Never rules: - apiGroups: - "" apiVersions: - v1 operations: - CREATE resources: - pods scope: '*' sideEffects: None timeoutSeconds: 30 EOF
為預設命名空間啟用補充資訊植入功能。補充資訊注入器會為在預設命名空間下建立的 Pod 注入補充資訊容器。
kubectl label namespace default td-injection=enabled
將下列服務的 GKE 設定儲存為
service_sample.yaml
。apiVersion: v1 kind: Service metadata: name: service-test annotations: cloud.google.com/neg: '{"exposed_ports":{"80":{"name": "rate-limit-demo-neg"}}}' spec: ports: - port: 80 name: service-test targetPort: 8000 selector: run: app1 type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: app1 labels: run: app1 spec: replicas: 1 selector: matchLabels: run: app1 template: metadata: labels: run: app1 annotations: cloud.google.com/proxyMetadata: '{"app": "rate-limit-demo"}' cloud.google.com/includeInboundPorts: "8000" cloud.google.com/sidecarProxyVersion: "1.34.1-gke.1" spec: containers: - image: mendhak/http-https-echo:37 name: app1 ports: - containerPort: 8000 env: - name: VALIDATION_NONCE value: "http" - name: HTTP_PORT value: "8000" securityContext: fsGroup: 1337
套用您在上一個步驟中建立的服務範例:
kubectl apply -f service_sample.yaml
將下列用戶端 GKE 設定儲存為
client_sample.yaml
:apiVersion: apps/v1 kind: Deployment metadata: labels: run: client name: load-generator spec: replicas: 1 selector: matchLabels: run: client template: metadata: labels: run: client spec: containers: - name: load-generator image: envoyproxy/nighthawk-dev command: ["/bin/sh", "-c"] args: ["echo 'Nighthawk client pod is running' && sleep infinity"] resources: requests: cpu: 200m memory: 256Mi limits: cpu: 1 memory: 512Mi securityContext: fsGroup: 1337
套用您在上一步驟中建立的用戶端範例:
kubectl apply -f client_sample.yaml
設定 Cloud Service Mesh 的速率限制
請按照本節的步驟,為 Cloud Service Mesh 準備速率限制。
建立
Mesh
資源規格,並儲存至名為mesh.yaml
的檔案:name: MESH_NAME interceptionPort: 15001
使用 mesh.yaml 規格建立
Mesh
資源。gcloud network-services meshes import "MESH_NAME" \ --source=mesh.yaml \ --location=global
建立健康狀態檢查:
gcloud compute health-checks create http rate-limit-demo-hc \ --use-serving-port
建立防火牆規則,允許傳入的健康狀態檢查連線抵達您網路中的執行個體。
gcloud compute firewall-rules create rate-limit-demo-fw-allow-hc \ --action ALLOW \ --direction INGRESS \ --source-ranges 35.191.0.0/16,130.211.0.0/22 \ --target-tags allow-envoy-health-checks \ --rules tcp
使用
INTERNAL_SELF_MANAGED
負載平衡機制建立全域後端服務,並新增健康狀態檢查。gcloud compute backend-services create rate-limit-demo-service \ --global \ --health-checks rate-limit-demo-hc \ --load-balancing-scheme INTERNAL_SELF_MANAGED
將 NEG
rate-limit-demo-neg
新增至後端服務。gcloud compute backend-services add-backend rate-limit-demo-service \ --global \ --network-endpoint-group rate-limit-demo-neg \ --network-endpoint-group-zone "ZONE" \ --balancing-mode RATE \ --max-rate-per-endpoint 5
建立
HTTPRoute
規格,並儲存至名為http_route.yaml
的檔案:name: rate-limit-demo-http-route hostnames: - service-test - service-test:80 meshes: - projects/PROJECT_ID/locations/global/meshes/MESH_NAME rules: - action: destinations: - serviceName: "projects/PROJECT_ID/locations/global/backendServices/rate-limit-demo-service"
使用
http_route.yaml
檔案中的規格建立HTTPRoute
資源。gcloud network-services http-routes import rate-limit-demo-http-route \ --source=http_route.yaml \ --location=global
使用 Envoy 設定頻率限制
下列各節說明如何為服務網格設定伺服器端速率限制。第一個部分說明如何為所有用戶端設定一個伺服器端全域速率限制,第二個部分則說明如何為不同用戶端群組強制執行不同的速率限制。
設定伺服器端全域速率限制
在本例中,您將建立一項伺服器端速率限制規則,對所有用戶端強制執行速率限制。
在名為
rate-limit-policy.yaml
的 YAML 檔案中,建立類型為CLOUD_ARMOR_INTERNAL_SERVICE
的 Cloud Armor 安全性政策。name: "rate-limit-policy" type: CLOUD_ARMOR_INTERNAL_SERVICE rules: - priority: 2147483647 match: config: srcIpRanges: ["*"] versionedExpr: SRC_IPS_V1 action: "fairshare" rateLimitOptions: rateLimitThreshold: count: 10000 intervalSec: 60 exceedAction: "deny(429)" conformAction: "allow" enforceOnKey: "ALL"
建立名為「
rate-limit-policy
」的安全性政策:gcloud beta compute security-policies create rate-limit-policy \ --global \ --file-name=rate-limit-policy.yaml
在 YAML 檔案中,建立參照您在上個步驟建立的安全性政策的端點政策。在這些範例中,這個檔案稱為
endpoints-policies.yaml
。name: "rate-limit-ep" endpointMatcher: metadataLabelMatcher: metadataLabelMatchCriteria: MATCH_ALL metadataLabels: - labelName: app labelValue: rate-limit-demo type: SIDECAR_PROXY securityPolicy: projects/PROJECT_ID/locations/global/securityPolicies/rate-limit-policy
建立名為
rate-limit-ep
的端點政策:gcloud beta network-services endpoint-policies import rate-limit-ep \ --source=endpoints-policies.yaml \ --location=global
為不同用戶端群組設定不同的伺服器端速率限制
在這個範例中,您會建立不同的伺服器端速率限制規則,為用戶端群組強制執行不同的速率限制門檻。
建立 Cloud Armor 安全性政策,類型為
CLOUD_ARMOR_INTERNAL_SERVICE
,並包含多項速率限制規則,如下列檔案中定義的規則。在這些範例中,這個檔案稱為per-client-security-policy.yaml
。name: "per-client-security-policy" type: CLOUD_ARMOR_INTERNAL_SERVICE rules: - priority: 0 match: expr: expression: "request.headers['user'] == 'demo'" action: "fairshare" rateLimitOptions: rateLimitThreshold: count: 1000 intervalSec: 60 exceedAction: "deny(429)" conformAction: "allow" enforceOnKey: "ALL" - priority: 2147483647 match: config: srcIpRanges: ["*"] versionedExpr: SRC_IPS_V1 action: "fairshare" rateLimitOptions: rateLimitThreshold: count: 10000 intervalSec: 60 exceedAction: "deny(429)" conformAction: "allow" enforceOnKey: "ALL"
如果 Cloud Service Mesh 在 60 秒內收到超過 1,000 項這類要求,這項政策就會對含有 HTTP 標頭 (名稱為
user
,值為demo
) 的要求套用速率限制。如果 Cloud Service Mesh 在 60 秒內收到超過 10,000 個沒有這個 HTTP 標頭的要求,就會對這些要求進行速率限制。使用下列指令建立名為
per-client-security-policy
的政策:gcloud beta compute security-policies create per-client-security-policy \ --global \ --file-name=per-client-security-policy.yaml
建立端點政策,參照您在上一個步驟中建立的安全性政策,例如下列檔案中定義的政策。在本例中,這個檔案稱為
per-client-endpoints-policies.yaml
。name: "rate-limit-ep" endpointMatcher: metadataLabelMatcher: metadataLabelMatchCriteria: MATCH_ALL metadataLabels: - labelName: app labelValue: rate-limit-demo type: SIDECAR_PROXY securityPolicy: projects/PROJECT_ID/locations/global/securityPolicies/per-client-security-policy
使用下列指令建立名為
rate-limit-ep
的端點政策:gcloud beta network-services endpoint-policies import rate-limit-ep \ --source=per-client-endpoints-policies.yaml \ --location=global
驗證設定
您可以使用 Nighthawk 負載測試工具產生流量,測試速率限制規則是否正常運作。使用下列指令,透過 Nighthawk 產生流量:
kubectl exec -it deploy/load-generator -c load-generator -- \ nighthawk_client http://service-test \ --open-loop --no-default-failure-predicates \ --rps 60 \ --duration 360 \ --connections 10 \ --protocol http1 \ --request-header user:demo
接著,使用下列指令啟用 Envoy 偵錯記錄:
kubectl exec -it deploy/app1 -c app1 -- wget -q -O - \ --post-data="" 'http://localhost:15000/logging?level=debug'
如要查看 Envoy 傳送至管理伺服器的用量報告,請參閱存取記錄。
測試結果會顯示下列資訊:
- 速率限制大約五分鐘後就會生效。
- 經過初始暖機期後,您會看到 Nighthawk 用戶端輸出
benchmark.http_2xx
計數器顯示約 15 到 21 次的每秒查詢次數。也就是說,Cloud Armor 每分鐘允許約 1,000 個要求。
如要查看 Cloud Armor 安全性政策規則的效力,請參閱查看監控資訊主頁。
停用頻率限制
您可以透過下列任一方法停用速率限制:
- 您可以刪除使用速率限制規則設定的端點政策和安全性政策。
- 更新端點政策,移除
securityPolicies
欄位,即可從端點政策卸離安全性政策。
以下各節說明如何使用各種方法停用速率限制。
刪除端點政策和安全性政策
首先,請使用下列 gcloud
指令刪除名為 rate-limit-ep
的端點政策。如果您使用本頁第一個或第二個範例中提供的名稱,端點政策會分別命名為 endpoints-policies
或 per-client-endpoints-policies
。
gcloud beta network-services endpoint-policies delete --location=global rate-limit-ep
然後使用下列 gcloud
指令刪除安全性政策,並將 per-client-security-policy
替換為安全性政策的名稱。如果您使用本頁面第一個或第二個範例中提供的名稱,則安全性政策的名稱會與端點政策的名稱相同。
gcloud beta compute security-policies delete --global per-client-security-policy
從端點政策卸離安全性政策
首先,請更新 endpoint-policy.yaml
檔案,移除 securityPolcies
欄位:
name: "rate-limit-ep" endpointMatcher: metadataLabelMatcher: metadataLabelMatchCriteria: MATCH_ALL metadataLabels: - labelName: app labelValue: rate-limit-demo type: SIDECAR_PROXY
接著,使用下列指令,以 endpoint-policy.yaml
檔案的變更內容,更新名為 rate-limit-ep
的端點政策:
gcloud beta network-services endpoint-policies import rate-limit-ep \ --source=endpoints-policies.yaml \ --location=global