Configurar una malla de servicios de gRPC sin proxy

En esta guía, se muestra cómo configurar una malla de servicios de gRPC sin proxy.

Antes de comenzar

No crees una malla de servicios de gRPC sin proxy en un espacio de nombres en el que esté habilitada la inserción automática de sidecar de Envoy. Para determinar si la inserción de sidecar está habilitada, ejecuta el siguiente comando:

kubectl get namespace default --show-labels

Si la inserción automática de sidecar está habilitada, ejecuta este comando para quitar la etiqueta:

kubectl label namespace default istio-injection-

Implementa un servicio de gRPC

En esta sección, implementarás un servicio de ejemplo helloworld de gRPC. 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. El servicio helloworld expone el servicio de gRPC en el puerto 8080 del clúster.

  1. En el archivo grpc-td-helloworld.yaml, guarda lo siguiente:

    apiVersion: v1
    kind: Service
    metadata:
      name: helloworld
      namespace: default
    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
      namespace: default
    spec:
      selector:
        matchLabels:
          run: app1
      replicas: 2
      template:
        metadata:
          labels:
            run: app1
          annotations:
            sidecar.istio.io/inject: "false"
        spec:
          containers:
          - image: grpc/java-example-hostname:1.37.0
            name: app1
            ports:
            - protocol: TCP
              containerPort: 50051
    
  2. Aplica el archivo grpc-td-helloworld.yaml:

    kubectl apply -f grpc-td-helloworld.yaml
    
  3. Verifica que se haya creado el nuevo servicio helloworld:

    kubectl get svc -n default
    

    El resultado es similar al siguiente:

    NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT (S)   AGE
    helloworld     ClusterIP   10.71.9.71   <none>        8080/TCP  41m
    [..skip..]
    
  4. Verifica que el pod de aplicación se esté ejecutando:

    kubectl get pods -n default
    
  5. Los Pods de salida deben ser similares a los siguientes:

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

Configura una malla de servicios de gRPC

En esta sección, configurarás una malla de servicios de gRPC simple.

  1. En el archivo td-grpc-mesh.yaml, guarda el siguiente manifiesto mesh.

    kind: TDMesh
    apiVersion: net.gke.io/v1alpha1
    metadata:
      name: td-grpc-mesh
      namespace: default
    spec:
      gatewayClassName: gke-td
      allowedRoutes:
        namespaces:
          from: All
        kinds:
        - group: net.gke.io
          kind: TDGRPCRoute
    
  2. Aplica el manifiesto de la malla a gke-1:

    kubectl apply -f td-grpc-mesh.yaml
    

    El ejemplo TDMesh permite que solo se conecten recursos TDGRPCRoute a él. El manifiesto define qué tipos de ruta están permitidas.

  3. Verifica que se haya creado la malla td-grpc-mesh nueva:

    kubectl describe tdmesh td-grpc-mesh -n default
    

    El resultado es similar a este:

    ...
    Status:
      Conditions:
        Last Transition Time:  2022-04-14T22:22:09Z
        Message:
        Reason:                MeshReady
        Status:                True
        Type:                  Ready
        Last Transition Time:  2022-04-14T22:21:41Z
        Message:
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
    Events:
      Type    Reason  Age   From                Message
      ----    ------  ----  ----                -------
      Normal  ADD     79s   mc-mesh-controller  Processing mesh default/td-grpc-mesh
      Normal  UPDATE  79s   mc-mesh-controller  Processing mesh default/td-grpc-mesh
      Normal  SYNC    50s   mc-mesh-controller  SYNC on default/td-grpc-mesh was a success
    
  4. En el archivo helloworld-route.yaml, guarda el siguiente manifiesto .

    kind: TDGRPCRoute
    apiVersion: net.gke.io/v1alpha1
    metadata:
      name: helloworld-route
      namespace: default
    spec:
      parentRefs:
      - name: td-grpc-mesh
        namespace: default
        group: net.gke.io
        kind: TDMesh
      hostnames:
      - helloworld
      rules:
      - backendRefs:
        - name: helloworld
          port: 8080
          namespace: default
    
  5. Aplica el manifiesto helloworld-route.yaml a gke-1:

    kubectl apply -f helloworld-route.yaml
    
  6. Verifica que se haya creado el nuevo recurso helloworld-route GRPCRoute:

    kubectl get tdgrpcroute -n default
    

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 y la usa para enviar tráfico a los backends del servicio.

En el siguiente ejemplo, usa la herramienta de grpcurl para verificar que Traffic Director enrute 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

  1. En un archivo grpc-client.yaml, guarda el siguiente manifiesto del Pod:

    apiVersion: v1
    kind: Pod
    metadata:
      name: static-sleeper
      namespace: default
      annotations:
        sidecar.istio.io/inject: "false"
    spec:
      containers:
      - image: curlimages/curl:7.82.0
        imagePullPolicy: IfNotPresent
        name: sleeper
        command:
        - sleep
        - 365d
        env:
        - name: GRPC_XDS_BOOTSTRAP
          value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/grpc-xds/
      initContainers:
      - args:
        - --config-mesh-experimental
        - "gketd-td-grpc-mesh"
        - --output
        - "/tmp/bootstrap/td-grpc-bootstrap.json"
        image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.14.0
        imagePullPolicy: IfNotPresent
        name: grpc-td-init
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/bootstrap/
      volumes:
      - name: grpc-td-conf
        emptyDir:
          medium: Memory
    
  2. Aplica el manifiesto del Pod en gke-1:

    kubectl apply -f grpc-client.yaml
    
  3. Cuando el Pod esté listo, abre una shell al Pod del cliente:

    kubectl exec -it static-sleeper -- /bin/sh
    

Puedes usar la herramienta de grpcurl como un cliente de gRPC sin proxy. La herramienta grpcurl usa información de variables de entorno y de arranque para conectarse a Traffic Director. Luego, la herramienta aprende sobre el servicio helloworld, que se configuró con Traffic Director.

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

  1. Descarga y, luego, instala la herramienta de grpcurl:

    cd /home/curl_user
    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 como el URI del servicio y helloworld.Greeter/SayHello como el nombre del servicio y el 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 helloworld.Greeter/SayHello
    

    El resultado es similar al siguiente, en el que INSTANCE_HOST_NAME es el nombre de host del Pod:

    Greetings: Hello world, from INSTANCE_HOST_NAME
    

Este resultado verifica que el cliente de gRPC sin proxy se conectó de forma correcta a Traffic Director y aprendió sobre los backends del servicio helloworld mediante el agente de resolución de nombres 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?