使用 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 时,系统会调用集群内准入控制器,并指示托管式边车注入器将 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
为默认命名空间启用边车注入。Sidecar 注入器会将 Sidecar 容器注入到在默认命名空间下创建的 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_INTERNAL_SERVICE
的 Cloud Armor 安全政策,其中包含多条速率限制规则,如以下文件中定义的那样。在这些示例中,此文件称为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 个包含名称为
user
且值为demo
的 HTTP 标头的请求,则此政策会对这些请求应用速率限制。如果 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 发送到管理服务器的使用情况报告,请参阅访问日志。
您可以通过测试结果了解以下信息:
- 速率限制大约需要 5 分钟才会生效。
- 在初始预热期过后,您会看到 Nighthawk 客户端输出
benchmark.http_2xx
计数器显示大约 15-21 QPS。这意味着 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