Configurar la limitación de frecuencia de Google Cloud Armor con Envoy
En esta página se explica cómo configurar la limitación de frecuencia global del lado del servidor para tu malla de servicios mediante Cloud Armor. Puedes usar esta función para aplicar límites de velocidad de uso compartido equitativo a todo el tráfico que llegue a tu servicio, lo que te ayudará a compartir de forma equitativa la capacidad disponible de tus servicios y a mitigar el riesgo de que los clientes maliciosos o con un comportamiento inadecuado sobrecarguen tus servicios. Para obtener más información sobre la limitación de la frecuencia, consulta la introducción a la limitación de la frecuencia.
Configurar Google Kubernetes Engine (GKE) para Envoy
Antes de empezar
Antes de empezar, debes habilitar las siguientes APIs:
container.googleapis.com
compute.googleapis.com
trafficdirector.googleapis.com
networkservices.googleapis.com
meshconfig.googleapis.com
monitoring.googleapis.com
Puedes habilitar todas las APIs con el siguiente comando de la CLI de Google Cloud:
gcloud services enable \ container.googleapis.com \ compute.googleapis.com \ trafficdirector.googleapis.com \ networkservices.googleapis.com \ meshconfig.googleapis.com \ monitoring.googleapis.com
A continuación, crea las variables de entorno que se usan en este documento:
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}
Sustituye las siguientes variables por la información de tu proyecto:
- Sustituye
PROJECT_ID
por el ID de tu proyecto. - Sustituye
ZONE
por la zona en la que quieras crear el clúster de GKE. - Sustituye
CLUSTER
por el nombre del clúster. - Sustituye
MESH_NAME
por el nombre de la malla.
Crear un clúster de GKE
Usa el siguiente comando para crear un clúster de GKE en la zona que has especificado en la sección anterior:
gcloud container clusters create "CLUSTER" \ --zone="ZONE" \ --scopes="cloud-platform" \ --tags="allow-envoy-health-checks" \ --enable-ip-alias
Obtén las credenciales de tu nuevo clúster:
gcloud container clusters get-credentials "CLUSTER" \ --zone="ZONE"
Habilitar la inyección automática
Usa el siguiente comando para aplicar el recurso
MutatingWebhookConfiguration
a tu clúster. Cuando se crea un pod, se invoca el controlador de admisión del clúster, que indica al inyector de sidecar gestionado que añada el contenedor Envoy al 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
Habilita la inyección de sidecar para el espacio de nombres predeterminado. El inyector de sidecar inserta contenedores sidecar en los pods creados en el espacio de nombres predeterminado.
kubectl label namespace default td-injection=enabled
Guarda la siguiente configuración de GKE para tu servicio como
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
Aplica el ejemplo de servicio que has creado en el paso anterior:
kubectl apply -f service_sample.yaml
Guarda la siguiente configuración de GKE para tu cliente como
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
Aplica la muestra de cliente que has creado en el paso anterior:
kubectl apply -f client_sample.yaml
Configurar Cloud Service Mesh para limitar la frecuencia
Sigue los pasos de esta sección para preparar Cloud Service Mesh para la limitación de velocidad.
Crea la especificación de recursos
Mesh
y guárdala en un archivo llamadomesh.yaml
:name: MESH_NAME interceptionPort: 15001
Crea el recurso
Mesh
con la especificación mesh.yaml.gcloud network-services meshes import "MESH_NAME" \ --source=mesh.yaml \ --location=global
Crea una comprobación del estado:
gcloud compute health-checks create http rate-limit-demo-hc \ --use-serving-port
Crea una regla de cortafuegos para permitir las conexiones de comprobación del estado entrantes a las instancias de tu red.
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
Crea un servicio de backend global con un esquema de balanceo de carga
INTERNAL_SELF_MANAGED
y añade la comprobación del estado.gcloud compute backend-services create rate-limit-demo-service \ --global \ --health-checks rate-limit-demo-hc \ --load-balancing-scheme INTERNAL_SELF_MANAGED
Añade el NEG
rate-limit-demo-neg
al servicio de backend.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
Crea la especificación
HTTPRoute
y guárdala en un archivo llamadohttp_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"
Crea el recurso
HTTPRoute
con la especificación del archivohttp_route.yaml
.gcloud network-services http-routes import rate-limit-demo-http-route \ --source=http_route.yaml \ --location=global
Configurar la limitación de frecuencia con Envoy
En las siguientes secciones se explica cómo configurar la limitación de frecuencia por parte del servidor para tu malla de servicios. En la primera sección se explica cómo configurar un límite de frecuencia global del lado del servidor para todos los clientes, y en la segunda, cómo aplicar límites de frecuencia diferentes a distintos grupos de clientes.
Configurar la limitación de frecuencia global del lado del servidor
En este ejemplo, se crea una regla de limitación de frecuencia del lado del servidor que aplica la limitación de frecuencia a todos los clientes.
En un archivo YAML llamado
rate-limit-policy.yaml
, crea una política de seguridad de Cloud Armor de tipoCLOUD_ARMOR_INTERNAL_SERVICE
.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"
Crea la política de seguridad llamada
rate-limit-policy
:gcloud beta compute security-policies create rate-limit-policy \ --global \ --file-name=rate-limit-policy.yaml
En un archivo YAML, cree una política de endpoint que haga referencia a la política de seguridad que ha creado en el paso anterior. En estos ejemplos, el archivo se llama
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
Crea una política de endpoint llamada
rate-limit-ep
:gcloud beta network-services endpoint-policies import rate-limit-ep \ --source=endpoints-policies.yaml \ --location=global
Configurar diferentes límites de frecuencia del lado del servidor para distintos grupos de clientes
En este ejemplo, se crean diferentes reglas de limitación de frecuencia del lado del servidor que aplican umbrales de limitación de frecuencia distintos a grupos de clientes.
Crea una política de seguridad de Cloud Armor con el tipo
CLOUD_ARMOR_INTERNAL_SERVICE
con varias reglas de limitación de frecuencia, como la que se define en el siguiente archivo. En estos ejemplos, este archivo se llamaper-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"
Esta política aplica la limitación de frecuencia a las solicitudes que contienen un encabezado HTTP con el nombre
user
y el valordemo
si Cloud Service Mesh recibe más de 1000 solicitudes de este tipo en un periodo de 60 segundos. Las solicitudes que no tienen este encabezado HTTP se limitan si Cloud Service Mesh recibe más de 10.000 solicitudes de este tipo en un periodo de 60 segundos.Usa el siguiente comando para crear la política, que se llama
per-client-security-policy
:gcloud beta compute security-policies create per-client-security-policy \ --global \ --file-name=per-client-security-policy.yaml
Crea una política de endpoint que haga referencia a la política de seguridad que has creado en el paso anterior, como la que se define en el siguiente archivo. En este ejemplo, el archivo se llama
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
Usa el siguiente comando para crear una política de endpoint llamada
rate-limit-ep
:gcloud beta network-services endpoint-policies import rate-limit-ep \ --source=per-client-endpoints-policies.yaml \ --location=global
Validar la configuración
Puedes usar la herramienta de prueba de carga Nighthawk para generar tráfico y comprobar si tus reglas de limitación de frecuencia funcionan como esperas. Usa el siguiente comando para generar tráfico con 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
A continuación, usa el siguiente comando para habilitar los registros de depuración de Envoy:
kubectl exec -it deploy/app1 -c app1 -- wget -q -O - \ --post-data="" 'http://localhost:15000/logging?level=debug'
Para ver los informes de uso que Envoy envía al servidor de gestión, consulta Acceder a los registros.
En los resultados de la prueba, verás lo siguiente:
- Se tarda unos cinco minutos en aplicar la limitación de frecuencia.
- Después del periodo de calentamiento inicial, verás entre 15 y 21 QPS en el contador
benchmark.http_2xx
de la salida del cliente de Nighthawk. Esto significa que Cloud Armor permite unas 1000 solicitudes por minuto.
Para ver la eficacia de las reglas de tu política de seguridad de Cloud Armor, consulta Ver el panel de monitorización.
Inhabilitar el límite de frecuencia
Puedes inhabilitar la limitación de la frecuencia mediante uno de los siguientes métodos:
- Puedes eliminar las políticas de endpoint y las políticas de seguridad que hayas configurado con tus reglas de limitación de frecuencia.
- Para desvincular la política de seguridad de tu política de endpoints, actualiza esta última para eliminar el campo
securityPolicies
.
En las siguientes secciones se explica cómo inhabilitar la limitación de la frecuencia con cada método.
Eliminar una política de endpoint y una política de seguridad
Primero, usa el siguiente comando gcloud
para eliminar la política de endpoint llamada rate-limit-ep
.
Si has usado el nombre proporcionado en el primer o segundo ejemplo de esta página, la política de endpoint se llamará endpoints-policies
o per-client-endpoints-policies
, respectivamente.
gcloud beta network-services endpoint-policies delete --location=global rate-limit-ep
A continuación, usa el siguiente comando gcloud
para eliminar una política de seguridad. Sustituye per-client-security-policy
por el nombre de tu política de seguridad. Si has usado el nombre proporcionado en el primer o segundo ejemplo de esta página, tu política de seguridad tendrá el mismo nombre que tu política de endpoint.
gcloud beta compute security-policies delete --global per-client-security-policy
Desvincular una política de seguridad de tu política de endpoint
Primero, actualiza el archivo endpoint-policy.yaml
para quitar el campo securityPolcies
:
name: "rate-limit-ep" endpointMatcher: metadataLabelMatcher: metadataLabelMatchCriteria: MATCH_ALL metadataLabels: - labelName: app labelValue: rate-limit-demo type: SIDECAR_PROXY
A continuación, usa el siguiente comando para actualizar la política de endpoint llamada rate-limit-ep
con los cambios del archivo endpoint-policy.yaml
:
gcloud beta network-services endpoint-policies import rate-limit-ep \ --source=endpoints-policies.yaml \ --location=global