Configuração do Traffic Director com Google Kubernetes Engine e 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 Traffic Director.

Antes de seguir as instruções deste guia, consulte Preparação para configurar o Traffic Director com serviços do gRPC sem proxy.

Visão geral

A configuração do Traffic Director com GKE e 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. Como configurar o Traffic Director usando o NEG e outros componentes de balanceamento de carga do GCP.
  4. Como 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 Traffic Director

Nesta seção, você vê instruções para permitir que os clusters do GKE funcionem com o Traffic Director.

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 independente de NEGs está disponível para o Traffic Director.
  • A conta de serviço das instâncias de nós do cluster precisa ter permissão para acessar a API Traffic Director. Para mais informações sobre as permissões necessárias, consulte Como ativar a conta de serviço para acessar a API Traffic Director.
  • Os contêineres precisam ter acesso à API Traffic Director, 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 Cloud, siga estas etapas:

  1. Acesse o menu do Kubernetes Engine no Console do 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:
      • Tamanho do cluster: o número de nós a serem criados no cluster. É preciso ter uma cota de recursos disponível para os nós e os respectivos recursos, como rotas de firewall.
      • Tipo de máquina: o tipo de máquina do Compute Engine a ser usado nas instâncias. O faturamento varia de acordo com cada tipo de máquina. O tipo de máquina padrão é n1-standard-1. Para informações sobre preços de tipo de máquina, consulte a [página de preços do Compute Engine)(/compute/pricing#machinetype).
      • Clique em Mais opções, role para baixo até Escopos de acesso e clique em Permitir acesso total a todas as APIs do Cloud. Clique em Salvar.
  5. Clique em Criar.

Depois de criar um cluster no Console do 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 Traffic Director. 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 simples em resposta à solicitação de um 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 Traffic Director, aprende sobre o serviço helloworld e pode enviar tráfego para pods associados a helloworld, sem a necessidade de depender de endereços IP ou da resolução de nomes com base 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 Traffic Director é expor o serviço por meio de 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":{}}}'

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":{}}}'
spec:
  ports:
  - port: 8080
    name: helloworld
    protocol: TCP
    targetPort: 50051
  selector:
    run: app1
  type: ClusterIP

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    run: app1
  name: app1
spec:
  replicas: 2
  template:
    metadata:
      labels:
        run: app1
    spec:
      containers:
      - image: grpc/java-example-hostname:1.27.0
        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..]

Como registar o nome do NEG

Encontre o NEG criado no exemplo acima e registre o nome dele para uso posterior no processo de configuração.

Console

Veja uma lista de grupos de endpoints de rede na página "Grupos de endpoints de rede" no Console do Google Cloud. Você vê um NEG com helloworld no nome.
Acessar a página "Grupos de endpoints de rede"

gcloud

# List the NEGs
gcloud compute network-endpoint-groups list

# Save NEG name for future configuration
NEG_NAME=$(gcloud compute network-endpoint-groups list | grep helloworld | awk '{print $1}')

# Verify the variable (optional)
echo ${NEG_NAME}

# Optionally examine the NEG
gcloud compute network-endpoint-groups describe ${NEG_NAME} \
    --zone us-central1-a

# Optionally examine the endpoint(s) contained
gcloud compute network-endpoint-groups list-network-endpoints \
    ${NEG_NAME} --zone us-central1-a

Como configurar o Traffic Director com componentes de balanceamento de carga do GCP

Nesta seção, descrevemos como configurar os componentes de balanceamento de carga do Traffic Director para os 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 Traffic Director a seguir presume que:

  • 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 ferramenta de linha de comando gcloud, o nome do NEG no cluster é armazenado na variável ${NEG_NAME}.

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 ${NEG_NAME} \
       --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. A porta de serviço 8080 mostrada na especificação de serviço do Kubernetes acima não é usada pelo Traffic Director porque helloworld-gke:8000 é resolvido diretamente para os endpoints de NEG que estão detectando no targetPort 50051. Normalmente, a porta na regra de host do mapa de URL e a especificação de serviço do Kubernetes port e targetPort estão definidas com o mesmo valor por conveniência, mas este exemplo usa valores diferentes para mostrar que port na especificação do serviço não é usado pelo Traffic Director.

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

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. Este cliente se conecta ao Traffic Director, recebe informações sobre o serviço helloworld (configurado com o Traffic Director usando o serviço de back-end grpc-gke-helloworld-service) e usa essas informações para enviar tráfego aos back-ends do serviço.

Você também pode verificar a seção do Traffic Director no Console do Cloud para ter 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, você usa clientes gRPC em linguagens diferentes ou a ferramenta grpcurl para verificar se o Traffic Director 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.9.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: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    run: client
  name: sleeper
spec:
  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.9.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 acima estiver pronta, abra um shell para o pod do 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 do gRPC Java versão 1.30.0 com o caminho mais recente e crie o aplicativo cliente xds-hello-world.

     curl -L https://github.com/grpc/grpc-java/archive/v1.30.0.tar.gz | tar -xz
     cd grpc-java-1.30.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 do gRPC Go versão 1.30.0 com o caminho 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.30.0.tar.gz | tar -xz
    cd grpc-go-1.30.0/examples/features/xds/client
    go get google.golang.org/grpc@v1.30.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 1.30.0 do gRPC em C++ (com o caminho mais recente) e crie o exemplo de cliente helloworld.

    apt-get update -y
    apt-get install -y build-essential cmake git
    git clone -b v1.30.0 https://github.com/grpc/grpc
    cd grpc
    git submodule update --init
    mkdir -p cmake/build
    cd cmake/build
    cmake ../..
    make
    make install
    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 Traffic Director. Em seguida, ela aprende sobre o serviço helloworld, que foi configurado com o Traffic Director 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.6.1/grpcurl_1.6.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 em Python, execute o seguinte comando:

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

C#

Para verificar o serviço com um cliente gRPC C#:

  1. Instale o SDK dotnet versão 2.1 usando um destes métodos:
  2. Execute o seguinte comando:

    curl -L https://github.com/grpc/grpc/archive/v1.30.0.tar.gz | tar -xz
    cd grpc-1.30.0/examples/csharp/Xds/GreeterClient
    dotnet run --server xds:///helloworld-gce
    

Ruby

Para verificar o serviço com um cliente Ruby do gRPC, execute o seguinte:

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

PHP

Para verificar o serviço com um cliente PHP gRPC, execute o seguinte:

apt-get update -y
apt-get install -y php7.3 php7.3-dev php-pear phpunit zlib1g-dev
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.30.0.tar.gz | tar -xz
cd grpc-1.30.0
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

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 Traffic Director 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