Configuración de Traffic Director con Google Kubernetes Engine y servicios de gRPC sin proxy

En esta guía, se describe cómo configurar Google Kubernetes Engine, las aplicaciones de gRPC y los componentes del balanceo de cargas que requiere Traffic Director.

Antes de seguir las instrucciones de esta guía, revisa Prepárate para configurar Traffic Director con servicios de gRPC sin proxy.

Descripción general

La configuración de Traffic Director con GKE y los servicios de gRPC sin proxy implica lo siguiente:

  1. Preparar tu clúster de GKE
  2. Implementar una aplicación de servidor de gRPC como un servicio de Kubernetes. Anota la especificación de implementación de GKE a fin de crear de forma automática un grupo de extremos de red (NEG) para el servicio
  3. Configurar Traffic Director mediante el NEG y otros componentes de balanceo de cargas de GCP
  4. Verificar que la implementación funcione de forma correcta mediante una aplicación cliente de gRPC sin proxy para enviar tráfico a la aplicación del servidor de gRPC

Configura clústeres de GKE para Traffic Director

En esta sección, se proporcionan instrucciones para permitir que los clústeres de GKE funcionen con Traffic Director.

Requisitos del clúster de GKE

Los clústeres de GKE deben cumplir con los siguientes requisitos:

  • Debes habilitar la compatibilidad para los grupos de extremos de red. Para obtener más información y ejemplos, consulta Grupos de extremos de red independientes. La función de NEG independientes se encuentra en la etapa de disponibilidad general para Traffic Director.
  • La cuenta de servicio de las instancias de nodos del clúster debe tener permiso para acceder a la API de Traffic Director. Para obtener más información sobre los permisos requeridos, consulta Habilita la cuenta de servicio para acceder a la API de Traffic Director.
  • Los contenedores deben tener acceso a la API de Traffic Director, que está protegida por la autenticación de OAuth. Para obtener más información, consulta la configuración del host.

Crea el clúster de GKE

En el siguiente ejemplo, se muestra cómo crear un clúster de GKE llamado grpc-td-cluster en us-central1-a zone.

Console

Para crear un clúster con Cloud Console, sigue estos pasos:

  1. Ve al menú de Kubernetes Engine en Cloud Console.

    Ir al menú de Google Kubernetes Engine

  2. Haz clic en Crear clúster.

  3. Elige la plantilla Standard cluster o elige una plantilla adecuada para tu carga de trabajo.

  4. Personaliza la plantilla si es necesario. Los siguientes campos son obligatorios:

    • Nombre: Ingresa grpc-td-cluster.
    • Tipo de ubicación: Zonal.
    • Zona: us-central1-a.
    • Grupo de nodos:
      • Tamaño del clúster: El número de nodos para crear en el clúster. Debes tener una cuota de recursos disponible para los nodos y sus recursos (como las rutas de firewall).
      • Tipo de máquina: El tipo de máquina de Compute Engine que se usará para las instancias. Cada tipo de máquina se factura de manera diferente. El tipo de máquina predeterminado es n1-standard-1. Para obtener información sobre los precios por tipo de máquina, consulta la [Página de precios de Compute Engine)(/compute/pricing#machinetype).
      • Haz clic en Más opciones, desplázate hacia abajo hasta Permiso de acceso y haz clic en Permitir el acceso total a todas las API de Cloud. Haz clic en Guardar.
  5. Haz clic en Crear.

Después de crear un clúster en Cloud Console, debes configurar kubectl para interactuar con el clúster. Para obtener más información, consulta Genera una entrada kubeconfig.

gcloud

Crea el clúster.

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

Obtén los privilegios necesarios del clúster de GKE

Cambia al clúster que acabas de crear mediante el siguiente comando. Esto apunta kubectl al clúster correcto.

gcloud

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

Configura servicios de GKE

En esta sección, se describe cómo preparar las especificaciones de implementación de GKE para trabajar con Traffic Director. Esto consiste en configurar un servicio de ejemplo helloworld de GKE con anotaciones de NEG.

El servicio de ejemplo helloworld es una aplicación de servidor de gRPC que muestra un mensaje simple en respuesta a la solicitud de un cliente de gRPC. Ten en cuenta que el servicio helloworld no tiene nada especial. No es un servicio de gRPC sin proxy y puede responder a las solicitudes de cualquier cliente de gRPC.

La parte “sin proxy” solo se incluye cuando una aplicación cliente de gRPC se conecta con Traffic Director, aprende sobre el servicio helloworld y puede enviar tráfico a pods asociados con helloworld, sin necesidad de depender de las direcciones IP o la resolución de nombres basados en DNS.

Configura servicios de GKE con NEG

El primer paso para configurar los servicios de GKE a fin de usarlos con Traffic Director es exponer el servicio a través de un NEG. Para exponerse a través de NEG, cada especificación debe tener la siguiente anotación, que coincide con el puerto que deseas exponer.

...
metadata:
  annotations:
    cloud.google.com/neg: '{"exposed_ports":{"8080":{}}}'

Esta anotación crea un NEG independiente cuando implementas tu servicio por primera vez. Este NEG contiene extremos que son las direcciones IP y los puertos del pod. Para obtener más información y ejemplos, consulta Grupos de extremos de red independientes.

En el siguiente ejemplo, se implementa un servicio de Kubernetes helloworld que se expone en el puerto 8080. Este es el puerto en el que el servicio es visible en el clúster. El servicio de gRPC del pod escucha en el targetPort 50051. Este es el puerto en el pod al que se envía la solicitud. Por lo general, el port y targetPort se configuran con el mismo valor para mayor comodidad, pero en este ejemplo se usan valores diferentes a fin de indicar el valor correcto que se usará en la anotación 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

Verifica que se haya creado el nuevo servicio helloworld:

kubectl get svc

El resultado de kubectl get svc debería ser similar al siguiente:

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

Verifica que el pod de aplicación se esté ejecutando:

kubectl get pods

El resultado de kubectl get pods debería ser similar al siguiente:

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

Registra el nombre del NEG

Busca el NEG que se creó en el ejemplo anterior y registra su nombre para usarlo más adelante en el proceso de configuración.

Console

Para ver una lista de grupos de extremos de red, ve a la página Grupos de extremos de red en Google Cloud Console. Verás un NEG con helloworld en su nombre.
Ir a la página Grupos de extremos de red

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

Configura Traffic Director con componentes de balanceo de cargas de GCP

En esta sección, se describe cómo configurar los componentes de balanceo de cargas de Traffic Director para tus servicios. Estos componentes contienen información de configuración que permite que los clientes de gRPC sin proxy se comuniquen con tus servicios de GKE.

En el ejemplo de configuración de Traffic Director que aparece a continuación, se supone lo siguiente:

  • Los NEG y todos los demás recursos se crean en la red predeterminada de modo automático, en la zona us-central1-a.
  • Cuando usas la herramienta de línea de comandos de gcloud, el nombre de NEG para el clúster se almacena en la variable ${NEG_NAME}.

Crea la verificación de estado, la regla de firewall y el servicio de backend

En esta sección, crearás una verificación de estado y la regla de firewall para la verificación de estado. La verificación de estado debe usar el protocolo de verificación de estado de gRPC. La regla de firewall permite que los sondeos de verificación de estado se conecten con las VM en tu implementación. Las verificaciones de estado usan la directiva --use-serving-port a fin de obtener el puerto de escucha configurado para cada extremo.

La regla de firewall permite conexiones de verificación de estado entrantes a instancias en tu red.

En esta sección, crearás un servicio de backend global con un esquema de balanceo de cargas de INTERNAL_SELF_MANAGED y el protocolo GRPC. Luego, asociarás la verificación de estado con el servicio de backend.

Para obtener más información, consulta Crea verificaciones de estado.

gcloud

  1. Crea la verificación de estado.

    gcloud compute health-checks create grpc grpc-gke-helloworld-hc \
     --use-serving-port
    
  2. Crea la regla 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. Crea el servicio de backend.

    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. Agrega los NEG de backend al servicio de backend.

    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
    

Crea el mapa de reglas de enrutamiento

En esta sección, crearás un mapa de URL, un comparador de rutas de acceso y una regla de host para enrutar el tráfico de tu servicio según el nombre de host y una ruta de acceso. En el siguiente ejemplo, se usa helloworld-gke como el nombre de servicio. El cliente de gRPC usa este nombre de servicio en el URI de destino cuando se conecta al servicio helloworld. También debes crear el proxy de gRPC de destino y la regla de reenvío.

Para obtener más información, consulta Mapas de reglas de enrutamiento.

En el siguiente ejemplo, se usa el nombre del servicio helloworld-gke y el puerto 8000. Esto significa que el cliente gRPC debe usar xds:///helloworld-gke:8000 para conectarse a este servicio y se debe configurar una regla de host helloworld-gke:8000 en el mapa de URL. Ten en cuenta que Traffic Director no usa el puerto de servicio 8080 que se muestra en las especificaciones del servicio de Kubernetes anterior, ya que helloworld-gke:8000 se resuelve directamente en los extremos de NEG que escuchan en el targetPort 50051. Por lo general, el puerto en la regla de host del mapa de URL y el port y targetPort de la especificación del servicio de Kubernetes están configurados con el mismo valor para mayor comodidad. Sin embargo, en este ejemplo se usan valores diferentes a fin de mostrar que Traffic Director no usa el port de la especificación de servicio.

gcloud

  1. Crea el mapa de URL.

    gcloud compute url-maps create grpc-gke-url-map \
    --default-service grpc-gke-helloworld-service
    
  2. Crea el comparador de rutas de acceso.

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

    gcloud compute target-grpc-proxies create grpc-gke-proxy \
    --url-map grpc-gke-url-map \
    --validate-for-proxyless
    
  4. Crea la regla de reenvío.

    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
    

Traffic Director está configurado a fin de balancear las cargas del tráfico en los extremos en el NEG para los servicios especificados en el mapa de URL.

Verifica la configuración

Cuando se complete el proceso de configuración, verifica que puedas acceder al servidor de gRPC helloworld con un cliente de gRPC sin proxy. Este cliente se conecta con Traffic Director, obtiene información sobre el servicio helloworld (configurado con Traffic Director mediante el servicio de backend grpc-gke-helloworld-service) y usa esta información para enviar tráfico a los backends del servicio.

También puedes consultar la sección Traffic Director en Cloud Console para obtener información sobre el servicio configurado helloworld-gke y verificar si los backends están en buen estado.

Verificación con un cliente de gRPC sin proxy

En los siguientes ejemplos, se usan clientes de gRPC en diferentes lenguajes o la herramienta de grpcurl para verificar que Traffic Director enruta el tráfico de forma correcta en la malla. Crea un pod de cliente, abre un shell y, luego, ejecuta los comandos de verificación desde el shell.

Configura la variable de entorno y el archivo de arranque

La aplicación cliente requiere un archivo de configuración de arranque. Si quieres modificar la especificación de implementación de tu aplicación de Kubernetes, agrega un initContainer que genere el archivo de arranque y un volumen para transferirlo. Actualiza tu contenedor existente para encontrar el archivo.

Agrega el siguiente initContainer a las especificaciones de implementación de la aplicación:

      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

Actualiza la sección env del contenedor de la aplicación de modo que incluya lo siguiente:

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

Este es un ejemplo completo de especificación de Kubernetes de un 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

Cuando la implementación anterior esté lista, abre un shell al pod del cliente.

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

Para verificar la configuración, ejecuta los ejemplos adecuados en el shell del pod.

Java

Si deseas verificar el servicio con un cliente de gRPC para Java, haz lo siguiente:

  1. Descarga la versión 1.30.0 de gRPC para Java con el parche más reciente y compila la aplicación 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. Ejecuta el cliente con "world" como su nombre y "xds:///helloworld-gke:8000" como el puerto y URI de servicio.

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

Go

Si deseas verificar el servicio con un cliente de gRPC para Go, haz lo siguiente:

  1. Descarga la versión 1.30.0 de gRPC para Go con el parche más reciente y compila la aplicación 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. Ejecuta el cliente con "world" como su nombre y "xds:///helloworld-gke:8000" como el puerto y URI de servicio.

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

C++

Si deseas verificar el servicio con un cliente de gRPC para C++, haz lo siguiente:

  1. Descarga la versión 1.30.0 de gRPC para C++ (con el parche más reciente) y compila el ejemplo 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. Ejecuta el cliente con “xds:///helloworld-gke:8000” como el puerto y URI de servicio.

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

grpcurl

La herramienta de grpcurl también puede actuar como un cliente de gRPC sin proxy. En este caso, grpcurl usa la variable de entorno y la información de arranque para conectarse a Traffic Director. Luego, aprende sobre el servicio helloworld, que se configuró con Traffic Director a través del servicio de backend grpc-gke-helloworld-service.

Para verificar tu configuración mediante la herramienta de grpcurl, sigue estos pasos:

  1. Descarga y, luego, instala la herramienta de 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. Ejecuta la herramienta de grpcurl con “xds:///helloworld-gke:8000” como URI de servicio y helloworld.Greeter/SayHello como nombre del servicio y método que se invocará. Los parámetros del método SayHello se pasan mediante la opción -d.

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

Python

Si deseas verificar el servicio con un cliente de gRPC para Python, ejecuta lo siguiente:

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#

Si deseas verificar el servicio con un cliente de gRPC para C#, haz lo siguiente:

  1. Instala la versión 2.1 del SDK de dotnet mediante uno de estos métodos:
  2. Ejecuta lo siguiente:

    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

Si deseas verificar el servicio con un cliente de gRPC para Ruby, ejecuta lo siguiente:

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

Si deseas verificar el servicio con un cliente de gRPC para PHP, ejecuta lo siguiente:

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

Deberías ver un resultado similar a este, en el que INSTANCE_HOST_NAME es el nombre de host de la instancia de VM:

Greetings: Hello world, from INSTANCE_HOST_NAME

Esto verifica que el cliente de gRPC sin proxy se conectó de forma correcta a Traffic Director y aprendió sobre los backends para el servicio helloworld-gke mediante el agente de resolución de nombres de xds. El cliente envió una solicitud a uno de los backends del servicio sin necesidad de conocer la dirección IP ni realizar la resolución de DNS.

Próximos pasos