Configurar o Google Kubernetes Engine e os serviços gRPC sem proxy

Neste guia, descrevemos como configurar o Google Kubernetes Engine, os aplicativos gRPC e os componentes de balanceamento de carga exigidos pelo Cloud Service Mesh.

Antes de seguir as instruções deste guia, consulte Como se preparar para configurar o Cloud Service Mesh com serviços gRPC sem proxy.

Visão geral

A configuração do Cloud Service Mesh com o GKE e os serviços gRPC sem proxy envolve o seguinte:

  1. Como preparar seu cluster do GKE
  2. implantar um aplicativo de servidor gRPC como um serviço do Kubernetes; Anote a especificação de implantação do GKE para criar automaticamente um grupo de endpoints de rede (NEG) para o serviço.
  3. configurar o Cloud Service Mesh usando o NEG e outros componentes de balanceamento de carga do Google Cloud;
  4. verificar se a implantação funciona corretamente usando um aplicativo cliente gRPC sem proxy para enviar tráfego ao aplicativo do servidor gRPC.

Como configurar clusters do GKE para o Cloud Service Mesh

Nesta seção, fornecemos instruções para permitir que os clusters do GKE funcionem com o Cloud Service Mesh.

Requisitos de cluster do GKE

Os clusters do GKE precisam atender aos seguintes requisitos:

  • Você precisa ativar o suporte para os grupos de endpoints da rede. Para mais informações e exemplos, consulte Grupos de endpoints de rede autônomos. O recurso autônomo de NEGs está em disponibilidade geral no Cloud Service Mesh.
  • A conta de serviço das instâncias de nós do cluster precisa ter permissão para acessar a API Cloud Service Mesh. Para mais informações sobre as permissões necessárias, consulte Como ativar a conta de serviço para acessar a API Cloud Service Mesh.
  • Os contêineres precisam ter acesso à API Cloud Service Mesh, que é protegida pela autenticação OAuth. Para mais informações, consulte configuração do host.

Como criar o cluster do GKE

No exemplo a seguir, mostramos como criar um cluster do GKE chamado grpc-td-cluster em us-central1-a zone.

Console

Para criar um cluster usando o Console do Google Cloud, siga estas etapas:

  1. Acesse o menu do Kubernetes Engine no Console do Google Cloud.

    Acessar o menu do Google Kubernetes Engine

  2. Clique em Criar cluster.

  3. Escolha o Cluster padrão ou um modelo apropriado para a carga de trabalho.

  4. Personalize o modelo se necessário. Os campos a seguir são obrigatórios:

    • Nome: insira grpc-td-cluster.
    • Tipo de local: Zonal.
    • Zona: us-central1-a.
    • Pool de nós:
  5. No menu à esquerda, clique em default-pool.

  6. Altere o Nome para grpc-td-cluster.

  7. Em Tamanho, digite o número de nós a serem criados. É preciso ter uma cota de recursos disponível para os nós e os respectivos recursos, como rotas de firewall.

  8. No menu à esquerda, clique em Nós.

  9. Na opção Configuração da máquina em Família de máquina, clique em Otimizado para computação.

  10. Selecione um tipo de máquina. Para ver informações sobre os preços dos tipos de máquina, consulte a página de preços do Compute Engine.

  11. Em Rede, adicione a Tag de rede allow-health-checks.

  12. No menu à esquerda, clique em Segurança do nó.

  13. Em Escopos de acesso, selecione Permitir acesso total a todas as APIs do Cloud:

  14. Clique em Criar.

Depois de criar um cluster no Console do Google Cloud, você precisa configurar kubectl para interagir com o cluster. Para saber mais, consulte Como gerar uma entrada kubeconfig.

gcloud

Crie o cluster.

gcloud container clusters create grpc-td-cluster \
   --zone us-central1-a \
   --scopes=https://www.googleapis.com/auth/cloud-platform \
   --tags=allow-health-checks \
   --enable-ip-alias

Como conseguir os privilégios de cluster necessários do GKE

Mude para o cluster que você acabou de criar emitindo o comando a seguir. Isso aponta kubectl para o cluster correto.

gcloud

gcloud container clusters get-credentials grpc-td-cluster \
    --zone us-central1-a

Como configurar serviços do GKE

Nesta seção, descrevemos como preparar as especificações de implantação do GKE para trabalhar com o Cloud Service Mesh. Isso consiste em configurar um serviço de exemplo helloworld do GKE com anotações de NEG.

O serviço de exemplo helloworld é um aplicativo do servidor gRPC que retorna uma mensagem em resposta a uma solicitação do cliente gRPC. Não há nada especial sobre o serviço helloworld. Ele não é um serviço gRPC sem proxy e pode responder a solicitações de qualquer cliente gRPC.

A parte "sem proxy" só entra em jogo quando um aplicativo cliente gRPC se conecta ao Cloud Service Mesh, aprende sobre o serviço helloworld e pode enviar tráfego para pods associados a helloworld, sem precisar depender de endereços IP ou da resolução de nomes baseada em DNS.

Como configurar serviços do GKE com NEGs

A primeira etapa na configuração dos serviços do GKE para uso com o Cloud Service Mesh é expor o serviço usando um NEG. Para ser exposta por meio de NEGs, cada especificação precisa ter a seguinte anotação, correspondente à porta que você quer expor.

...
metadata:
  annotations:
    cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'

Essa anotação cria um NEG autônomo quando você implanta seu serviço pela primeira vez. Este NEG contém endpoints que são os endereços IP e as portas do pod. Para mais informações e exemplos, consulte Grupos de endpoints de rede autônomos.

No exemplo a seguir, você implanta um serviço helloworld do Kubernetes exposto na porta 8080. Essa é a porta em que o serviço pode ser visto no cluster. O serviço gRPC no pod está detectando em targetPort 50051. Essa é a porta no pod para onde a solicitação é enviada. Normalmente, port e targetPort são definidos com o mesmo valor por conveniência, mas este exemplo usa valores diferentes para indicar o valor correto a ser usado na anotação do NEG.

cat << EOF > grpc-td-helloworld.yaml
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  annotations:
    cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
spec:
  ports:
  - port: 8080
    name: helloworld
    protocol: TCP
    targetPort: 50051
  selector:
    run: app1
  type: ClusterIP

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: app1
  name: app1
spec:
  selector:
    matchLabels:
      run: app1
  replicas: 2
  template:
    metadata:
      labels:
        run: app1
    spec:
      containers:
      - image: grpc/java-example-hostname:1.50.2
        name: app1
        ports:
        - protocol: TCP
          containerPort: 50051
EOF
kubectl apply -f grpc-td-helloworld.yaml

Verifique se o novo serviço helloworld foi criado:

kubectl get svc

A saída de kubectl get svc será semelhante a esta:

NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
helloworld     ClusterIP   10.71.9.71   <none>        8080/TCP  41m
[..skip..]

Verifique se o pod do aplicativo está em execução:

kubectl get pods

A saída de kubectl get pods será semelhante a esta:

NAME                        READY     STATUS    RESTARTS   AGE
app1-6db459dcb9-zvfg2   1/1       Running   0          6m
app1-6db459dcb9-hlvhj   1/1       Running   0          6m
[..skip..]

Verifique se o nome do NEG está correto.

Console

Veja uma lista de grupos de endpoints de rede na página "Grupos de endpoints de rede" no Console do Google Cloud. Você verá um NEG chamado example-grpc-server.
Acessar a página "Grupos de endpoints de rede"

gcloud

# List the NEGs
gcloud compute network-endpoint-groups list \
    --filter "name=example-grpc-server" --format "value(name)"

# Optionally examine the NEG
gcloud compute network-endpoint-groups describe example-grpc-server \
    --zone us-central1-a

# Optionally examine the endpoint(s) contained
gcloud compute network-endpoint-groups list-network-endpoints example-grpc-server \
    --zone us-central1-a

Como configurar o Cloud Service Mesh com componentes de balanceamento de carga

Nesta seção, descrevemos como configurar os componentes de balanceamento de carga do Google Cloud para seus serviços. Esses componentes contêm informações de configuração que permitem que os clientes do gRPC sem proxy se comuniquem com seus serviços do GKE.

O exemplo de configuração do Cloud Service Mesh a seguir faz essas suposições:

  • Os NEGs e todos os outros recursos são criados na rede padrão de modo automático, na zona us-central1-a.
  • Quando você usa a Google Cloud CLI, o nome do NEG no cluster é example-grpc-server.

Como criar a verificação de integridade, a regra de firewall e o serviço de back-end

Nesta seção, você cria uma verificação de integridade e a regra de firewall para a verificação de integridade. A verificação de integridade precisa usar o protocolo de verificação de integridade gRPC. A regra de firewall permite que as sondagens de verificação de integridade se conectem às VMs na implantação. A diretiva --use-serving-port é usada por verificações de integridade para conseguir a porta de detecção configurada para cada endpoint.

A regra de firewall permite a entrada de conexões de verificação de integridade para instâncias na sua rede.

Nesta seção, você cria um serviço de back-end global com o esquema de balanceamento de carga INTERNAL_SELF_MANAGED e protocolo GRPC e associa a verificação de integridade ao serviço de back-end.

Para mais informações, consulte Como criar verificações de integridade.

gcloud

  1. Crie a verificação de integridade.

    gcloud compute health-checks create grpc grpc-gke-helloworld-hc \
     --use-serving-port
    
  2. Crie a regra de firewall.

    gcloud compute firewall-rules create grpc-gke-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --target-tags allow-health-checks \
      --rules tcp:50051
    
  3. Crie o serviço de back-end:

    gcloud compute backend-services create grpc-gke-helloworld-service \
       --global \
       --load-balancing-scheme=INTERNAL_SELF_MANAGED \
       --protocol=GRPC \
       --health-checks grpc-gke-helloworld-hc
    
  4. Adicione os NEGs de back-end ao serviço de back-end.

    gcloud compute backend-services add-backend grpc-gke-helloworld-service \
       --global \
       --network-endpoint-group example-grpc-server \
       --network-endpoint-group-zone us-central1-a \
       --balancing-mode RATE \
       --max-rate-per-endpoint 5
    

Como criar o mapa de regras de roteamento

Nesta seção, você cria um mapa de URL, a correspondência de caminho e uma regra de host para rotear o tráfego para seu serviço, com base no nome do host e em um caminho. O exemplo a seguir usa helloworld-gke como o nome do serviço. O cliente gRPC usa esse nome de serviço no URI de destino ao se conectar ao serviço helloworld. Também é possível criar o proxy de destino e a regra de encaminhamento do gRPC.

Para saber mais, consulte Como mapear mapas de regras.

O exemplo a seguir usa o nome de serviço helloworld-gke e a porta 8000. Isso significa que o cliente gRPC precisa usar xds:///helloworld-gke:8000 para se conectar a esse serviço, e uma regra de host helloworld-gke:8000 precisa ser configurada no mapa de URL. Observe que a porta de serviço 8080 mostrada na especificação de serviço do Kubernetes em uma seção anterior não é usada pelo Cloud Service Mesh porque helloworld-gke:8000 é resolvido diretamente para os endpoints do NEG que detectam no targetPort 50051. Normalmente, a porta na regra de host do mapa de URL e a especificação de serviço port e targetPort do Kubernetes estão definidas com o mesmo valor por conveniência, mas este exemplo usa valores diferentes para mostrar que o port na especificação de serviço não é usado pelo Cloud Service Mesh.

gcloud

  1. Crie o mapa de URL.

    gcloud compute url-maps create grpc-gke-url-map \
    --default-service grpc-gke-helloworld-service
    
  2. Crie a correspondência de caminho.

    gcloud compute url-maps add-path-matcher grpc-gke-url-map \
    --default-service grpc-gke-helloworld-service \
    --path-matcher-name grpc-gke-path-matcher \
    --new-hosts helloworld-gke:8000
    
  3. Crie o proxy de destino do gRPC.

    gcloud compute target-grpc-proxies create grpc-gke-proxy \
    --url-map grpc-gke-url-map \
    --validate-for-proxyless
    
  4. Crie a regra de encaminhamento.

    gcloud compute forwarding-rules create grpc-gke-forwarding-rule \
    --global \
    --load-balancing-scheme=INTERNAL_SELF_MANAGED \
    --address=0.0.0.0 \
    --target-grpc-proxy=grpc-gke-proxy \
    --ports 8000 \
    --network default
    

O Cloud Service Mesh agora está configurado para balancear a carga do tráfego nos endpoints no NEG para os serviços especificados no mapa de URL.

Como verificar a configuração

Quando o processo de configuração estiver concluído, verifique se é possível acessar o servidor gRPC helloworld usando um cliente gRPC sem proxy. Esse cliente se conecta ao Cloud Service Mesh, recebe informações sobre o serviço helloworld (configurado com o Cloud Service Mesh usando o serviço de back-end grpc-gke-helloworld-service) e usa essas informações para enviar tráfego para os back-ends do serviço.

Também é possível verificar a seção do Cloud Service Mesh no console do Google Cloud para informações sobre o serviço configurado helloworld-gke e verificar se os back-ends são informados como íntegros.

Verificação com um cliente gRPC sem proxy

Nos exemplos a seguir, use clientes gRPC em linguagens diferentes ou a ferramenta grpcurl para verificar se o Cloud Service Mesh está roteando o tráfego corretamente na malha. Crie um pod cliente, abra um shell e execute os comandos de verificação no shell.

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

O aplicativo cliente requer um arquivo de configuração de inicialização. Modifique a especificação de implantação do aplicativo Kubernetes adicionando um initContainer que gere o arquivo de inicialização e um volume para transferir o arquivo. Atualize o contêiner existente para encontrar o arquivo.

Adicione o seguinte initContainer à especificação de implantação do aplicativo:

      initContainers:
      - args:
        - --output
        - "/tmp/bootstrap/td-grpc-bootstrap.json"
        image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.11.0

        imagePullPolicy: IfNotPresent
        name: grpc-td-init
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
          requests:
            cpu: 10m
            memory: 100Mi
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/bootstrap/
      volumes:
      - name: grpc-td-conf
        emptyDir:
          medium: Memory

Atualize a seção env do contêiner do aplicativo para incluir o seguinte:

        env:
        - name: GRPC_XDS_BOOTSTRAP
          value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/grpc-xds/

Este é um exemplo completo de uma especificação Kubernetes do cliente:

cat << EOF  | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: client
  name: sleeper
spec:
  selector:
    matchLabels:
      run: client
  template:
    metadata:
      labels:
        run: client
    spec:
      containers:
      - image: openjdk:8-jdk
        imagePullPolicy: IfNotPresent
        name: sleeper
        command:
        - sleep
        - 365d
        env:
        - name: GRPC_XDS_BOOTSTRAP
          value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
        resources:
          limits:
            cpu: "2"
            memory: 2000Mi
          requests:
            cpu: 300m
            memory: 1500Mi
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/grpc-xds/
      initContainers:
      - args:
        - --output
        - "/tmp/bootstrap/td-grpc-bootstrap.json"
        image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.11.0
        imagePullPolicy: IfNotPresent
        name: grpc-td-init
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
          requests:
            cpu: 10m
            memory: 100Mi
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/bootstrap/
      volumes:
      - name: grpc-td-conf
        emptyDir:
          medium: Memory
EOF

Quando a implantação estiver pronta, abra um shell para o pod cliente.

kubectl exec -it $(kubectl get pods -o custom-columns=:.metadata.name \
    --selector=run=client) -- /bin/bash

Para verificar a configuração, execute os exemplos apropriados no shell do pod.

Java

Para verificar o serviço com um cliente Java gRPC:

  1. Faça o download da versão mais recente do gRPC Java com o patch mais recente e crie o aplicativo cliente xds-hello-world.

     curl -L https://github.com/grpc/grpc-java/archive/v1.37.0.tar.gz | tar -xz
     cd grpc-java-1.37.0/examples/example-xds
     ../gradlew --no-daemon installDist
     

  2. Execute o cliente com "world" como nome e "xds:///helloworld-gke:8000" como o URI e a porta do serviço.

    ./build/install/example-xds/bin/xds-hello-world-client "world" \
    xds:///helloworld-gke:8000
    

Go

Para verificar o serviço com um cliente gRPC Go:

  1. Faça o download da versão mais recente do gRPC Go com o patch mais recente e crie o aplicativo cliente xds-hello-world.

    apt-get update -y
    apt-get install -y golang git
    curl -L https://github.com/grpc/grpc-go/archive/v1.37.0.tar.gz | tar -xz
    cd grpc-go-1.37.0/examples/features/xds/client
    go get google.golang.org/grpc@v1.37.0
    go build .
    
  2. Execute o cliente com "world" como nome e "xds:///helloworld-gke:8000" como o URI e a porta do serviço.

    ./client "world" xds:///helloworld-gke:8000
    

C++

Para verificar o serviço com um cliente gRPC em C++:

  1. Faça o download da versão mais recente do gRPC C++, com o patch mais recente e crie o exemplo de cliente helloworld.

    apt-get update -y
    apt-get install -y build-essential cmake git
    git clone --recurse-submodules -b v1.37.1 https://github.com/grpc/grpc
    cd grpc
    mkdir -p cmake/build
    pushd cmake/build
    cmake ../..
    make
    make install
    popd
    mkdir -p third_party/abseil-cpp/cmake/build
    pushd third_party/abseil-cpp/cmake/build
    cmake ../..
    make
    make install
    popd
    cd examples/cpp/helloworld
    mkdir -p cmake/build
    cd cmake/build/
    cmake ../..
    make
    
  2. Execute o cliente com "xds:///helloworld-gke:8000" como URI e porta de serviço.

    ./greeter_client --target=xds:///helloworld-gke:8000
    

grpcurl

A ferramenta grpcurl também pode atuar como um cliente gRPC sem proxy. Nesse caso, grpcurl usa a variável de ambiente e as informações de inicialização para se conectar ao Cloud Service Mesh. Em seguida, ele aprende sobre o serviço helloworld, que foi configurado com o Cloud Service Mesh por meio do serviço de back-end grpc-gke-helloworld-service.

Para verificar a configuração usando a ferramenta grpcurl:

  1. Faça o download e instale a ferramenta grpcurl.

    curl -L https://github.com/fullstorydev/grpcurl/releases/download/v1.8.1/grpcurl_1.8.1_linux_x86_64.tar.gz | tar -xz
    
  2. Execute a ferramenta grpcurl com "xds:///helloworld-gke:8000" como URI do serviço e helloworld.Greeter/SayHello como o nome do serviço e o método a serem invocados. Os parâmetros para o método SayHello são transmitidos usando a opção -d.

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

Python

Para verificar o serviço com um cliente gRPC Python, execute o seguinte: Use a versão mais recente do gRPC com o patch mais recente.

apt-get update -y
apt-get install python3-pip -y
pip3 install virtualenv
curl -L https://github.com/grpc/grpc/archive/v1.37.1.tar.gz | tar -xz
cd grpc-1.37.1/examples/python/xds
virtualenv venv -p python3
source venv/bin/activate
pip install -r requirements.txt
python client.py  xds:///helloworld-gke:8000

Ruby

Para verificar o serviço com um cliente gRPC Ruby, execute o seguinte: Use a versão mais recente do gRPC com o patch mais recente.

apt-get update -y
apt-get install -y ruby-full
gem install grpc
curl -L https://github.com/grpc/grpc/archive/v1.37.1.tar.gz | tar -xz
cd grpc-1.37.1/examples/ruby
ruby greeter_client.rb john xds:///helloworld-gke:8000

PHP

Para verificar o serviço com um cliente gRPC PHP, execute o seguinte: Use a versão mais recente do gRPC com o patch mais recente.

apt-get update -y
apt-get install -y php7.3 php7.3-dev php-pear phpunit python-all zlib1g-dev git
pecl install grpc
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
curl -L https://github.com/grpc/grpc/archive/v1.37.1.tar.gz | tar -xz
cd grpc-1.37.1
export CC=/usr/bin/gcc
./tools/bazel build @com_google_protobuf//:protoc
./tools/bazel build src/compiler:grpc_php_plugin
cd examples/php
composer install
../../bazel-bin/external/com_google_protobuf/protoc --proto_path=../protos \
--php_out=. --grpc_out=. \
--plugin=protoc-gen-grpc=../../bazel-bin/src/compiler/grpc_php_plugin \
../protos/helloworld.proto
php -d extension=grpc.so greeter_client.php john xds:///helloworld-gke:8000

Node.js

Para verificar o serviço com um cliente gRPC Node.js, execute o seguinte: Use a versão mais recente do gRPC com o patch mais recente.

apt-get update -y
apt-get install -y nodejs npm
curl -L https://github.com/grpc/grpc/archive/v1.34.0.tar.gz | tar -xz
cd grpc-1.34.0/examples/node/xds
npm install
node ./greeter_client.js --target=xds:///helloworld-gke:8000

Você verá um resultado semelhante a este, em que INSTANCE_HOST_NAME é o nome do host da instância de VM:

Greetings: Hello world, from INSTANCE_HOST_NAME

Isso verifica se o cliente gRPC sem proxy se conectou ao Cloud Service Mesh e aprendeu sobre os back-ends do serviço helloworld-gke 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.

A seguir