Configure a limitação de taxa do Google Cloud Armor com o Envoy

Esta página mostra como configurar a limitação de taxa global do lado do servidor para a sua malha de serviços através do Cloud Armor. Pode usar esta funcionalidade para aplicar a limitação de taxa de partilha equitativa a todo o tráfego que chega ao seu serviço, o que ajuda a partilhar equitativamente a capacidade disponível dos seus serviços e a mitigar o risco de clientes maliciosos ou com comportamento inadequado sobrecarregarem os seus serviços. Para mais informações sobre a limitação de taxa, leia a vista geral da limitação de taxa.

Configure o Google Kubernetes Engine (GKE) para o Envoy

Antes de começar

Antes de começar, tem de ativar as seguintes APIs:

  • container.googleapis.com
  • compute.googleapis.com
  • trafficdirector.googleapis.com
  • networkservices.googleapis.com
  • meshconfig.googleapis.com
  • monitoring.googleapis.com

Pode ativar todas as APIs através do seguinte comando da CLI gcloud do Google Cloud:

gcloud services enable \
    container.googleapis.com \
    compute.googleapis.com \
    trafficdirector.googleapis.com \
    networkservices.googleapis.com \
    meshconfig.googleapis.com \
    monitoring.googleapis.com

Em seguida, crie as variáveis de ambiente usadas neste 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}

Substitua as seguintes variáveis por informações do seu projeto:

  • Substitua PROJECT_ID pelo ID do seu projeto
  • Substitua ZONE pela zona na qual quer criar o cluster do GKE
  • Substitua CLUSTER pelo nome do cluster
  • Substitua MESH_NAME pelo nome da malha

Crie um cluster do GKE

  1. Use o comando seguinte para criar um cluster do GKE na zona que especificou na secção anterior:

     gcloud container clusters create "CLUSTER" \
         --zone="ZONE" \
         --scopes="cloud-platform" \
         --tags="allow-envoy-health-checks" \
         --enable-ip-alias
    
  2. Obtenha as credenciais do novo cluster:

     gcloud container clusters get-credentials "CLUSTER" \
         --zone="ZONE"
    

Ative a injeção automática

  1. Use o seguinte comando para aplicar o recurso MutatingWebhookConfiguration ao seu cluster. Quando um Pod é criado, o controlador de admissão no cluster é invocado e indica ao injetor de sidecar gerido que adicione o contentor Envoy ao 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
    
  2. Ative a injeção de sidecar para o espaço de nomes predefinido. O injetor de sidecar injeta contentores sidecar para pods criados no espaço de nomes predefinido.

    kubectl label namespace default td-injection=enabled
    
  3. Guarde a seguinte configuração do GKE para o seu serviço 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
    
  4. Aplique o exemplo de serviço que criou no passo anterior:

    kubectl apply -f service_sample.yaml
    
  5. Guarde a seguinte configuração do GKE para o seu 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
    
  6. Aplique o exemplo de cliente que criou no passo anterior:

    kubectl apply -f client_sample.yaml
    

Configure o Cloud Service Mesh para a limitação de taxa

Use os passos nesta secção para preparar a Cloud Service Mesh para a limitação de taxas.

  1. Crie a especificação do recurso Mesh e guarde-a num ficheiro denominado mesh.yaml:

    name: MESH_NAME
    interceptionPort: 15001
    
  2. Crie o recurso Mesh com a especificação mesh.yaml.

      gcloud network-services meshes import "MESH_NAME" \
          --source=mesh.yaml \
          --location=global
    
  3. Crie uma verificação de funcionamento:

      gcloud compute health-checks create http rate-limit-demo-hc \
          --use-serving-port
    
  4. Crie uma regra de firewall para permitir ligações de verificações de estado de funcionamento de entrada a instâncias na sua rede.

      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
    
  5. Crie um serviço de back-end global com um esquema de balanceamento de carga de INTERNAL_SELF_MANAGED e adicione a verificação de funcionamento.

      gcloud compute backend-services create rate-limit-demo-service \
          --global \
          --health-checks rate-limit-demo-hc \
          --load-balancing-scheme INTERNAL_SELF_MANAGED
    
  6. Adicione o NEG rate-limit-demo-neg ao serviço de back-end.

      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
    
  7. Crie a especificação HTTPRoute e guarde-a num ficheiro denominado 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"
    
  8. Crie o recurso HTTPRoute com base na especificação no ficheiro http_route.yaml.

      gcloud network-services http-routes import rate-limit-demo-http-route \
          --source=http_route.yaml \
          --location=global
    

Configure a limitação de taxa com o Envoy

As secções seguintes explicam como configurar a limitação de taxa do lado do servidor para a sua malha de serviços. A primeira secção mostra como configurar um limite de taxa global do lado do servidor para todos os clientes e a segunda secção mostra como aplicar limites de taxa diferentes para diferentes grupos de clientes.

Configure a limitação de taxa global do lado do servidor

Neste exemplo, cria uma regra de limitação de velocidade do lado do servidor que aplica a limitação de velocidade a todos os clientes.

  1. Num ficheiro YAML denominado rate-limit-policy.yaml, crie uma política de segurança do Cloud Armor com o tipo CLOUD_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"
    
  2. Crie a política de segurança denominada rate-limit-policy:

      gcloud beta compute security-policies create rate-limit-policy \
          --global \
          --file-name=rate-limit-policy.yaml
    
  3. Num ficheiro YAML, crie uma política de ponto final que faça referência à política de segurança que criou no passo anterior. Nestes exemplos, este ficheiro chama-se 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
    
  4. Crie uma política de ponto final com o nome rate-limit-ep:

      gcloud beta network-services endpoint-policies import rate-limit-ep \
          --source=endpoints-policies.yaml \
          --location=global
    

Configure diferentes limites de taxa do lado do servidor para diferentes grupos de clientes

Neste exemplo, cria diferentes regras de limitação de taxa do lado do servidor que aplicam diferentes limites de limitação de taxa para grupos de clientes.

  1. Crie uma política de segurança do Cloud Armor com o tipo CLOUD_ARMOR_INTERNAL_SERVICE com várias regras de limitação de taxa, como a definida no ficheiro seguinte. Nestes exemplos, este ficheiro chama-se 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"
    

    Esta política aplica a limitação de taxa a pedidos que contenham um cabeçalho HTTP com o nome user e o valor demo se o Cloud Service Mesh receber mais de 1000 desses pedidos num período de 60 segundos. Os pedidos que não têm este cabeçalho HTTP são, em alternativa, limitados por taxa se o Cloud Service Mesh receber mais de 10 000 desses pedidos num período de 60 segundos.

  2. Use o seguinte comando para criar a política, que se chama per-client-security-policy:

      gcloud beta compute security-policies create per-client-security-policy \
          --global \
          --file-name=per-client-security-policy.yaml
    

    Crie uma política de ponto final que faça referência à política de segurança que criou no passo anterior, como a definida no ficheiro seguinte. Neste exemplo, este ficheiro chama-se 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
    

    Use o seguinte comando para criar uma política de pontos finais com o nome rate-limit-ep:

      gcloud beta network-services endpoint-policies import rate-limit-ep \
          --source=per-client-endpoints-policies.yaml \
          --location=global
    

Valide a configuração

Pode usar a ferramenta de teste de carga Nighthawk para gerar tráfego e testar se as regras de limitação de taxa estão a ter o desempenho esperado. Use o seguinte comando para gerar tráfego com o 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

Em seguida, use o seguinte comando para ativar os registos de depuração do Envoy:

kubectl exec -it deploy/app1 -c app1 -- wget -q -O - \
    --post-data="" 'http://localhost:15000/logging?level=debug'

Para ver os relatórios de utilização que o Envoy envia para o servidor de gestão, consulte o artigo Aceder aos seus registos.

Pode esperar ver o seguinte nos resultados dos testes:

  • Demora cerca de cinco minutos até que a limitação de taxa entre em vigor.
  • Após o período de aquecimento inicial, vê cerca de 15 a 21 QPS na saída do cliente do Nighthawk, no contador benchmark.http_2xx. Isto significa que o Cloud Armor permite cerca de 1000 pedidos por minuto.

Para ver a eficácia das regras da política de segurança do Cloud Armor, consulte Ver o painel de controlo de monitorização.

Desative a limitação de velocidade

Pode desativar a limitação de taxa através de um dos seguintes métodos:

  • Pode eliminar as políticas de pontos finais e as políticas de segurança que configurou com as suas regras de limitação de taxa.
  • Pode desanexar a política de segurança da política de pontos finais atualizando a política de pontos finais para remover o campo securityPolicies.

As secções seguintes explicam como desativar a limitação de taxa através de cada método.

Elimine uma política de ponto final e uma política de segurança

Primeiro, use o seguinte comando gcloud para eliminar a sua política de ponto final com o nome rate-limit-ep. Se usou o nome fornecido no primeiro ou segundo exemplo nesta página, a política de endpoint tem o nome endpoints-policies ou per-client-endpoints-policies respetivamente.

gcloud beta network-services endpoint-policies delete --location=global rate-limit-ep

Em seguida, use o seguinte comando gcloud para eliminar uma política de segurança, substituindo per-client-security-policy pelo nome da sua política de segurança. Se usou o nome indicado no primeiro ou segundo exemplo desta página, a sua política de segurança tem o mesmo nome que a sua política de ponto final.

gcloud beta compute security-policies delete --global per-client-security-policy

Desanexe uma política de segurança da sua política de pontos finais

Primeiro, atualize o ficheiro endpoint-policy.yaml para remover o campo securityPolcies:

name: "rate-limit-ep"
endpointMatcher:
  metadataLabelMatcher:
    metadataLabelMatchCriteria: MATCH_ALL
    metadataLabels:
    - labelName: app
      labelValue: rate-limit-demo
type: SIDECAR_PROXY

Em seguida, use o seguinte comando para atualizar a política de ponto final com o nome rate-limit-ep com as alterações ao ficheiro endpoint-policy.yaml:

gcloud beta network-services endpoint-policies import rate-limit-ep \
    --source=endpoints-policies.yaml \
    --location=global