Cloud Service Mesh regional

Com o isolamento regional, os clientes que se conectam a uma região específica do plano de controle do Cloud Service Mesh só podem acessar recursos nessa região. Da mesma forma, os recursos de API em uma região específica só podem se referir a outros recursos nessa região.

O Cloud Service Mesh regional tem as seguintes limitações:

  • A API Istio não é compatível. Não é possível usar o Kubernetes com a API Istio usando o Traffic Director regional. Somente APIs Google Cloud são compatíveis nesta prévia.
  • As considerações e limitações atuais das APIs globais de roteamento de serviço se aplicam.
  • A versão mínima do Envoy para oferecer suporte a esquemas de nomenclatura xdSTP é a v1.31.1.
  • A API Gateway for Mesh não é compatível.
  • A versão mínima do gRPC é v1.65.
  • Somente as seguintes regiões são compatíveis:

    africa-south1
    asia-east1
    asia-east2
    asia-northeast1
    asia-northeast2
    asia-northeast3
    asia-south1
    asia-south2
    asia-southeast1
    asia-southeast2
    australia-southeast1
    australia-southeast2
    europe-central2
    europe-north1
    europe-north2
    europe-southwest1
    europe-west10
    europe-west12
    europe-west1
    europe-west2
    europe-west3
    europe-west4
    europe-west6
    europe-west8
    europe-west9
    me-central1
    me-central2
    me-west1
    northamerica-northeast1
    northamerica-northeast2
    northamerica-south1
    southamerica-east1
    southamerica-west1
    us-central1
    us-east1
    us-east4
    us-east5
    us-south1
    us-west1
    us-west2
    us-west3
    us-west4
    

Preços

Cada região em que o Cloud Service Mesh regional é compatível terá uma SKU regional quando esse recurso estiver em disponibilidade geral. Por enquanto, os preços são os mesmos da versão global.

Preparar o cliente xDS para o Cloud Service Mesh

xDS do Envoy da VM do Compute

Manual

As etapas manuais se baseiam em Configurar VMs usando a implantação manual do Envoy. A principal diferença é que ENVOY_CONTROL_PLANE_REGION é definido e injetado na inicialização.

  1. Crie o modelo da instância:

    gcloud compute instance-templates create td-vm-templategcloud compute instance-templates create td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=http-td-tag,http-server,https-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script='#! /usr/bin/env bash
    
    # Set variables
    export ENVOY_CONTROL_PLANE_REGION="us-central1"
    export ENVOY_USER="envoy"
    export ENVOY_USER_UID="1337"
    export ENVOY_USER_GID="1337"
    export ENVOY_USER_HOME="/opt/envoy"
    export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
    export ENVOY_PORT="15001"
    export ENVOY_ADMIN_PORT="15000"
    export ENVOY_TRACING_ENABLED="false"
    export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
    export ENVOY_ACCESS_LOG="/dev/stdout"
    export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
    export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
    export GCE_METADATA_SERVER="169.254.169.254/32"
    export INTERCEPTED_CIDRS="*"
    export GCP_PROJECT_NUMBER=PROJECT_NUMBER
    export VPC_NETWORK_NAME=mesh:sidecar-mesh
    export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)
    
    # Create system user account for Envoy binary
    sudo groupadd ${ENVOY_USER} \
      --gid=${ENVOY_USER_GID} \
      --system
    sudo adduser ${ENVOY_USER} \
      --uid=${ENVOY_USER_UID} \
      --gid=${ENVOY_USER_GID} \
      --home=${ENVOY_USER_HOME} \
      --disabled-login \
      --system
    # Download and extract the Cloud Service Mesh tar.gz file
    cd ${ENVOY_USER_HOME}
    sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
      -C bootstrap_template.yaml \
      --strip-components 1
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
      -C iptables.sh \
      --strip-components 1
    sudo rm traffic-director-xdsv3.tar.gz
    
    # Generate Envoy bootstrap configuration
    cat "${BOOTSTRAP_TEMPLATE}" \
      | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
      | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
      | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
      | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
      | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
      | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
      | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
      | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
      | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
      | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
      | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
      | sudo tee "${ENVOY_CONFIG}"
    
    # Install Envoy binary
    wget -O envoy_key https://apt.envoyproxy.io/signing.key
    cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
    sudo apt-get update
    sudo apt-get install envoy
    
    # Run Envoy as systemd service
    sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
      --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
      bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"
    
    # Configure iptables for traffic interception and redirection
    sudo ${ENVOY_USER_HOME}/iptables.sh \
      -p "${ENVOY_PORT}" \
      -u "${ENVOY_USER_UID}" \
      -g "${ENVOY_USER_GID}" \
      -m "REDIRECT" \
      -i "${INTERCEPTED_CIDRS}" \
      -x "${GCE_METADATA_SERVER}"
    

xDS do gRPC da VM do Compute

Assim como no Cloud Service Mesh global, os clientes gRPC precisam configurar um bootstrap para informar como se conectar ao Cloud Service Mesh regional.

Use o gerador de inicialização do gRPC para gerar essa inicialização. Para definir o uso do Cloud Service Mesh regional, especifique uma nova flag: --xds-server-region.

Neste exemplo, definir xds-server-region como us-central1 determina automaticamente o endpoint regional do Cloud Service Mesh: trafficdirector.us-central1.rep.googleapis.com:443.

Injeção manual do Envoy no K8s

As etapas manuais se baseiam em Configurar pods do Google Kubernetes Engine usando injeção manual do Envoy. No entanto, você só precisa modificar a seção sobre injeção manual de pods.

  1. Mude o plano de controle de global para regional:

    wget -q -O - https://storage.googleapis.com/traffic-director/demo/trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s/PROJECT_NUMBER/PROJECT_NUMBER/g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s/MESH_NAME/MESH_NAME/g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s|trafficdirector.googleapis.com|trafficdirector.${REGION}.rep.googleapis.com|g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s|gcr.io/google-containers/busybox|busybox:stable|g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    1. Aplique as alterações:

      kubectl apply -f trafficdirector_client_new_api_sample_xdsv3.yaml
        ```
      

Guias de configuração

A seção aborda cinco configurações e modelos de implantação independentes. Todas são versões regionalizadas dos guias de configuração da API de roteamento de serviço global.

Configurar serviços gRPC sem proxy com GRPCRoute regional e Cloud Service Mesh regional

Nesta seção, explicamos como configurar uma malha de serviço gRPC sem proxy com a malha de serviço do Cloud regional e recursos GRPCRoute regionais.

Para sua conveniência, armazene o número do projeto Google Cloud em que você realiza a configuração para que todos os exemplos neste guia possam ser copiados e colados na linha de comando:

export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"

Substitua PROJECT_NUMBER pelo número do projeto.

Também é possível substituir o seguinte:

  • us-central1 por uma região diferente que você quer usar.
  • us-central1-a por uma zona diferente que você quer usar.
  • default com um VPC_NAME diferente.

Configuração da malha

Quando um aplicativo gRPC sem proxy se conecta a um xds://hostname, a biblioteca de cliente do gRPC estabelece uma conexão com o Cloud Service Mesh para receber a configuração de roteamento necessária para encaminhar solicitações para o nome do host.

  1. Crie uma especificação de malha e armazene-a no arquivo mesh.yaml:

    cat <<EOF > mesh.yaml
    name: grpc-mesh
    EOF
    
  2. Crie uma malha usando a especificação mesh.yaml:

    gcloud network-services meshes import grpc-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

    Depois que a malha regional é criada, o Cloud Service Mesh está pronto para disponibilizar a configuração. No entanto, como ainda não há serviços definidos, a configuração está vazia.

Configuração do serviço gRPC

Para fins de demonstração, você vai criar um serviço de back-end regional com VMs com escalonamento automático (usando grupos gerenciados de instâncias, MIG) que vai veicular hello world usando o protocolo gRPC na porta 50051.

  1. Crie o modelo de instância de VM do Compute Engine com um serviço gRPC helloworld que é exposto na porta 50051:

    gcloud compute instance-templates create grpc-td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=allow-health-checks \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata-from-file=startup-script=<(echo '#! /bin/bash
    set -e
    cd /root
    sudo apt-get update -y
    sudo apt-get install -y openjdk-11-jdk-headless
    curl -L https://github.com/grpc/grpc-java/archive/v1.38.0.tar.gz | tar -xz
    cd grpc-java-1.38.0/examples/example-hostname
    ../gradlew --no-daemon installDist
    # Server listens on 50051
    sudo systemd-run ./build/install/hostname-server/bin/hostname-server')
    
  2. Crie um MIG com base no modelo:

    gcloud compute instance-groups managed create grpc-td-mig-us-central1 \
      --zone=${ZONE} \
      --size=2 \
      --template=grpc-td-vm-template
    
  3. Configure uma porta nomeada para o serviço gRPC. Essa é a porta em que o serviço gRPC está configurado para detectar solicitações.

    gcloud compute instance-groups set-named-ports grpc-td-mig-us-central1 \
      --named-ports=grpc-helloworld-port:50051 \
      --zone=${ZONE}
    

    Neste exemplo, a porta é 50051.

  4. Crie verificações de integridade do gRPC.

    gcloud compute health-checks create grpc grpc-helloworld-health-check \
      --use-serving-port --region=${REGION}
    

    Os serviços precisam implementar o protocolo de verificação de integridade do gRPC para que as verificações de integridade do gRPC funcionem corretamente. Para mais informações, consulte Como criar verificações de integridade.

  5. Crie uma regra de firewall para permitir conexões de verificação de integridade de entrada com instâncias na sua rede:

    gcloud compute firewall-rules create grpc-vm-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \
      --target-tags allow-health-checks \
      --rules tcp:50051
    
  6. Crie um serviço de back-end regional com um esquema de balanceamento de carga de INTERNAL_SELF_MANAGED e adicione a verificação de integridade e um grupo gerenciado de instâncias criados anteriormente ao serviço de back-end. A porta no nome da porta especificado é usada para se conectar às VMs no grupo gerenciado de instâncias.

    gcloud compute backend-services create grpc-helloworld-service \
        --load-balancing-scheme=INTERNAL_SELF_MANAGED \
        --protocol=GRPC \
        --port-name=grpc-helloworld-port \
      --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/grpc-helloworld-health-check" \
        --region=${REGION}
    
  7. Adicione o grupo gerenciado de instâncias ao BackendService:

    gcloud compute backend-services add-backend grpc-helloworld-service \
      --instance-group=grpc-td-mig-us-central1 \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

Configurar o roteamento com GRPCRoute regional

Neste ponto, a malha regional e o serviço de servidor gRPC estão configurados. Agora você pode configurar o roteamento necessário.

  1. Crie a especificação regional de GRPCRoute e armazene-a no arquivo grpc_route.yaml:

    cat <<EOF > grpc_route.yaml
    name: helloworld-grpc-route
    hostnames:
    - helloworld-gce
    meshes:
    - projects/${PROJECT_NUMBER}/locations/${REGION}/meshes/grpc-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/grpc-helloworld-service
    EOF
    
  2. Crie um GRPCRoute regional usando a especificação grpc_route.yaml:

    gcloud network-services grpc-routes import helloworld-grpc-route \
        --source=grpc_route.yaml \
        --location=${REGION}
    

    O Cloud Service Mesh agora está configurado para balancear a carga do tráfego dos serviços especificados na rota gRPC nos back-ends no grupo de instâncias gerenciadas.

Criar serviço de cliente gRPC

Para verificar a configuração, crie uma instância de um aplicativo cliente com um plano de dados gRPC sem proxy. Esse aplicativo precisa especificar (no arquivo de inicialização) o nome da malha.

Depois de configurado, esse aplicativo pode enviar uma solicitação às instâncias ou endpoints associados ao helloworld-gce usando o URI de serviço xds:///helloworld-gce.

Nos exemplos a seguir, use a ferramenta grpcurl para testar o serviço gRPC.

  1. Crie uma VM cliente:

    gcloud compute instances create grpc-client \
      --zone=${ZONE}\
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata-from-file=startup-script=<(echo '#! /bin/bash
    set -ex
    export PROJECT=PROJECT_NUMBER
    export REGION=us-central1
    export GRPC_XDS_BOOTSTRAP=/run/td-grpc-bootstrap.json
    echo export GRPC_XDS_BOOTSTRAP=$GRPC_XDS_BOOTSTRAP | sudo tee /etc/profile.d/grpc-xds-bootstrap.sh
    curl -L https://storage.googleapis.com/traffic-director/td-grpc-bootstrap-0.18.0.tar.gz | tar -xz
    ./td-grpc-bootstrap-0.18.0/td-grpc-bootstrap --config-mesh=grpc-mesh --xds-server-uri=trafficdirector.${REGION}.rep.googleapis.com:443 --gcp-project-number=${PROJECT} | sudo tee $GRPC_XDS_BOOTSTRAP
    sudo sed -i "s|\"authorities\": {|\"authorities\": {\n    \"traffic-director.${REGION}.xds.googleapis.com\": {\"xds_servers\":[{\"server_uri\": \"trafficdirector.${REGION}.rep.googleapis.com:443\", \"channel_creds\": [ { \"type\": \"google_default\" } ], \"server_features\": [ \"xds_v3\", \"ignore_resource_deletion\" ]}], \"client_listener_resource_name_template\": \"xdstp://traffic-director.${REGION}.xds.googleapis.com/envoy.config.listener.v3.Listener/${PROJECT}/mesh:grpc-mesh/%s\"},|g" $GRPC_XDS_BOOTSTRAP
    sudo sed -i "s|\"client_default_listener_resource_name_template\": \"xdstp://traffic-director-global.xds.googleapis.com|\"client_default_listener_resource_name_template\": \"xdstp://traffic-director.${REGION}.xds.googleapis.com|g" $GRPC_XDS_BOOTSTRAP')
    

Configurar a variável de ambiente e o arquivo de inicialização

O aplicativo cliente precisa de um arquivo de configuração de inicialização. O script de inicialização na seção anterior define a variável de ambiente GRPC_XDS_BOOTSTRAP e usa um script auxiliar para gerar o arquivo de inicialização. Os valores de TRAFFICDIRECTOR_GCP_PROJECT_NUMBER e da zona no arquivo de inicialização gerado são recebidos do servidor de metadados que conhece esses detalhes sobre suas instâncias de VM do Compute Engine.

É possível fornecer manualmente esses valores para o script auxiliar usando a opção -gcp-project-number. É necessário fornecer um nome de malha que corresponda ao recurso de malha usando a opção -config-mesh-experimental.

  1. Para verificar a configuração, faça login no cliente:

    gcloud compute ssh grpc-client --zone=${ZONE}
    
  2. Faça o download e instale a ferramenta grpcurl:

    curl -L https://github.com/fullstorydev/grpcurl/releases/download/v1.9.3/grpcurl_1.9.3_linux_x86_64.tar.gz | tar -xz
    
  3. Execute a ferramenta grpcurl com xds:///helloworld-gce como o URI do serviço e helloworld.Greeter/SayHello como o nome e o método do serviço a serem invocados.

    ./grpcurl --plaintext \
      -d '{"name": "world"}' \
      xds:///helloworld-gce helloworld.Greeter/SayHello
    

    Os parâmetros do método SayHello são transmitidos usando a opção -d.

    Você vai ver uma saída semelhante a esta, em que INSTANCE_NAME é o nome da instância de VM:

    Greeting: Hello world, from INSTANCE_HOSTNAME
    

Isso verifica se o cliente gRPC sem proxy se conectou ao Cloud Service Mesh e aprendeu sobre os back-ends do serviço helloworld-gce usando o resolvedor de nomes xDS. O cliente enviou uma solicitação para um dos back-ends do serviço sem precisar saber sobre o endereço IP ou executar a resolução de DNS.

Configurar o proxy sidecar do Envoy com serviços HTTP usando HTTPRoute regional e malha regional

Nesta seção, explicamos como configurar uma malha de serviço baseada em proxy do Envoy com recursos de malha regional e HTTPRoute regional.

Para sua conveniência, armazene o número do projeto Google Cloud em que você realiza a configuração para que todos os exemplos neste guia possam ser copiados e colados na linha de comando:

export PROJECT_ID="PROJECT_ID"
export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"

Substitua:

  • PROJECT_ID pelo código do projeto;
  • PROJECT_NUMBER pelo número do projeto.

Também é possível substituir o seguinte:

  • us-central1 por uma região diferente que você quer usar.
  • us-central1-a por uma zona diferente que você quer usar.

Configuração da malha

O proxy sidecar Envoy recebe a configuração de roteamento de serviço do Cloud Service Mesh. O sidecar apresenta o nome do recurso de malha regional para identificar a malha de serviço específica configurada. A configuração de roteamento recebida do Cloud Service Mesh é usada para direcionar o tráfego que passa pelo proxy sidecar para vários serviços de back-end regionais, dependendo dos parâmetros de solicitação, como o nome do host ou os cabeçalhos, configurados nos recursos de rota.

O nome da malha é a chave que o proxy sidecar usa para solicitar a configuração associada a ela.

  1. Crie a especificação de malha regional e armazene-a no arquivo mesh.yaml:

    cat <<EOF > mesh.yaml
    name: sidecar-mesh
    EOF
    

    A porta de interceptação tem o padrão 15001 se não for especificada.

  2. Crie uma malha regional usando a especificação mesh.yaml:

    gcloud network-services meshes import sidecar-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

    Depois que a malha regional é criada, o Cloud Service Mesh está pronto para disponibilizar a configuração. No entanto, como ainda não há serviços definidos, a configuração vai estar vazia.

Configuração do servidor HTTP

Para fins de demonstração, crie um serviço de back-end regional com VMs com escalonamento automático (usando grupos gerenciados de instâncias, MIG) que vai veicular "hello world" usando o protocolo gRPC na porta 80.

  1. Crie o modelo de instância de VM do Compute Engine com um serviço HTTP helloworld exposto na porta 80:

    gcloud compute instance-templates create td-httpd-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=http-td-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script="#! /bin/bash
    
    sudo apt-get update -y
    sudo apt-get install apache2 -y
    sudo service apache2 restart
    echo '<!doctype html><html><body><h1>'\`/bin/hostname\`'</h1></body></html>' | sudo tee /var/www/html/index.html"
    
  2. Crie um MIG com base no modelo:

    gcloud compute instance-groups managed create http-td-mig-us-central1 \
      --zone=${ZONE} \
      --size=2 \
      --template=td-httpd-vm-template
    
  3. Crie as verificações de integridade:

    gcloud compute health-checks create http http-helloworld-health-check --region=${REGION}
    
  4. Crie uma regra de firewall para permitir conexões de verificação de integridade de entrada com instâncias na sua rede:

    gcloud compute firewall-rules create http-vm-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \
      --target-tags http-td-server \
      --rules tcp:80
    
  5. Crie um serviço de back-end regional com um esquema de balanceamento de carga de INTERNAL_SELF_MANAGED:

    gcloud compute backend-services create http-helloworld-service \
        --load-balancing-scheme=INTERNAL_SELF_MANAGED \
        --protocol=HTTP \
    --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/http-helloworld-health-check" \
        --region=${REGION}
    
  6. Adicione a verificação de integridade e um grupo de instâncias gerenciadas ou não gerenciadas ao serviço de back-end:

    gcloud compute backend-services add-backend http-helloworld-service \
      --instance-group=http-td-mig-us-central1 \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

    Este exemplo usa o grupo gerenciado de instâncias com o modelo de VM do Compute Engine que executa o serviço HTTP de amostra criado anteriormente.

Configurar o roteamento com HTTPRoute regional

O recurso de malha e o servidor HTTP estão configurados. Agora é possível conectá-los usando um recurso HTTPRoute que associa um nome de host a um serviço de back-end.

  1. Crie a especificação HTTPRoute e armazene como http_route.yaml:

    cat <<EOF > http_route.yaml
    name: helloworld-http-route
    hostnames:
    - helloworld-gce
    meshes:
    - projects/${PROJECT_NUMBER}/locations/${REGION}/meshes/sidecar-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/http-helloworld-service
    EOF
    
  2. Crie o HTTPRoute usando a especificação http_route.yaml:

    gcloud network-services http-routes import helloworld-http-route \
        --source=http_route.yaml \
        --location=${REGION}
    

    O Cloud Service Mesh agora está configurado para balancear a carga do tráfego dos serviços especificados na HTTPRoute nos back-ends no grupo gerenciado de instâncias.

Criar um cliente HTTP com sidecar do Envoy

Nesta seção, você vai instanciar uma VM cliente com um proxy sidecar do Envoy para solicitar a configuração do Cloud Service Mesh criada anteriormente. O parâmetro mesh no comando da Google Cloud CLI faz referência ao recurso de malha criado anteriormente.

gcloud compute instance-templates create td-vm-template \
  --scopes=https://www.googleapis.com/auth/cloud-platform \
  --tags=http-td-tag,http-server,https-server \
  --image-family=debian-11 \
  --image-project=debian-cloud \
  --metadata=startup-script='#! /usr/bin/env bash

# Set variables
export ENVOY_CONTROL_PLANE_REGION="us-central1"
export ENVOY_USER="envoy"
export ENVOY_USER_UID="1337"
export ENVOY_USER_GID="1337"
export ENVOY_USER_HOME="/opt/envoy"
export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
export ENVOY_PORT="15001"
export ENVOY_ADMIN_PORT="15000"
export ENVOY_TRACING_ENABLED="false"
export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
export ENVOY_ACCESS_LOG="/dev/stdout"
export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
export GCE_METADATA_SERVER="169.254.169.254/32"
export INTERCEPTED_CIDRS="*"
export GCP_PROJECT_NUMBER=PROJECT_NUMBER
export VPC_NETWORK_NAME=mesh:sidecar-mesh
export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)

# Create system user account for Envoy binary
sudo groupadd ${ENVOY_USER} \
  --gid=${ENVOY_USER_GID} \
  --system
sudo adduser ${ENVOY_USER} \
  --uid=${ENVOY_USER_UID} \
  --gid=${ENVOY_USER_GID} \
  --home=${ENVOY_USER_HOME} \
  --disabled-login \
  --system
# Download and extract the Cloud Service Mesh tar.gz file
cd ${ENVOY_USER_HOME}
sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
  -C bootstrap_template.yaml \
  --strip-components 1
sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
  -C iptables.sh \
  --strip-components 1
sudo rm traffic-director-xdsv3.tar.gz

# Generate Envoy bootstrap configuration
cat "${BOOTSTRAP_TEMPLATE}" \
  | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
  | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
  | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
  | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
  | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
  | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
  | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
  | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
  | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
  | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
  | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
  | sudo tee "${ENVOY_CONFIG}"

# Install Envoy binary
wget -O envoy_key https://apt.envoyproxy.io/signing.key
cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
sudo apt-get update
sudo apt-get install envoy

# Run Envoy as systemd service
sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
  --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
  bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"

# Configure iptables for traffic interception and redirection
sudo ${ENVOY_USER_HOME}/iptables.sh \
  -p "${ENVOY_PORT}" \
 -u "${ENVOY_USER_UID}" \
  -g "${ENVOY_USER_GID}" \
  -m "REDIRECT" \
  -i "${INTERCEPTED_CIDRS}" \
  -x "${GCE_METADATA_SERVER}"
'

gcloud compute instances create td-vm-client \
  --zone=${ZONE} \
  --source-instance-template td-vm-template
  1. Faça login na VM criada:

    gcloud compute ssh td-vm-client --zone=${ZONE}
    
  2. Verifique a conectividade HTTP com os serviços de teste criados:

    curl -H "Host: helloworld-gce" http://10.0.0.1/
    

    O comando retorna uma resposta de uma das VMs no grupo gerenciado de instâncias com o nome do host impresso no console.

Como configurar serviços TCP com TCPRoute regional

Esse fluxo de configuração é muito semelhante a Configurar proxies do Envoy com serviços HTTP com uma exceção: o serviço de back-end fornece um serviço TCP e o roteamento baseado em parâmetros TCP/IP é usado em vez de baseado no protocolo HTTP.

Para sua conveniência, armazene o número do projeto Google Cloud em que você realiza a configuração para que todos os exemplos neste guia possam ser copiados e colados na linha de comando:

export PROJECT_ID="PROJECT_ID"
export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"

Substitua:

  • PROJECT_ID pelo código do projeto;
  • PROJECT_NUMBER pelo número do projeto.

Também é possível substituir o seguinte:

  • us-central1 por uma região diferente que você quer usar.
  • us-central1-a por uma zona diferente que você quer usar.

Configuração da malha

  1. Crie a especificação de malha regional e armazene-a no arquivo mesh.yaml:

    cat <<EOF > mesh.yaml
    name: sidecar-mesh
    EOF
    
  2. Crie uma malha regional usando a especificação mesh.yaml:

    gcloud network-services meshes import sidecar-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

Configuração do servidor TCP

Para fins de demonstração, você vai criar um serviço de back-end regional com VMs com escalonamento automático (usando grupos gerenciados de instâncias, MIG) que vai veicular "hello world" usando o protocolo gRPC na porta 10000.

  1. Crie o modelo de instância de VM do Compute Engine com um serviço de teste na porta 10000 usando o utilitário netcat:

    gcloud compute instance-templates create tcp-td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=allow-health-checks \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script="#! /bin/bash
    sudo apt-get update -y
    sudo apt-get install netcat -y
    while true;
      do echo 'Hello from TCP service' | nc -l -s 0.0.0.0 -p 10000;
    done &"
    
  2. Crie um MIG com base no modelo:

    gcloud compute instance-groups managed create tcp-td-mig-us-central1 \
      --zone=${ZONE} \
      --size=1 \
      --template=tcp-td-vm-template
    
  3. Defina as portas nomeadas no grupo gerenciado de instâncias criado como port 10000:

    gcloud compute instance-groups set-named-ports tcp-td-mig-us-central1 \
      --zone=${ZONE} --named-ports=tcp:10000
    
  4. Criar uma verificação de integridade regional:

    gcloud compute health-checks create tcp tcp-helloworld-health-check --port 10000 --region=${REGION}
    
  5. Crie uma regra de firewall para permitir conexões de verificação de integridade de entrada com instâncias na sua rede:

    gcloud compute firewall-rules create tcp-vm-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \
      --target-tags allow-health-checks \
      --rules tcp:10000
    
  6. Crie um serviço de back-end regional com um esquema de balanceamento de carga INTERNAL_SELF_MANAGED e adicione a verificação de integridade e um grupo de instâncias gerenciadas ou não gerenciadas ao serviço de back-end.

    gcloud compute backend-services create tcp-helloworld-service \
        --region=${REGION} \
        --load-balancing-scheme=INTERNAL_SELF_MANAGED \
        --protocol=TCP \
        --port-name=tcp \
        --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/tcp-helloworld-health-check"
    
  7. Adicione o MIG ao BackendService:

    gcloud compute backend-services add-backend tcp-helloworld-service \
      --instance-group tcp-td-mig-us-central1 \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

Configurar o roteamento com TCPRoute regional

  1. Crie a especificação TCPRoute e armazene-a no arquivo tcp_route.yaml:

    cat <<EOF > tcp_route.yaml
    name: helloworld-tcp-route
    meshes:
    - projects/$PROJECT_NUMBER/locations/$REGION/meshes/sidecar-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/$PROJECT_NUMBER/locations/$REGION/backendServices/tcp-helloworld-service
      matches:
      - address: '10.0.0.1/32'
        port: '10000'
    EOF
    
  2. Crie um TCPRoute usando a especificação tcp_route.yaml:

    gcloud network-services tcp-routes import helloworld-tcp-route \
        --source=tcp_route.yaml \
        --location=${REGION}
    

Criar um cliente TCP com um sidecar do Envoy

  1. Crie uma VM com o Envoy conectado ao Cloud Service Mesh:

    gcloud compute instance-templates create td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=http-td-tag,http-server,https-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script='#! /usr/bin/env bash
    
    # Set variables
    export ENVOY_CONTROL_PLANE_REGION="us-central1"
    export ENVOY_USER="envoy"
    export ENVOY_USER_UID="1337"
    export ENVOY_USER_GID="1337"
    export ENVOY_USER_HOME="/opt/envoy"
    export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
    export ENVOY_PORT="15001"
    export ENVOY_ADMIN_PORT="15000"
    export ENVOY_TRACING_ENABLED="false"
    export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
    export ENVOY_ACCESS_LOG="/dev/stdout"
    export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
    export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
    export GCE_METADATA_SERVER="169.254.169.254/32"
    export INTERCEPTED_CIDRS="*"
    export GCP_PROJECT_NUMBER=PROJECT_NUMBER
    export VPC_NETWORK_NAME=mesh:sidecar-mesh
    
    export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)
    
    # Create system user account for Envoy binary
    sudo groupadd ${ENVOY_USER} \
      --gid=${ENVOY_USER_GID} \
      --system
    sudo adduser ${ENVOY_USER} \
      --uid=${ENVOY_USER_UID} \
      --gid=${ENVOY_USER_GID} \
      --home=${ENVOY_USER_HOME} \
      --disabled-login \
      --system
    # Download and extract the Cloud Service Mesh tar.gz file
    cd ${ENVOY_USER_HOME}
    sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
      -C bootstrap_template.yaml \
      --strip-components 1
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
      -C iptables.sh \
      --strip-components 1
    sudo rm traffic-director-xdsv3.tar.gz
    
    # Generate Envoy bootstrap configuration
    cat "${BOOTSTRAP_TEMPLATE}" \
      | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
      | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
      | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
      | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
      | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
      | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
      | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
      | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
      | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
      | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
      | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
      | sudo tee "${ENVOY_CONFIG}"
    
    # Install Envoy binary
    wget -O envoy_key https://apt.envoyproxy.io/signing.key
    cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
    sudo apt-get update
    sudo apt-get install envoy
    
    # Run Envoy as systemd service
    sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
      --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
      bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"
    
    # Configure iptables for traffic interception and redirection
    sudo ${ENVOY_USER_HOME}/iptables.sh \
      -p "${ENVOY_PORT}" \
    -u "${ENVOY_USER_UID}" \
      -g "${ENVOY_USER_GID}" \
      -m "REDIRECT" \
      -i "${INTERCEPTED_CIDRS}" \
      -x "${GCE_METADATA_SERVER}"
    '
    
    gcloud compute instances create td-vm-client \
      --zone=${ZONE} \
      --source-instance-template td-vm-template
    
  2. Faça login na VM criada:

    gcloud compute ssh td-vm-client --zone=${ZONE}
    
  3. Verifique a conectividade com os serviços de teste criados:

    curl 10.0.0.1:10000 --http0.9 -v
    

    Você vai ver um texto Hello from TCP service retornado, além de todo o texto digitado pelo serviço netcat em execução na VM remota.

Configuração de malha regional no projeto host

Designar um projeto como o projeto host. Qualquer conta de serviço com permissão para criar/atualizar/excluir malhas neste projeto pode controlar as configurações de roteamento anexadas às malhas regionais neste projeto.

  1. Defina uma variável que será usada em todo o exemplo:

    export REGION="us-central1"
    

    Se quiser, substitua us-central1 por uma região diferente.

  2. Crie a especificação de malha e armazene-a no arquivo mesh.yaml:

    cat <<EOF > mesh.yaml
    name: shared-mesh
    EOF
    
  3. Defina um recurso de malha neste projeto com a configuração necessária:

    gcloud network-services meshes import shared-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

    Anote o URI completo desse recurso de malha. Os proprietários de serviços vão precisar dele no futuro para anexar as rotas a essa malha.

  4. Conceda a permissão networkservices.meshes.use do IAM a essa malha e às contas de serviço entre projetos que poderão anexar as informações de serviço a essa malha:

    gcloud projects add-iam-policy-binding HOST_PROJECT_NUMBER --member='HTTP_ROUTE_SERVICE_OWNER_ACCOUNT' --role='roles/compute.networkAdmin'
    

    Agora, todos os proprietários de serviço com permissão networkservices.meshes.use concedida podem adicionar as regras de roteamento a essa malha.

Configuração de rotas em projetos de serviço

Cada proprietário de serviço precisa criar serviços de back-end regionais e recursos de rota regionais no projeto, de forma semelhante a Configurar proxies do Envoy com serviços HTTP. A única diferença é que cada HTTPRoute/GRPCRoute/TCPRoute teria o URI do recurso de malha do projeto host no campo meshes.

  1. Crie uma sharedvpc-http-route:

    echo "name: sharedvpc-http-route
    hostnames:
    - helloworld-gce
    meshes:
    - /projects/HOST_PROJECT_NUMBER/locations/${REGION}/meshes/shared-mesh
    rules:
    - action:
        destinations:
        - serviceName: \"SERVICE_URL\"" | \
    gcloud network-services http-routes import sharedvpc-http-route \
        --source=- \
        --location=${REGION}
    

Como configurar serviços de cliente em projetos de serviço

Ao configurar um cliente do Cloud Service Mesh (proxy Envoy ou sem proxy) que está localizado em um projeto de serviço, é necessário especificar o número do projeto em que o recurso de malha está localizado e o nome da malha na configuração de inicialização:

TRAFFICDIRECTOR_GCP_PROJECT_NUMBER=HOST_PROJECT_NUMBER
TRAFFICDIRECTOR_MESH_NAME=MESH_NAME

Roteamento de TLS do gateway

Esta seção demonstra como configurar um gateway de entrada baseado em proxy do Envoy com recursos regionais de gateway e TLSRoute.

Um balanceador de carga de rede de passagem regional externo direciona o tráfego para proxies do Envoy que atuam como um gateway de entrada. Os proxies do Envoy usam roteamento de passagem de TLS e tráfego direto para servidores HTTPS em execução nas instâncias de VM de back-end.

Defina algumas variáveis que serão usadas em todo o exemplo.

export PROJECT_ID="PROJECT_ID"
export PROJECT_NUMBER="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-b"
export NETWORK_NAME = "default"

Substitua: default

  • PROJECT_ID pelo código do projeto;
  • PROJECT_NUMBER pelo número do projeto.

Também é possível substituir o seguinte:

  • us-central1 por uma região diferente que você quer usar.
  • us-central1-b por uma zona diferente que você quer usar.
  • default com um nome de rede diferente que você quer usar.

Referência cruzada de recursos de malha regional e rota regional em um ambiente de VPC compartilhada de vários projetos

Há cenários em que a configuração da malha de serviço consiste em serviços que são de propriedade de projetos diferentes. Por exemplo, em implantações de VPC compartilhada ou de VPC com peering, cada proprietário do projeto pode definir o próprio conjunto de serviços para disponibilizar esses serviços a todos os outros projetos.

Essa configuração é "entre projetos" porque vários recursos definidos em projetos diferentes são combinados para formar uma única configuração que pode ser veiculada para um proxy ou cliente sem proxy.

Configurar regras de firewall

  1. Configure regras de firewall para permitir tráfego de qualquer origem. Edite os comandos para suas portas e intervalos de endereços IP de origem.

    gcloud compute firewall-rules create allow-gateway-health-checks \
    --network=${NETWORK_NAME} \
    --direction=INGRESS \
    --action=ALLOW \
    --rules=tcp \
    --source-ranges="35.191.0.0/16,209.85.152.0/22,209.85.204.0/22" \
    --target-tags=gateway-proxy
    

configure as permissões do IAM

  1. Crie uma identidade de conta de serviço para os proxies de gateway:

    gcloud iam service-accounts create gateway-proxy
    
  2. Atribua os papéis do IAM necessários à identidade da conta de serviço:

    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="serviceAccount:gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \
      --role="roles/trafficdirector.client"
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="serviceAccount:gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \
      --role="roles/logging.logWriter"
    

Configure o gateway regional:

  1. Em um arquivo chamado gateway8443.yaml, crie a especificação do gateway para tráfego HTTP:

    cat <<EOF > gateway8443.yaml
    name: gateway8443
    scope: gateway-proxy-8443
    ports:
    - 8443
    type: OPEN_MESH
    EOF
    
  2. Crie o recurso de gateway regional usando a especificação gateway8443.yaml:

    gcloud network-services gateways import gateway8443 \
        --source=gateway8443.yaml \
        --location=${REGION}
    

Criar um grupo de instâncias gerenciadas com proxies do Envoy

Nesta seção, você vai criar um modelo de instância para uma VM que executa um proxy de serviço do Envoy implantado automaticamente. O escopo dos Envoys é definido como gateway-proxy. Não transmita a porta de exibição como um parâmetro da flag --service-proxy.

  1. Crie um grupo gerenciado de instâncias com proxies do Envoy:

    gcloud beta compute instance-templates create gateway-proxy \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=gateway-proxy,http-td-tag,http-server,https-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --network-interface=network=${NETWORK_NAME} \
      --service-account="gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \
      --metadata=startup-script='#! /usr/bin/env bash
    
    # Set variables
    export ENVOY_CONTROL_PLANE_REGION="us-central1"
    export GCP_PROJECT_NUMBER=PROJECT_NUMBER
    export VPC_NETWORK_NAME=scope:gateway-proxy-8443
    export ENVOY_USER="envoy"
    export ENVOY_USER_UID="1337"
    export ENVOY_USER_GID="1337"
    export ENVOY_USER_HOME="/opt/envoy"
    export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
    export ENVOY_PORT="15001"
    export ENVOY_ADMIN_PORT="15000"
    export ENVOY_TRACING_ENABLED="false"
    export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
    export ENVOY_ACCESS_LOG="/dev/stdout"
    export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
    export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
    export GCE_METADATA_SERVER="169.254.169.254/32"
    export INTERCEPTED_CIDRS="*"
    
    export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)
    
    # Create system user account for Envoy binary
    sudo groupadd ${ENVOY_USER} \
      --gid=${ENVOY_USER_GID} \
      --system
    sudo adduser ${ENVOY_USER} \
      --uid=${ENVOY_USER_UID} \
      --gid=${ENVOY_USER_GID} \
      --home=${ENVOY_USER_HOME} \
      --disabled-login \
      --system
    # Download and extract the Cloud Service Mesh tar.gz file
    cd ${ENVOY_USER_HOME}
    sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
      -C bootstrap_template.yaml \
      --strip-components 1
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
      -C iptables.sh \
      --strip-components 1
    sudo rm traffic-director-xdsv3.tar.gz
    
    # Generate Envoy bootstrap configuration
    cat "${BOOTSTRAP_TEMPLATE}" \
      | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
      | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
      | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
      | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
      | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
      | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
      | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
      | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
      | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
      | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
      | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
      | sudo tee "${ENVOY_CONFIG}"
    
    # Install Envoy binary
    wget -O envoy_key https://apt.envoyproxy.io/signing.key
    cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
    sudo apt-get update
    sudo apt-get install envoy
    
    # Run Envoy as systemd service
    sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
      --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
      bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"
    
    # Configure iptables for traffic interception and redirection
    sudo ${ENVOY_USER_HOME}/iptables.sh \
      -p "${ENVOY_PORT}" \
    -u "${ENVOY_USER_UID}" \
      -g "${ENVOY_USER_GID}" \
      -m "REDIRECT" \
      -i "${INTERCEPTED_CIDRS}" \
      -x "${GCE_METADATA_SERVER}"
    '
    
  2. Crie um grupo de instâncias gerenciadas por região a partir do modelo de instância:

    gcloud compute instance-groups managed create gateway-proxy \
      --region=${REGION} \
      --size=1 \
      --template=gateway-proxy
    
  3. Defina o nome da porta de exibição para o grupo de instâncias gerenciadas:

    gcloud compute instance-groups managed set-named-ports gateway-proxy \
      --named-ports=https:8443 \
      --region=${REGION}
    

Configurar o balanceador de carga de rede de passagem regional externo

  1. Crie um endereço IP regional e estático externo:

    gcloud compute addresses create xnlb-${REGION} \
      --region=${REGION}
    
  2. Consiga o endereço IP reservado para o balanceador de carga externo:

    gcloud compute addresses describe xnlb-${REGION} \
      --region=${REGION} --format='value(address)'
    
  3. Crie uma verificação de integridade para os proxies de gateway:

    gcloud compute health-checks create tcp xnlb-${REGION} \
      --region=${REGION} \
      --use-serving-port
    
  4. Crie um serviço de back-end para os proxies de gateway:

    gcloud compute backend-services create xnlb-${REGION} \
      --health-checks=xnlb-${REGION} \
      --health-checks-region=${REGION} \
      --load-balancing-scheme=EXTERNAL \
      --protocol=TCP \
      --region=${REGION} \
      --port-name=https
    
  5. Adicione o grupo de instâncias gerenciadas como o back-end:

    gcloud compute backend-services add-backend xnlb-${REGION} \
      --instance-group=gateway-proxy \
      --instance-group-region=${REGION} \
      --region=${REGION}
    
  6. Crie uma regra de encaminhamento para encaminhar o tráfego para os proxies do gateway:

    gcloud compute forwarding-rules create xnlb-${REGION} \
      --region=${REGION} \
      --load-balancing-scheme=EXTERNAL \
      --address=${IP_ADDRESS} \
      --ip-protocol=TCP \
      --ports=8443 \
      --backend-service=xnlb-${REGION} \
      --backend-service-region=${REGION}
    

Configurar um grupo gerenciado de instâncias com um serviço HTTPS

  1. Crie um modelo de instância com um serviço HTTPS exposto na porta 8443:

    gcloud compute instance-templates create td-https-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=https-td-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script='#! /bin/bash
    
    sudo rm -rf /var/lib/apt/lists/*
    sudo apt-get -y clean
    sudo apt-get -y update
    sudo apt-get -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common
    sudo curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
    sudo add-apt-repository -y "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
    sudo apt-get -y update
    sudo apt-get -y install docker-ce
    sudo which docker
    echo "{ \"registry-mirrors\": [\"https://mirror.gcr.io\"] }" | sudo tee -a /etc/docker/daemon.json
    sudo service docker restart
    sudo docker run -e HTTPS_PORT=9999 -p 8443:9999 --rm -dt mendhak/http-https-echo:22'
    
  2. Crie um grupo gerenciado de instâncias com base no modelo de instância:

    gcloud compute instance-groups managed create https-td-mig-us-${REGION} \
      --zone=${ZONE} \
      --size=2 \
      --template=td-https-vm-template
    
  3. Defina o nome da porta de exibição para o grupo de instâncias gerenciadas:

    gcloud compute instance-groups managed set-named-ports https-td-mig-us-${REGION} \
      --named-ports=https:8443 \
      --zone=${ZONE}
    
  4. Crie uma verificação de integridade:

    gcloud compute health-checks create https https-helloworld-health-check \
      --port=8443 --region=${REGION}
    
  5. Crie uma regra de firewall para permitir conexões de verificação de integridade de entrada com instâncias na sua rede:

    gcloud compute firewall-rules create https-vm-allow-health-checks \
      --network ${NETWORK_NAME} --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --target-tags https-td-server \
      --rules tcp:8443
    
  6. Crie um serviço de back-end regional com um esquema de balanceamento de carga de INTERNAL_SELF_MANAGED e adicione a verificação de integridade:

    gcloud compute backend-services create https-helloworld-service \
      --region=${REGION} \
      --load-balancing-scheme=INTERNAL_SELF_MANAGED \
      --port-name=https \
      --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/https-helloworld-health-check"
    
  7. Adicione o grupo de instâncias gerenciadas como um back-end ao serviço de back-end:

    gcloud compute backend-services add-backend https-helloworld-service \
      --instance-group=https-td-mig-us-${REGION} \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

Configurar o roteamento com um recurso TLSRoute

  1. Em um arquivo chamado tls_route.yaml, crie a especificação TLSRoute:

    cat <<EOF > tls_route.yaml
    name: helloworld-tls-route
    gateways:
    - projects/${PROJECT_NUMBER}/locations/${REGION}/gateways/gateway8443
    rules:
    - matches:
      - sniHost:
        - example.com
        alpn:
        - h2
      action:
        destinations:
        - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/https-helloworld-service
    EOF
    

    Na instrução anterior, TLSRoute corresponde a example.com como SNI e h2 como ALPN. Se as correspondências forem alteradas da seguinte maneira, TLSRoute corresponderá a SNI ou ALPN:

    - matches:
      - sniHost:
        - example.com
      - alpn:
        - h2
    
  2. Use a especificação tls_route.yaml para criar o recurso TLSRoute:

    gcloud network-services tls-routes import helloworld-tls-route \
        --source=tls_route.yaml \
        --location=${REGION}
    

Validar a implantação

  1. Execute o seguinte comando curl para verificar a conectividade HTTP dos serviços de teste que você criou:

    curl https://example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -k
    
  2. O comando retorna uma resposta de uma das VMs no grupo gerenciado de instâncias. O resultado será o seguinte:

    {
      "path": "/",
      "headers": {
        "host": "example.com:8443",
        "user-agent": "curl/8.16.0",
        "accept": "*/*"
      },
      "method": "GET",
      "body": "",
      "fresh": false,
      "hostname": "example.com",
      "ip": "::ffff:10.128.0.59",
      "ips": [],
      "protocol": "https",
      "query": {},
      "subdomains": [],
      "xhr": false,
      "os": {
        "hostname": "19cd7812e792"
      },
      "connection": {
        "servername": "example.com"
      }
    

Verificar com uma verificação negativa

  1. No comando a seguir, a SNI não corresponde a example.com. Portanto, o gateway rejeita a conexão:

    curl https://invalid-server.com:8443 --resolve invalid-server.com:8443:${IP_ADDRESS} -k
    
  2. No comando a seguir, o ALPN não corresponde a h2 (protocolo HTTP2), então o gateway rejeita a conexão:

    curl https://example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -k --http1.1
    

    Todos os comandos anteriores retornam o seguinte erro:

    curl: (35) OpenSSL SSL_connect: Connection reset by peer in connection.
    
  3. No comando a seguir, o cliente está criando uma conexão de texto simples (não criptografado). Portanto, o gateway rejeita a conexão com um erro 404 Not Found:

    curl example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -k