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

Este guia descreve como configurar o Google Kubernetes Engine, as aplicações gRPC e os componentes de balanceamento de carga que a Cloud Service Mesh requer.

Antes de seguir as instruções neste guia, reveja o artigo Preparar-se para configurar o Cloud Service Mesh com serviços gRPC sem proxy.

Vista geral

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

  1. A preparar o cluster do GKE.
  2. Implementar uma aplicação de servidor gRPC como um serviço do Kubernetes. Anote a especificação de implementação do GKE para criar automaticamente um grupo de pontos finais de rede (NEG) para o serviço.
  3. Configurar a malha de serviços na nuvem através do NEG e de outros componentes de Google Cloud equilíbrio de carga.
  4. Validar se a implementação funciona corretamente através de uma aplicação cliente gRPC sem proxy para enviar tráfego para a aplicação de servidor gRPC.

Configurar clusters do GKE para o Cloud Service Mesh

Esta secção fornece instruções para ativar os clusters do GKE para funcionarem com a Cloud Service Mesh.

Requisitos do cluster do GKE

Os clusters do GKE têm de cumprir os seguintes requisitos:

  • Tem de ativar o suporte para grupos de pontos finais de rede. Para mais informações e exemplos, consulte o artigo Grupos de pontos finais de rede autónomos. A funcionalidade NEGs autónoma está disponível para disponibilidade geral para a Cloud Service Mesh.
  • A conta de serviço das instâncias dos nós do cluster tem de ter autorização para aceder à API Cloud Service Mesh. Para mais informações sobre as autorizações necessárias, consulte o artigo Ativar a conta de serviço para aceder à API Cloud Service Mesh.
  • Os contentores têm de ter acesso à Cloud Service Mesh API, que está protegida pela autenticação OAuth. Para mais informações, consulte a configuração do anfitrião.

Criar o cluster do GKE

O exemplo seguinte mostra como criar um cluster do GKE denominado grpc-td-cluster no us-central1-a zone.

Consola

Para criar um cluster através da Google Cloud consola, siga os passos seguintes:

  1. Aceda ao menu Kubernetes Engine na Google Cloud consola.

    Aceda ao menu do Google Kubernetes Engine

  2. Clique em Criar cluster.

  3. Escolha o modelo de cluster padrão ou escolha um modelo adequado para a sua carga de trabalho.

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

    • Nome: introduza grpc-td-cluster.
    • Tipo de localização: Zonal.
    • Zona: us-central1-a.
    • Pool de nós:
  5. No menu do lado esquerdo, clique em default-pool.

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

  7. Em Tamanho, introduza o número de nós a criar. Tem de ter quota de recursos disponível para os nós e os respetivos recursos (como trajetos de firewall).

  8. No menu do lado esquerdo, clique em Nodes.

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

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

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

  12. No menu do lado esquerdo, clique em Segurança do nó.

  13. Em Âmbitos de acesso, selecione Permitir acesso total a todas as APIs Cloud.

  14. Clique em Criar.

Depois de criar um cluster na Google Cloud consola, tem de o configurar kubectl para interagir com o cluster. Para saber mais, consulte o artigo 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

Obter os privilégios do cluster do GKE necessários

Mude para o cluster que acabou de criar executando o seguinte comando. Isto aponta kubectl para o cluster correto.

gcloud

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

Configurar serviços do GKE

Esta secção descreve como preparar as especificações de implementação do GKE para funcionar com a Cloud Service Mesh. Isto consiste em configurar um serviço de exemplo do GKE com anotações NEG.helloworld

O serviço de exemplo helloworld é uma aplicação de servidor gRPC que devolve uma mensagem em resposta ao pedido de um cliente gRPC. Tenha em atenção que não existe nada de especial no serviço helloworld. Não é um serviço gRPC sem proxy e pode responder a pedidos de qualquer cliente gRPC.

A parte "sem proxy" só entra em ação quando uma aplicação cliente gRPC se liga ao Cloud Service Mesh, fica a conhecer o serviço helloworld e pode, em seguida, enviar tráfego para os pods associados a helloworld, sem ter de depender de endereços IP ou da resolução de nomes baseada em DNS.

Configurar serviços do GKE com NEGs

O primeiro passo na configuração dos serviços do GKE para utilização com o Cloud Service Mesh é expor o serviço através de um NEG. Para serem expostas através de NEGs, cada especificação tem de ter a seguinte anotação, correspondendo à porta que quer expor.

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

Esta anotação cria um NEG autónomo quando implementa o seu serviço pela primeira vez. Este NEG contém pontos finais que são os endereços IP e as portas do pod. Para mais informações e exemplos, consulte o artigo Grupos de pontos finais de rede autónomos.

No exemplo seguinte, implementa um helloworld serviço Kubernetes que é exposto na porta 8080. Esta é a porta na qual o serviço está visível no cluster. O serviço gRPC no pod está a ouvir em targetPort 50051. Esta é a porta no pod para a qual o pedido é enviado. Normalmente, os elementos 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 usar na anotação 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

O resultado de kubectl get svc deve ser semelhante ao seguinte:

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

Verifique se o pod da aplicação está em execução:

kubectl get pods

O resultado de kubectl get pods deve ser semelhante ao seguinte:

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.

Consola

Para ver uma lista de grupos de pontos finais de rede, aceda à página Grupos de pontos finais de rede na Google Cloud consola. Vê um NEG com o nome example-grpc-server.
Aceda à página Grupos de pontos finais da 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

Configurar o Cloud Service Mesh com componentes de equilíbrio de carga

Esta secção descreve como configurar os componentes de Google Cloud equilíbrio de carga para os seus serviços. Estes componentes contêm informações de configuração que permitem que os clientes gRPC sem proxy comuniquem com os seus serviços GKE.

O exemplo de configuração da malha de serviços na nuvem que se segue baseia-se nas seguintes suposições:

  • Os NEGs e todos os outros recursos são criados na rede predefinida do modo automático, na zona us-central1-a.
  • Quando usa a CLI gcloud, o nome do NEG para o cluster é example-grpc-server.

Criar a verificação de funcionamento, a regra de firewall e o serviço de back-end

Nesta secção, cria uma verificação de funcionamento e a regra de firewall para a verificação de funcionamento. A verificação de estado tem de usar o protocolo de verificação de estado gRPC. A regra de firewall permite que as sondas de verificação de estado se liguem às VMs na sua implementação. A diretiva --use-serving-port é usada pelas verificações de funcionamento para obter a porta de escuta configurada para cada ponto final.

A regra de firewall permite ligações de verificações de estado de funcionamento de entrada a instâncias na sua rede.

Nesta secção, cria um serviço de back-end global com um esquema de equilíbrio de carga de INTERNAL_SELF_MANAGED e um protocolo GRPC. Em seguida, associa a verificação de funcionamento ao serviço de back-end.

Para mais informações, consulte o artigo Criar verificações de funcionamento.

gcloud

  1. Crie a verificação de funcionamento.

    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
    

Criar o mapa de regras de encaminhamento

Nesta secção, cria um mapa de URL, um correspondente de caminhos e uma regra de anfitrião para encaminhar o tráfego para o seu serviço com base no nome do anfitrião e num caminho. O exemplo seguinte usa helloworld-gke como nome do serviço. O cliente gRPC usa este nome do serviço no URI de destino quando se liga ao serviço helloworld. Também cria o proxy gRPC de destino e a regra de encaminhamento.

Para mais informações, consulte o artigo Mapas de regras de encaminhamento.

O exemplo seguinte usa o nome do serviço helloworld-gke e a porta 8000. Isto significa que o cliente gRPC tem de usar xds:///helloworld-gke:8000 para se ligar a este serviço e tem de configurar uma regra de anfitrião helloworld-gke:8000 no mapa de URLs. Tenha em atenção que a porta de serviço 8080 apresentada na especificação do serviço Kubernetes numa secção anterior não é usada pela Cloud Service Mesh porque helloworld-gke:8000 é resolvida diretamente para os pontos finais do NEG que estão a escutar na porta targetPort 50051. Normalmente, a porta na regra do anfitrião do mapa de URLs e na especificação do serviço Kubernetes port e targetPort estão todas definidas com o mesmo valor por conveniência, mas este exemplo usa valores diferentes para mostrar que o port na especificação do serviço não é usado pela malha de serviços na nuvem.

gcloud

  1. Crie o mapa de URLs.

    gcloud compute url-maps create grpc-gke-url-map \
    --default-service grpc-gke-helloworld-service
    
  2. Crie o correspondente de caminhos.

    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 gRPC de destino.

    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 está agora configurado para equilibrar a carga do tráfego nos pontos finais no NEG para os serviços especificados no mapa de URLs.

Validar a configuração

Quando o processo de configuração estiver concluído, verifique se consegue aceder ao servidor gRPC helloworld através de um cliente gRPC sem proxy. Este cliente liga-se à malha de serviços na nuvem, obtém informações sobre o serviço helloworld (configurado com a malha de serviços na nuvem através do serviço de back-end grpc-gke-helloworld-service) e usa estas informações para enviar tráfego para os back-ends do serviço.

Também pode consultar a secção Cloud Service Mesh na Google Cloud consola para obter informações sobre o serviço configurado helloworld-gke e verificar se os back-ends são comunicados como estando em bom estado.

Validação com um cliente gRPC sem proxy

Nos exemplos seguintes, usa clientes gRPC em diferentes idiomas ou a ferramenta grpcurl para verificar se a Cloud Service Mesh está a encaminhar o tráfego corretamente na malha. Cria um pod de cliente e, em seguida, abre uma shell e executa os comandos de validação a partir da shell.

Configurar a variável de ambiente e o ficheiro de arranque

A aplicação cliente requer um ficheiro de configuração de arranque. Modifique a especificação de implementação da aplicação Kubernetes adicionando um initContainer que gera o ficheiro de arranque e um volume para transferir o ficheiro. Atualize o contentor existente para encontrar o ficheiro.

Adicione o seguinte initContainer à especificação de implementação da aplicação:

      initContainers:
      - args:
        - --output
        - "/tmp/bootstrap/td-grpc-bootstrap.json"
        image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.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 secção env do contentor da aplicação 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/

Segue-se um exemplo completo de uma especificação do 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.16.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 implementação estiver pronta, abra uma shell para o pod do cliente.

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

Para validar a configuração, execute os exemplos adequados na shell do pod.

Java

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

  1. Transfira a versão mais recente do gRPC Java, com o patch e a compilação mais recentes, e crie a aplicação 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 URI e porta do serviço.

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

Ir

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

  1. Transfira a versão mais recente do gRPC Go, com o patch mais recente, e crie a aplicação 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 URI e porta do serviço.

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

C++

Para validar o serviço com um cliente gRPC C++:

  1. Transfira a 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 o URI e a porta do serviço.

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

grpcurl

A ferramenta grpcurl também pode funcionar como um cliente gRPC sem proxy. Neste caso, o grpcurl usa a variável de ambiente e as informações de arranque para se ligar ao Cloud Service Mesh. Em seguida, aprende sobre o serviço helloworld, que foi configurado com a malha de serviços na nuvem através do serviço de back-end grpc-gke-helloworld-service.

Para validar a configuração através da grpcurl ferramenta:

  1. Transfira 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 o URI do serviço e helloworld.Greeter/SayHello como o nome do serviço e o método a invocar. Os parâmetros para o método SayHello são transmitidos através da opção -d.

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

Python

Para validar o serviço com um cliente Python gRPC, 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 validar 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 validar o serviço com um cliente PHP gRPC, 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 validar 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

Deverá ver uma saída semelhante a esta, em que INSTANCE_HOST_NAME é o nome de anfitrião da instância de VM:

Greetings: Hello world, from INSTANCE_HOST_NAME

Isto verifica se o cliente gRPC sem proxy se ligou com êxito ao Cloud Service Mesh e aprendeu sobre os back-ends do serviço helloworld-gke através do resolvedor de nomes xds. O cliente enviou um pedido a um dos backends do serviço sem precisar de saber o endereço IP nem realizar a resolução de DNS.

O que se segue?