Configurar Google Kubernetes Engine y servicios de gRPC sin proxy

En esta guía se describe cómo configurar Google Kubernetes Engine, las aplicaciones gRPC y los componentes de balanceo de carga que requiere Cloud Service Mesh.

Antes de seguir las instrucciones de esta guía, consulta el artículo Prepararse para configurar Cloud Service Mesh con servicios de gRPC sin proxy.

Información general

Para configurar Cloud Service Mesh con GKE y servicios de gRPC sin proxy, debes hacer lo siguiente:

  1. Preparar el clúster de GKE.
  2. Desplegar una aplicación de servidor gRPC como servicio de Kubernetes. Anota la especificación de implementación de GKE para crear automáticamente un grupo de endpoints de red (NEG) para el servicio.
  3. Configurar Cloud Service Mesh con el NEG y otros componentes de balanceo de carga. Google Cloud
  4. Verificar que el despliegue funciona correctamente mediante una aplicación cliente de gRPC sin proxy para enviar tráfico a la aplicación de servidor de gRPC.

Configurar clústeres de GKE para Cloud Service Mesh

En esta sección se explica cómo habilitar los clústeres de GKE para que funcionen con Cloud Service Mesh.

Requisitos de los clústeres de GKE

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

  • Debes habilitar la compatibilidad con grupos de puntos finales de red. Para obtener más información y ejemplos, consulta Grupos de puntos de conexión de red independientes. La función de NEG independiente está disponible para todos los usuarios de Cloud Service Mesh.
  • La cuenta de servicio de las instancias de los nodos del clúster debe tener permiso para acceder a la API Cloud Service Mesh. Para obtener más información sobre los permisos necesarios, consulta Habilitar la cuenta de servicio para acceder a la API Cloud Service Mesh.
  • Los contenedores deben tener acceso a la API Cloud Service Mesh, que está protegida por la autenticación OAuth. Para obtener más información, consulta la configuración de host.

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

Consola

Para crear un clúster mediante la consola de Google Cloud , sigue estos pasos:

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

    Ir al menú de Google Kubernetes Engine

  2. Haz clic en Crear clúster.

  3. Elige la plantilla Clúster estándar o selecciona una plantilla adecuada para tu carga de trabajo.

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

    • Nombre: escribe 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, introduce el número de nodos que quieras crear. Debes tener cuota de recursos disponible para los nodos y sus recursos (como las rutas de cortafuegos).

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

  9. En Configuración de la máquina, en Familia de máquinas, haga clic en Optimizado para la computación.

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

  11. En Redes, añade la etiqueta de red allow-health-checks.

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

  13. En Permisos de acceso, selecciona Permitir el acceso completo a todas las APIs de Cloud.

  14. Haz clic en Crear.

Una vez que hayas creado un clúster en la Google Cloud consola, debes configurar kubectlpara interactuar con él. Para obtener más información, consulta Generar 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

Obtener los privilegios de clúster de GKE necesarios

Cambia al clúster que acabas de crear con el siguiente comando. De esta forma, kubectl apunta al clúster correcto.

gcloud

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

Configurar servicios de GKE

En esta sección se describe cómo preparar las especificaciones de despliegue de GKE para que funcionen con Cloud Service Mesh. Para ello, se debe configurar un helloworld servicio de ejemplo de GKE con anotaciones NEG.

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

La parte "sin proxy" solo entra en juego cuando una aplicación cliente de gRPC se conecta a Cloud Service Mesh, obtiene información sobre el servicio helloworld y, a continuación, puede enviar tráfico a los pods asociados a helloworld sin tener que depender de direcciones IP ni de la resolución de nombres basada en DNS.

Configurar servicios de GKE con NEGs

El primer paso para configurar los servicios de GKE para usarlos con Cloud Service Mesh es exponer el servicio a través de un NEG. Para que se exponga a través de NEGs, cada especificación debe tener la siguiente anotación, que coincida con el puerto que quieras exponer.

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

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

En el siguiente ejemplo, se despliega un helloworld servicio de Kubernetes que se expone en el puerto 8080. Este es el puerto en el que el servicio está visible en el clúster. El servicio gRPC del pod está escuchando en targetPort 50051. Este es el puerto del pod al que se envía la solicitud. Por lo general, port y targetPort tienen el mismo valor por comodidad, pero en este ejemplo se usan valores diferentes para indicar el valor correcto que se debe 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

Comprueba que se haya creado el nuevo servicio helloworld:

kubectl get svc

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

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

Comprueba que el pod de la aplicación se está ejecutando:

kubectl get pods

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

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 del NEG sea correcto.

Consola

Para ver una lista de grupos de endpoints de red, ve a la página Grupos de endpoints de red de la Google Cloud consola. Verás un NEG llamado example-grpc-server.
Ve a la página Grupos de puntos finales 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

Configurar Cloud Service Mesh con componentes de balanceo de carga

En esta sección se describe cómo configurar los componentes de Google Cloud balanceo de carga de 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 Cloud Service Mesh que se muestra a continuación se dan por supuestos los siguientes aspectos:

  • Los NEGs y todos los demás recursos se crean en la red predeterminada del modo automático, en la zona us-central1-a.
  • Cuando usas Google Cloud CLI, el nombre del NEG del clúster es example-grpc-server.

Crear la comprobación del estado, la regla de cortafuegos y el servicio de backend

En esta sección, creará una comprobación del estado y la regla de cortafuegos correspondiente. La comprobación del estado debe usar el protocolo de comprobación del estado de gRPC. La regla de cortafuegos permite que las sondas de comprobación del estado se conecten a las VMs de tu implementación. Las comprobaciones del estado usan la directiva --use-serving-port para obtener el puerto de escucha configurado de cada endpoint.

La regla de cortafuegos permite que las conexiones de comprobación del estado entrantes se dirijan a las instancias de tu red.

En esta sección, crearás un servicio de backend global con un esquema de balanceo de carga INTERNAL_SELF_MANAGED y un protocolo GRPC. A continuación, asociarás la comprobación del estado al servicio de backend.

Para obtener más información, consulta el artículo Crear comprobaciones del estado.

gcloud

  1. Crea la comprobación del estado.

    gcloud compute health-checks create grpc grpc-gke-helloworld-hc \
     --use-serving-port
    
  2. Crea la regla de cortafuegos.

    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. Añade los NEGs 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
    

Crear el mapa de reglas de enrutamiento

En esta sección, crearás un mapa de URLs, un comparador de rutas y una regla de host para enrutar el tráfico de tu servicio en función del nombre de host y de una ruta. En el siguiente ejemplo, se usa helloworld-gke como nombre del servicio. El cliente gRPC usa este nombre de servicio en el URI de destino al conectarse al servicio helloworld. También creas el proxy 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 usan el nombre de servicio helloworld-gke y el puerto 8000. Esto significa que el cliente de gRPC debe usar xds:///helloworld-gke:8000 para conectarse a este servicio y que se debe configurar una regla de host helloworld-gke:8000 en el mapa de URLs. Ten en cuenta que Cloud Service Mesh no usa el puerto de servicio 8080 que se muestra en la especificación del servicio de Kubernetes de una sección anterior, ya que helloworld-gke:8000 se resuelve directamente en los endpoints del NEG que están escuchando en targetPort 50051. Normalmente, el puerto de la regla de host del mapa de URLs y la especificación del servicio de Kubernetes port y targetPort se definen con el mismo valor por comodidad, pero en este ejemplo se usan valores diferentes para mostrar que Cloud Service Mesh no usa el valor port de la especificación del servicio.

gcloud

  1. Crea el mapa de URLs.

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

    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 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 la carga del tráfico entre los endpoints del NEG de los servicios especificados en el mapa de URLs.

Verificar la configuración

Cuando se haya completado el proceso de configuración, comprueba que puedes acceder al servidor gRPC helloworld mediante un cliente gRPC sin proxy. Este cliente se conecta a 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 de la Google Cloud consola para obtener información sobre el servicio helloworld-gke configurado y comprobar si los back-ends se han notificado como correctos.

Verificación con un cliente gRPC sin proxy

En los siguientes ejemplos, se usan clientes de gRPC en diferentes idiomas o la herramienta grpcurl para verificar que Cloud Service Mesh enruta el tráfico correctamente en la malla. Crea un pod de cliente, abre un shell y ejecuta los comandos de verificación desde el shell.

Configurar la variable de entorno y el archivo de arranque

La aplicación cliente requiere un archivo de configuración de arranque. Modifica la especificación de despliegue de tu aplicación de Kubernetes añadiendo un initContainer que genere el archivo de arranque y un volumen para transferir el archivo. Actualiza el contenedor que ya tienes para encontrar el archivo.

Añade lo siguiente initContainer a la especificación 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 para 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 una especificación de Kubernetes de 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 una shell en el 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 correspondientes en el shell del pod.

Java

Para verificar el servicio con un cliente Java de gRPC, sigue estos pasos:

  1. Descarga la versión más reciente de gRPC Java, con el parche y la compilación más recientes, y 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 nombre y "xds:///helloworld-gke:8000" como URI y puerto del servicio.

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

Go

Para verificar el servicio con un cliente gRPC Go, sigue estos pasos:

  1. Descarga la versión más reciente de gRPC 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.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 nombre y "xds:///helloworld-gke:8000" como URI y puerto del servicio.

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

C++

Para verificar el servicio con un cliente gRPC C++, sigue estos pasos:

  1. Descarga la versión más reciente de gRPC 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 --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 URI y puerto del servicio.

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

grpcurl

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

Para verificar la configuración con la herramienta grpcurl, sigue estos pasos:

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

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

Python

Para verificar el servicio con un cliente de Python de gRPC, 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

Para verificar el servicio con un cliente gRPC 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

Para verificar el servicio con un cliente gRPC 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 de Node.js gRPC, 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 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ía ver un resultado similar a este, donde INSTANCE_HOST_NAME es el nombre de host de la instancia de VM::

Greetings: Hello world, from INSTANCE_HOST_NAME

De esta forma, se verifica que el cliente de gRPC sin proxy se ha conectado correctamente a Cloud Service Mesh y ha obtenido información sobre los backends del servicio helloworld-gke mediante el resolvedor de nombres xds. El cliente ha enviado una solicitud a uno de los back-ends del servicio sin necesidad de conocer la dirección IP ni de realizar la resolución de DNS.

Siguientes pasos