Configurer Google Kubernetes Engine et des services gRPC sans proxy

Ce guide explique comment configurer Google Kubernetes Engine, des applications gRPC et des composants d'équilibrage de charge requis par Cloud Service Mesh.

Avant de suivre les instructions de ce guide, consultez la page Préparer la configuration de Cloud Service Mesh avec des services gRPC sans proxy.

Présentation

La configuration de Cloud Service Mesh avec GKE et des services gRPC sans proxy implique les opérations suivantes:

  1. Préparer le cluster GKE
  2. Déployer une application de serveur gRPC en tant que service Kubernetes. Annoter la spécification de déploiement GKE afin de créer automatiquement un groupe de points de terminaison du réseau (NEG, Network Endpoint Group) pour le service
  3. Configurer Cloud Service Mesh à l'aide du NEG et d'autres composants d'équilibrage de charge Google Cloud
  4. Vérifier que le déploiement fonctionne correctement en utilisant une application cliente gRPC sans proxy pour envoyer du trafic vers l'application de serveur gRPC

Configurer des clusters GKE pour Cloud Service Mesh

Cette section fournit des instructions pour autoriser les clusters GKE à fonctionner avec Cloud Service Mesh.

Configuration requise pour les clusters GKE

Les clusters GKE doivent répondre aux exigences suivantes :

  • Vous devez activer la compatibilité avec les groupes de points de terminaison du réseau. Pour en savoir plus et obtenir des exemples, consultez la section NEG autonomes. La fonctionnalité de NEG autonome est disponible en disponibilité générale pour Cloud Service Mesh.
  • Les instances des nœuds du cluster doivent disposer d'une autorisation pour accéder à l'API Cloud Service Mesh. Pour en savoir plus sur les autorisations requises, consultez la section Activer le compte de service pour accéder à l'API Cloud Service Mesh.
  • Les conteneurs doivent avoir accès à l'API Cloud Service Mesh, qui est protégée par l'authentification OAuth. Pour en savoir plus, consultez la section Configuration de l'hôte.

Créer le cluster GKE

L'exemple suivant montre comment créer un cluster GKE nommé grpc-td-cluster dans la zone us-central1-a zone.

Console

Pour créer un cluster à l'aide de la console Google Cloud, procédez comme suit :

  1. Accédez au menu "Kubernetes Engine" dans la console Google Cloud.

    Accéder au menu Google Kubernetes Engine

  2. Cliquez sur Créer un cluster.

  3. Sélectionnez le modèle Cluster standard ou choisissez un modèle approprié pour votre charge de travail.

  4. Personnalisez le modèle si nécessaire. Les champs suivants sont obligatoires :

    • Nom : saisissez grpc-td-cluster.
    • Type d'emplacement : Zonal.
    • Zone : us-central1-a
    • Pool de nœuds :
  5. Dans le menu de gauche, cliquez sur default-pool.

  6. Redéfinissez le paramètre Nom sur grpc-td-cluster.

  7. Dans le champTaille, saisissez le nombre de nœuds à créer. Vous devez disposer d'un quota de ressources disponible pour les nœuds et les ressources associées (telles que les routes de pare-feu).

  8. Dans le menu de gauche, cliquez sur Nodes (Nœuds).

  9. Sous Configuration de la machine, dans Famille de machines, cliquez sur Optimisé pour le calcul.

  10. Sélectionnez un type de machine. Pour en savoir plus sur les tarifs par type de machine, consultez la page des tarifs de Compute Engine.

  11. Sous Mise en réseau, ajoutez le tag réseau allow-health-checks.

  12. Dans le menu de gauche, cliquez sur Sécurité du nœud.

  13. Dans la section Champs d'application de l'accès, sélectionnez Autoriser l'accès complet à toutes les API Cloud.

  14. Cliquez sur Create (Créer).

Après avoir créé un cluster dans la console Google Cloud, vous devez configurer kubectl pour interagir avec le cluster. Pour en savoir plus, consultez la section Générer une entrée kubeconfig.

gcloud

Créez le 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

Obtenir les droits requis pour le cluster GKE

Basculez vers le cluster que vous venez de créer en exécutant la commande ci-après. Cette commande redirige kubectl vers le cluster approprié.

gcloud

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

Configurer des services GKE

Cette section explique comment préparer les spécifications de déploiement GKE pour qu'elles fonctionnent avec Cloud Service Mesh. Cette démarche consiste à configurer un exemple de service GKE helloworld avec des annotations NEG.

L'exemple de service helloworld est une application de serveur gRPC qui renvoie un message en réponse à la requête d'un client gRPC. Notez que le service helloworld n'a rien de spécial. Il ne s'agit pas d'un service gRPC sans proxy, et il peut répondre aux requêtes de n'importe quel client gRPC.

La partie "sans proxy" ne fonctionne que lorsqu'une application cliente gRPC se connecte à Cloud Service Mesh, découvre le service helloworld, puis peut envoyer du trafic vers les pods associés à helloworld, sans avoir à compter sur les adresses IP ou la résolution de noms DNS.

Configurer des services GKE avec des NEG

La première étape dans la configuration des services GKE à utiliser avec Cloud Service Mesh consiste à exposer le service via un NEG. Pour être exposée via des NEG, chaque spécification doit comporter l'annotation suivante, correspondant au port que vous souhaitez exposer.

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

Cette annotation crée un NEG autonome lorsque vous déployez votre service pour la première fois. Ce NEG contient des points de terminaison qui correspondent aux adresses IP et aux ports du pod. Pour en savoir plus et obtenir des exemples, consultez la section NEG autonomes.

Dans l'exemple suivant, vous allez déployer un service Kubernetes helloworld exposé sur le port 8080. Il s'agit du port sur lequel le service est visible dans le cluster. Le service gRPC du pod écoute sur targetPort 50051. Il s'agit du port sur le pod auquel la requête est envoyée. Généralement, le port et le targetPort sont définis sur la même valeur pour plus de commodité, mais cet exemple utilise des valeurs différentes pour indiquer la valeur correcte à utiliser dans l'annotation 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

Vérifiez que le service helloworld est créé :

kubectl get svc

Le résultat de kubectl get svc doit ressembler à ce qui suit :

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

Vérifiez que le pod de l'application est en cours d'exécution :

kubectl get pods

Le résultat de kubectl get pods doit ressembler à ce qui suit :

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

Vérifiez que le nom du NEG est correct.

Console

Pour afficher la liste des groupes de points de terminaison du réseau, accédez à la page "Groupes de points de terminaison du réseau" dans Google Cloud Console. Un NEG nommé example-grpc-server s'affiche.
Accéder à la page "Groupes de points de terminaison du réseau"

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

Configurer Cloud Service Mesh avec des composants d'équilibrage de charge

Cette section explique comment configurer les composants d'équilibrage de charge Google Cloud pour vos services. Ces composants contiennent des informations de configuration permettant aux clients gRPC sans proxy de communiquer avec vos services GKE.

L'exemple de configuration de Cloud Service Mesh qui suit repose sur les hypothèses suivantes:

  • Les NEG et toutes les autres ressources sont créés dans le réseau par défaut en mode automatique, dans la zone us-central1-a.
  • Lorsque vous utilisez Google Cloud CLI, le nom du NEG du cluster est example-grpc-server.

Créer la vérification d'état, la règle de pare-feu et le service de backend

Dans cette section, vous allez créer une vérification d'état et la règle de pare-feu de celle-ci. La vérification d'état doit utiliser le protocole de vérification d'état gRPC. La règle de pare-feu permet aux tests de vérification d'état de se connecter aux VM de votre déploiement. L'instruction --use-serving-port est utilisée par les vérifications d'état afin d'obtenir le port d'écoute configuré pour chaque point de terminaison.

La règle de pare-feu autorise les connexions à la vérification d'état entrantes aux instances de votre réseau.

Dans cette section, vous allez créer un service de backend global avec un schéma d'équilibrage de charge INTERNAL_SELF_MANAGED et le protocole GRPC, puis associer la vérification d'état au service de backend.

Pour en savoir plus, consultez la page Créer des vérifications d'état.

gcloud

  1. Créez la vérification d'état.

    gcloud compute health-checks create grpc grpc-gke-helloworld-hc \
     --use-serving-port
    
  2. Créez la règle de pare-feu.

    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. Créez le service 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. Ajoutez des groupes de points de terminaison du réseau au service 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
    

Créer la carte des règles de routage

Dans cette section, vous allez créer un mappage d'URL, un outil de mise en correspondance des chemins d'accès et une règle d'hôte pour acheminer le trafic de votre service, en fonction du nom d'hôte et d'un chemin d'accès. L'exemple suivant utilise helloworld-gke comme nom de service. Le client gRPC utilise ce nom de service dans l'URI cible lors de la connexion au service helloworld. Vous allez également créer le proxy gRPC cible et la règle de transfert.

Pour en savoir plus, consultez la section Cartes des règles de routage.

L'exemple suivant utilise le nom de service helloworld-gke et le port 8000. Cela signifie que le client gRPC doit utiliser xds:///helloworld-gke:8000 pour se connecter à ce service, et une règle d'hôte helloworld-gke:8000 doit être configurée dans le mappage d'URL. Notez que le port de service 8080 affiché dans la spécification de service Kubernetes dans une section précédente n'est pas utilisé par Cloud Service Mesh, car helloworld-gke:8000 est directement résolu en points de terminaison NEG qui écoutent sur le targetPort 50051. Généralement, le port de la règle d'hôte du mappage d'URL et les port et targetPort de la spécification de service Kubernetes sont tous définis sur la même valeur pour plus de commodité, mais cet exemple utilise des valeurs différentes pour indiquer que le port dans la spécification de service n'est pas utilisé par Cloud Service Mesh.

gcloud

  1. Créez le mappage d'URL.

    gcloud compute url-maps create grpc-gke-url-map \
    --default-service grpc-gke-helloworld-service
    
  2. Créez l'outil de mise en correspondance des chemins d'accès.

    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. Créez le proxy gRPC cible.

    gcloud compute target-grpc-proxies create grpc-gke-proxy \
    --url-map grpc-gke-url-map \
    --validate-for-proxyless
    
  4. Créez la règle de transfert.

    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 est maintenant configuré pour équilibrer la charge du trafic sur les points de terminaison du NEG pour les services spécifiés dans le mappage d'URL.

Vérifier la configuration

Une fois le processus de configuration terminé, vérifiez que vous pouvez accéder au serveur gRPC helloworld à l'aide d'un client gRPC sans proxy. Ce client se connecte à Cloud Service Mesh, obtient des informations sur le service helloworld (configuré avec Cloud Service Mesh à l'aide du service de backend grpc-gke-helloworld-service) et utilise ces informations pour envoyer du trafic aux backends du service.

Vous pouvez également consulter la section Cloud Service Mesh dans la console Google Cloud pour en savoir plus sur le service configuré helloworld-gke, et vérifier si les backends sont signalés comme étant opérationnels.

Effectuer la vérification avec un client gRPC sans proxy

Dans les exemples suivants, vous utilisez des clients gRPC dans différents langages ou l'outil grpcurl pour vérifier que Cloud Service Mesh achemine correctement le trafic au sein du maillage. Créez un pod client, puis ouvrez une interface système et exécutez les commandes de validation à partir de l'interface système.

Configurer la variable d'environnement et le fichier d'amorçage

L'application cliente nécessite un fichier de configuration d'amorçage. Modifiez la spécification de déploiement de votre application Kubernetes en ajoutant un initContainer qui génère le fichier d'amorçage et un volume pour transférer le fichier. Mettez à jour votre conteneur existant pour trouver le fichier.

Ajoutez les éléments initContainer suivants à la spécification de déploiement de l'application :

      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

Mettez à jour la section env du conteneur d'application pour inclure les éléments suivants :

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

Voici un exemple complet de spécification Kubernetes côté client :

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

Lorsque le déploiement est prêt, ouvrez une interface système sur le pod client.

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

Pour vérifier la configuration, exécutez les exemples appropriés dans l'interface système du pod.

Java

Pour vérifier le service avec un client Java gRPC, procédez comme suit :

  1. Téléchargez la dernière version de gRPC Java, avec le dernier correctif et créez l'application 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. Exécutez le client en spécifiant "world" comme nom et "xds:///helloworld-gke:8000" comme URI et port du service.

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

Go

Pour vérifier le service avec un client Go gRPC, procédez comme suit :

  1. Téléchargez la dernière version de gRPC Go avec le correctif le plus récent, puis créez l'application 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. Exécutez le client en spécifiant "world" comme nom et "xds:///helloworld-gke:8000" comme URI et port du service.

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

C++

Pour vérifier le service avec un client C++ gRPC, procédez comme suit :

  1. Téléchargez la dernière version de gRPC C++, avec le dernier correctif, et créez l'exemple de client 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. Exécutez le client avec "xds:///helloworld-gke:8000" comme URI et port de service.

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

grpcurl

L'outil grpcurl peut également agir en tant que client gRPC sans proxy. Dans ce cas, grpcurl utilise la variable d'environnement et les informations d'amorçage pour se connecter à Cloud Service Mesh. Il apprend ensuite le service helloworld, qui a été configuré avec Cloud Service Mesh via le service de backend grpc-gke-helloworld-service.

Pour vérifier votre configuration à l'aide de l'outil grpcurl, procédez comme suit :

  1. Téléchargez et installez l'outil 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. Exécutez l'outil grpcurl avec "xds:///helloworld-gke:8000" comme URI de service et helloworld.Greeter/SayHello comme nom du service et méthode à appeler. Les paramètres de la méthode SayHello sont transmis à l'aide de l'option -d.

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

Python

Pour vérifier le service avec un client Python gRPC, exécutez la commande suivante. Utilisez la dernière version de gRPC avec le correctif le plus récent.

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

Pour vérifier le service avec un client Ruby gRPC, exécutez la commande suivante : Utilisez la dernière version de gRPC avec le correctif le plus récent.

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

Pour vérifier le service avec un client PHP gRPC, exécutez la commande suivante : Utilisez la dernière version de gRPC avec le correctif le plus récent.

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

Pour vérifier le service avec un client Node.js gRPC, exécutez la commande suivante : Utilisez la dernière version de gRPC avec le correctif le plus récent.

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

Un résultat semblable à ce qui suit doit s'afficher, où INSTANCE_HOST_NAME correspond au nom d'hôte de l'instance de VM :

Greetings: Hello world, from INSTANCE_HOST_NAME

Cela confirme que le client gRPC sans proxy a bien été connecté à Cloud Service Mesh et a découvert les backends du service helloworld-gke à l'aide du résolveur de nom xds. Le client a envoyé une requête à l'un des backends du service sans avoir à connaître l'adresse IP ou la résolution DNS.

Étape suivante