Configura Google Kubernetes Engine y los 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 Cloud Service Mesh.

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

Descripción general

La configuración de Cloud Service Mesh con GKE y 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 Cloud Service Mesh mediante el NEG y otros componentes de balanceo de cargas de Google Cloud
  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 Cloud Service Mesh

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

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 Cloud Service Mesh.
  • La cuenta de servicio de las instancias de nodos del clúster debe tener permiso para acceder a la API de Cloud Service Mesh. Para obtener más información sobre los permisos requeridos, consulta Habilita la cuenta de servicio para acceder a la API de Cloud Service Mesh.
  • Los contenedores deben tener acceso a la API de Cloud Service Mesh, 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 la consola de Google Cloud, sigue estos pasos:

  1. Ve al menú de Kubernetes Engine en la consola de Google Cloud.

    Ir al menú de Google Kubernetes Engine

  2. Haga 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:
  5. En el menú de la izquierda, haz clic en default-pool.

  6. Cambia el Nombre a grpc-td-cluster.

  7. En Tamaño, ingresa la cantidad de nodos que se crearán. Debes tener una cuota de recursos disponible para los nodos y sus recursos (como las rutas de firewall).

  8. En el menú de la izquierda, haz clic en Nodos.

  9. Ve a Configuración de la máquina, en Familia de máquinas, y haz clic en Optimizada para procesamiento.

  10. Selecciona un tipo de máquina. Para obtener información sobre los precios de los tipos de máquina, consulta la página de precios de Compute Engine.

  11. En Herramientas de redes, agrega la etiqueta de red allow-health-checks.

  12. En el menú de la izquierda, haz clic en Seguridad de nodos.

  13. En Permiso de acceso, selecciona Permitir el acceso total a todas las API de Cloud.

  14. Haga clic en Crear.

Después de crear un clúster en la consola de Google Cloud, 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 Cloud Service Mesh. 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 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 Cloud Service Mesh, 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 Cloud Service Mesh 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":{"name": "example-grpc-server"}}}'

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":{"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

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..]

Verifica que el nombre de NEG sea correcto.

Console

Para ver una lista de grupos de extremos de red, ve a la página Grupos de extremos de red en la consola de Google Cloud. Verás un NEG llamado example-grpc-server.
Ir a la página Grupos de extremos de red

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

Configura Cloud Service Mesh con componentes de balanceo de cargas

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

En el siguiente ejemplo de configuración de Cloud Service Mesh, 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 Google Cloud CLI, el nombre del NEG para el clúster es example-grpc-server.

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 example-grpc-server \
       --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 Cloud Service Mesh no usa el puerto de servicio 8080 que se muestra en las especificaciones del servicio de Kubernetes en una sección 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 para mostrar que Cloud Service Mesh 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
    

Cloud Service Mesh ahora está configurado para 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 Cloud Service Mesh, obtiene información sobre el servicio helloworld (configurado con Cloud Service Mesh 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 Cloud Service Mesh en la consola de Google Cloud 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 Cloud Service Mesh 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.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

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: 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

Cuando la implementación 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 última versión 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.37.0.tar.gz | tar -xz
     cd grpc-java-1.37.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 última versión de gRPC para Go con el parche más reciente y crea 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.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. 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 última versión de gRPC para C++,con el parche más reciente, y crea el ejemplo 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. 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 Cloud Service Mesh. Luego, aprende sobre el servicio helloworld, que se configuró con Cloud Service Mesh 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.8.1/grpcurl_1.8.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. Usa la versión más reciente de gRPC con el parche más reciente.

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

Si deseas verificar el servicio con un cliente de gRPC para Ruby, ejecuta lo siguiente. Usa la versión más reciente de gRPC con el parche más reciente.

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

Si deseas verificar el servicio con un cliente de gRPC para PHP, ejecuta lo siguiente. Usa la versión más reciente de gRPC con el parche más reciente.

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 el servicio con un cliente Node.js de gRPC, ejecuta el siguiente comando. Usa la versión más reciente de gRPC con el parche más reciente.

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

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 Cloud Service Mesh y aprendió sobre los backends del 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.

¿Qué sigue?