Rotear o tráfego dos serviços do Cloud Run para cargas de trabalho do Cloud Service Mesh no GKE

Nesta página, mostramos como rotear com segurança o tráfego de rede dos serviços do Cloud Run para cargas de trabalho do Cloud Service Mesh no GKE para usar APIs do Istio e aproveitar um sidecar Envoy totalmente gerenciado.

Antes de começar

As seções a seguir presumem que você tenha um cluster do GKE com o Cloud Service Mesh ativado.

Se você não tiver um serviço do GKE implantado, use o comando a seguir para implantar um serviço de exemplo:

cat <<EOF > /tmp/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: ads
spec:
  ports:
  - port: 9999
    targetPort: 8000
  selector:
    run: ads
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ads
spec:
  replicas: 1
  selector:
    matchLabels:
      run: ads
  template:
    metadata:
      labels:
        run: ads
    spec:
      containers:
      - image: docker.io/waip/simple-http:v1.0.1
        name: my-http2-svc
        ports:
        - protocol: TCP
          containerPort: 8000
      securityContext:
        fsGroup: 1337
EOF
kubectl apply -f /tmp/service.yaml

Configurar um domínio personalizado para hosts VirtualService

Um serviço virtual define regras de roteamento de tráfego. Todo tráfego correspondente é enviado para um serviço de destino nomeado

  1. Para criar uma nova zona gerenciada, faça o seguinte:

    gcloud dns managed-zones create ZONE_NAME \
      --description="zone for service mesh routes" \
      --dns-name=DNS_SUFFIX. \
      --networks=default \
      --visibility=private
    

    em que:

    • ZONE_NAME é um nome para sua zona (por exemplo, "prod").
    • DNS_SUFFIX é qualquer host DNS válido (por exemplo, "mesh.private").
  2. Crie um conjunto de registros de recurso:

    IP=10.0.0.1
    gcloud dns record-sets create '*.'"DNS_SUFFIX." --type=A --zone="ZONE_NAME" \
      --rrdatas=10.0.0.1 --ttl 3600
    

    Verifique se o IP (RFC 1918 obrigatório) não está em uso. Como alternativa, reserve um IP interno estático.

  3. Exporte um VirtualService para clientes externos do Cloud Run:

    cat <<EOF > virtual-service.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: VIRTUAL_SERVICE_NAME
      namespace: NAMESPACE
    spec:
      hosts:
      - GKE_SERVICE_NAME.DNS_SUFFIX
      gateways:
      - external-mesh
      http:
      - route:
        - destination:
            host: GKE_SERVICE_NAME
    EOF
    kubectl apply -f virtual-service.yaml
    

    em que:

    • VIRTUAL_SERVICE_NAME é um nome para sua VirtualService.
    • NAMESPACE é default se você estiver usando o serviço de exemplo fornecido. Caso contrário, substitua NAMESPACE pelo nome do namespace.
    • GKE_SERVICE_NAME é ads se você estiver usando o serviço de exemplo fornecido. Caso contrário, substitua GKE_SERVICE_NAME por um nome para seu serviço do GKE.

Embora seja possível adicionar um gateway external-mesh como destino a um VirtualService preexistente, é necessário estabelecer um VirtualService distinto para exportar um serviço do Kubernetes para clientes externos do Cloud Run. Ter um VirtualService separado facilita o gerenciamento de serviços exportados e as configurações deles sem afetar os clientes do GKE atuais. Além disso, alguns campos em VirtualServices são ignorados para VirtualServices externo de malha, mas continuam funcionando como esperado para os serviços do GKE. Portanto, gerenciar e resolver problemas com VirtualServices separadamente pode ser vantajoso.

Para que os clientes do GKE também recebam a configuração VirtualService, é necessário adicionar o gateway mesh ou mesh/default.

O VirtualService externo da malha precisa ser definido no mesmo namespace do serviço do Kubernetes no destino VirtualService.

Configurar um serviço do Cloud Run para ingressar em uma service mesh

Para conectar um serviço do Cloud Run a uma service mesh, siga estas etapas:

  1. Determine o ID da malha que dá suporte ao cluster do GKE do Cloud Service Mesh:

    MESH=$(kubectl get controlplanerevision --namespace istio-system -o json | jq -r '.items[0].metadata.annotations["mesh.cloud.google.com/external-mesh"]')
    
  2. Implante um serviço do Cloud Run usando o ID de malha, conectando-se também à rede VPC do cluster:

    gcloud alpha run deploy --mesh "$MESH" --network default \
      mesh-svc --image=fortio/fortio \
      --region=REGION --project=PROJECT_ID --no-allow-unauthenticated
    
  3. Verifique se o serviço do Cloud Run pode enviar uma solicitação para a carga de trabalho do GKE:

    TEST_SERVICE_URL=$(gcloud run services describe mesh-svc --region REGION --format="value(status.url)" --project=PROJECT_ID)
    
    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" "$TEST_SERVICE_URL/fortio/fetch/GKE_SERVICE_NAME.DNS_SUFFIX"
    

    A saída precisa ser uma resposta HTTP 200 válida.

Solução de problemas

Esta seção mostra como resolver erros comuns com o Cloud Service Mesh e o Cloud Run.

Registros do sidecar do Cloud Run

Os erros do Envoy são registrados no Cloud Logging.

Por exemplo, um erro como o seguinte será registrado se a conta de serviço do Cloud Run não receber a função de cliente do TrafficDirector no projeto de mesh:

StreamAggregatedResources gRPC config stream to trafficdirector.googleapis.com:443 closed: 7, Permission 'trafficdirector.networks.getConfigs' denied on resource '//trafficdirector.googleapis.com/projects/525300120045/networks/mesh:test-mesh/nodes/003fb3e0c8927482de85f052444d5e1cd4b3956e82b00f255fbea1e114e1c0208dbd6a19cc41694d2a271d1ab04b63ce7439492672de4499a92bb979853935b03d0ad0' (or it may not exist).

CSDS

O estado do cliente do Traffic Director pode ser recuperado usando o CSDS:

gcloud alpha container fleet mesh debug proxy-status --membership=<CLUSTER_MEMBERSHIP> --location=<CLUSTER_LOCATION>
External Clients:
....

A seguir