Configurar la seguridad de los servicios con gRPC sin proxy (versión antigua)

En esta guía se explica cómo configurar un servicio de seguridad para una malla de servicios gRPC sin proxy.

Este documento solo se aplica a Cloud Service Mesh con las APIs de balanceo de carga. Este es un documento antiguo.

Requisitos

Antes de configurar la seguridad del servicio para la malla de servicios gRPC sin proxy, asegúrate de que cumples los siguientes requisitos.

Configurar la gestión de identidades y accesos

Debes tener los permisos necesarios para usar Google Kubernetes Engine. Como mínimo, debes tener los siguientes roles:

  • roles/container.clusterAdmin rol de GKE
  • Rol de roles/compute.instanceAdmin Compute Engine
  • Rol de roles/iam.serviceAccountUser

Para crear los recursos necesarios para la configuración, debe tener el rol compute.NetworkAdmin. Este rol contiene todos los permisos necesarios para crear, actualizar, eliminar, enumerar y usar (es decir, hacer referencia a este en otros recursos) los recursos necesarios. Si eres el propietario y editor de tu proyecto, tienes este rol automáticamente.

Ten en cuenta que networksecurity.googleapis.com.clientTlsPolicies.use y networksecurity.googleapis.com.serverTlsPolicies.use no se aplican cuando haces referencia a estos recursos en el servicio de backend y en los recursos de proxy HTTPS de destino.

Si se aplica en el futuro y usas el rol compute.NetworkAdmin, no notarás ningún problema cuando se aplique esta comprobación.

Si usas roles personalizados y esta comprobación se aplica en el futuro, debes incluir el permiso .use correspondiente. De lo contrario, en el futuro, es posible que tu rol personalizado no tenga los permisos necesarios para hacer referencia a clientTlsPolicy o serverTlsPolicy desde el servicio de backend o el proxy HTTPS de destino, respectivamente.

Prepararse para la configuración

La seguridad de la malla de servicios sin proxy (PSM) añade seguridad a una malla de servicios configurada para el balanceo de carga según la documentación de los servicios gRPC sin proxy. En una malla de servicios sin proxy, un cliente gRPC usa el esquema xds: en el URI para acceder al servicio, lo que habilita las funciones de balanceo de carga y descubrimiento de endpoints de PSM.

Actualizar los clientes y servidores gRPC a la versión correcta

Crea o vuelve a crear tus aplicaciones con la versión mínima admitida de gRPC para tu lenguaje.

Actualizar el archivo de arranque

Las aplicaciones gRPC usan un único archivo de arranque, que debe tener todos los campos que requiere el código del lado del cliente y del servidor de gRPC. Un generador de bootstrap genera automáticamente el archivo de bootstrap para incluir las marcas y los valores que necesita la seguridad de PSM. Para obtener más información, consulta la sección Archivo de arranque, que incluye un archivo de arranque de ejemplo.

Descripción general de la configuración

Este proceso de configuración es una extensión de la configuración de Cloud Service Mesh con GKE y servicios de gRPC sin proxy. Los pasos de ese procedimiento de configuración que no se hayan modificado se mencionan en los casos en los que se apliquen.

Estas son las principales mejoras de la configuración de Cloud Service Mesh con GKE:

  1. Configurar el servicio de AC, en el que creas grupos de AC privadas y las autoridades de certificación necesarias.
  2. Crear un clúster de GKE con las funciones de Workload Identity Federation for GKE y de certificados de malla, así como con la integración de CA Service.
  3. Configurar la emisión de certificados de malla en el clúster.
  4. Crear las cuentas de servicio de cliente y de servidor.
  5. Configurar el servidor de ejemplo que usa las APIs xDS y las credenciales del servidor xDS para obtener la configuración de seguridad de Cloud Service Mesh.
  6. Configurar el cliente de ejemplo que usa credenciales de xDS.
  7. Actualizar la configuración de la malla de servicios de Cloud para incluir la configuración de seguridad.

Puedes ver ejemplos de código para usar las credenciales de xDS en las siguientes ubicaciones:

Actualizar Google Cloud CLI

Para actualizar la CLI de Google Cloud, ejecuta el siguiente comando:

gcloud components update

Configurar variables de entorno

En esta guía, se usan comandos de Cloud Shell y la información repetida en los comandos se representa mediante varias variables de entorno. Asigna tus valores específicos a las siguientes variables de entorno en el entorno de shell antes de ejecutar los comandos. Cada línea de comentario indica el significado de la variable de entorno asociada.

# Your project ID
PROJECT_ID=YOUR_PROJECT_ID

# GKE cluster name and zone for this example.
CLUSTER_NAME="secure-psm-cluster"
ZONE="us-east1-d"

# GKE cluster URL derived from the above
GKE_CLUSTER_URL="https://container.googleapis.com/v1/projects/${PROJECT_ID}/locations/${ZONE}/clusters/${CLUSTER_NAME}"

# Workload pool to be used with the GKE cluster
WORKLOAD_POOL="${PROJECT_ID}.svc.id.goog"

# Kubernetes namespace to run client and server demo.
K8S_NAMESPACE='default'
DEMO_BACKEND_SERVICE_NAME='grpc-gke-helloworld-service'

# Compute other values
# Project number for your project
PROJNUM=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)")

# VERSION is the GKE cluster version. Install and use the most recent version
# from the rapid release channel and substitute its version for
# CLUSTER_VERSION, for example:
# VERSION=latest available version
# Note that the minimum required cluster version is 1.21.4-gke.1801.
VERSION="CLUSTER_VERSION"
SA_GKE=service-${PROJNUM}@container-engine-robot.iam.gserviceaccount.com

Habilitar el acceso a las APIs necesarias

En esta sección se explica cómo habilitar el acceso a las APIs necesarias.

  1. Ejecuta el siguiente comando para habilitar Cloud Service Mesh y otras APIs necesarias para la seguridad de la malla de servicios gRPC sin proxy.

    gcloud services enable \
        container.googleapis.com \
        cloudresourcemanager.googleapis.com \
        compute.googleapis.com \
        trafficdirector.googleapis.com \
        networkservices.googleapis.com \
        networksecurity.googleapis.com \
        privateca.googleapis.com \
        gkehub.googleapis.com
    
  2. Ejecuta el siguiente comando para permitir que la cuenta de servicio predeterminada acceda a la API de seguridad de Cloud Service Mesh.

    GSA_EMAIL=$(gcloud iam service-accounts list --format='value(email)' \
        --filter='displayName:Compute Engine default service account')
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member serviceAccount:${GSA_EMAIL} \
       --role roles/trafficdirector.client
    

Crear o actualizar un clúster de GKE

La seguridad de los servicios de Cloud Service Mesh depende de la integración del servicio de CA con GKE. El clúster de GKE debe cumplir los siguientes requisitos, además de los requisitos de configuración:

  • Usa una versión de clúster mínima de 1.21.4-gke.1801. Si necesitas funciones que estén en una versión posterior, puedes obtenerla del canal de lanzamiento rápido.
  • El clúster de GKE debe estar habilitado y configurado con certificados de malla, tal como se describe en el artículo Crear autoridades de certificación para emitir certificados.
  1. Crea un clúster que use Workload Identity Federation para GKE. Si vas a actualizar un clúster, ve al siguiente paso. El valor que proporciones para --tags debe coincidir con el nombre que se haya pasado a la marca --target-tags del comando firewall-rules create en la sección Configurar Cloud Service Mesh con componentes de Cloud Load Balancing.

    # Create a GKE cluster with GKE managed mesh certificates.
    gcloud container clusters create CLUSTER_NAME \
      --release-channel=rapid \
      --scopes=cloud-platform \
      --image-type=cos_containerd \
      --machine-type=e2-standard-2 \
      --zone=ZONE \
      --workload-pool=PROJECT_ID.svc.id.goog \
      --enable-mesh-certificates \
      --cluster-version=CLUSTER_VERSION \
      --enable-ip-alias \
      --tags=allow-health-checks \
      --workload-metadata=GKE_METADATA
    

    La creación del clúster puede tardar varios minutos en completarse.

  2. Si utilizas un clúster, activa Workload Identity Federation para GKE y los certificados de malla de GKE. Asegúrate de que el clúster se haya creado con la marca --enable-ip-alias, que no se puede usar con el comando update.

    gcloud container clusters update CLUSTER_NAME \
      --enable-mesh-certificates
    
  3. Ejecuta el siguiente comando para cambiar al nuevo clúster como clúster predeterminado para tus comandos kubectl:

    gcloud container clusters get-credentials CLUSTER_NAME \
      --zone ZONE
    

Registrar clústeres en una flota

Registra el clúster que has creado o actualizado en Crear un clúster de GKE con una flota. Si registras el clúster, te resultará más fácil configurar clústeres en varios proyectos.

Ten en cuenta que cada uno de estos pasos puede tardar hasta diez minutos en completarse.

  1. Registra tu clúster en la flota:

    gcloud container fleet memberships register CLUSTER_NAME \
      --gke-cluster=ZONE/CLUSTER_NAME \
      --enable-workload-identity --install-connect-agent \
      --manifest-output-file=MANIFEST-FILE_NAME
    

    Sustituye las variables de la siguiente manera:

    • CLUSTER_NAME: el nombre del clúster.
    • ZONE: la zona de tu clúster.
    • MANIFEST-FILE_NAME: la ruta en la que estos comandos generan el archivo de manifiesto para el registro.

    Si el proceso de registro se completa correctamente, verás un mensaje como el siguiente:

    Finished registering the cluster CLUSTER_NAME with the fleet.
  2. Aplica el archivo de manifiesto generado a tu clúster:

    kubectl apply -f MANIFEST-FILE_NAME
    

    Si el proceso de solicitud se completa correctamente, verás mensajes como los siguientes:

    namespace/gke-connect created
    serviceaccount/connect-agent-sa created
    podsecuritypolicy.policy/gkeconnect-psp created
    role.rbac.authorization.k8s.io/gkeconnect-psp:role created
    rolebinding.rbac.authorization.k8s.io/gkeconnect-psp:rolebinding created
    role.rbac.authorization.k8s.io/agent-updater created
    rolebinding.rbac.authorization.k8s.io/agent-updater created
    role.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created
    clusterrole.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created
    clusterrolebinding.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created
    clusterrolebinding.rbac.authorization.k8s.io/gke-connect-feature-authorizer-20210416-01-00 created
    rolebinding.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created
    role.rbac.authorization.k8s.io/gke-connect-namespace-getter created
    rolebinding.rbac.authorization.k8s.io/gke-connect-namespace-getter created
    secret/http-proxy created
    deployment.apps/gke-connect-agent-20210416-01-00 created
    service/gke-connect-monitoring created
    secret/creds-gcp create
    
  3. Obtén el recurso de pertenencia del clúster:

    kubectl get memberships membership -o yaml
    

    El resultado debe incluir el grupo de identidades de carga de trabajo asignado por la flota, donde PROJECT_ID es el ID de tu proyecto:

    workload_identity_pool: PROJECT_ID.svc.id.goog
    

    Esto significa que el clúster se ha registrado correctamente.

Crear autoridades de certificación para emitir certificados

Para emitir certificados a tus pods, crea un grupo de Servicio de Autoridades de Certificación y las siguientes autoridades de certificación (ACs):

  • CA raíz. Es la raíz de confianza de todos los certificados de malla emitidos. Puedes usar una CA raíz que ya tengas. Crea la AC raíz en el nivel enterprise, que está pensado para la emisión de certificados de larga duración y bajo volumen.
  • Autoridad de certificación subordinada. Esta CA emite certificados para cargas de trabajo. Crea la CA subordinada en la región en la que se haya desplegado tu clúster. Crea la AC subordinada en el nivel devops, que está diseñado para la emisión de certificados de gran volumen y de corta duración.

Crear una AC subordinada es opcional, pero te recomendamos que lo hagas en lugar de usar tu AC raíz para emitir certificados de malla de GKE. Si decides usar la AC raíz para emitir certificados de malla, asegúrate de que el modo de emisión basado en la configuración predeterminado siga permitido.

La CA subordinada puede estar en una región diferente a la de tu clúster, pero te recomendamos que la crees en la misma región que tu clúster para optimizar el rendimiento. Sin embargo, puedes crear las autoridades de certificación raíz y subordinadas en diferentes regiones sin que esto afecte al rendimiento ni a la disponibilidad.

Estas regiones se admiten en el servicio de autoridades de certificación:

Nombre de la región Descripción de la región
asia-east1 Taiwán
asia-east2 Hong Kong
asia-northeast1 Tokio
asia-northeast2 Osaka
asia-northeast3 Seúl
asia-south1 Bombay
asia-south2 Deli
asia-southeast1 Singapur
asia-southeast2 Yakarta
australia-southeast1 Sídney
australia-southeast2 Melbourne
europe-central2 Varsovia
europe-north1 Finlandia
europe-southwest1 Madrid
europe-west1 Bélgica
europe-west2 Londres
europe-west3 Fráncfort
europe-west4 Países Bajos
europe-west6 Zúrich
europe-west8 Milán
europe-west9 París
europe-west10 Berlín
europe-west12 Turín
me-central1 Doha
me-central2 Dammam
me-west1 Tel Aviv
northamerica-northeast1 Montreal
northamerica-northeast2 Toronto
southamerica-east1 São Paulo
southamerica-west1 Santiago
us-central1 Iowa
us-east1 Carolina del Sur
us-east4 Norte de Virginia
us-east5 Columbus
us-south1 Dallas
us-west1 Oregón
us-west2 Los Ángeles
us-west3 Salt Lake City
us-west4 Las Vegas

También puedes consultar la lista de ubicaciones admitidas ejecutando el siguiente comando:

gcloud privateca locations list
  1. Concede el permiso roles/privateca.caManager de IAM a las personas que creen un grupo de AC y una AC. Ten en cuenta que, en el caso de MEMBER, el formato correcto es user:userid@example.com. Si esa persona es el usuario actual, puedes obtener su ID con el comando de shell $(gcloud auth list --filter=status:ACTIVE --format="value(account)").

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.caManager
    
  2. Asigna el rol role/privateca.admin al servicio de CA a las personas que necesiten modificar las políticas de gestión de identidades y accesos, donde MEMBER es una persona que necesita este acceso, en concreto, cualquier persona que realice los pasos que se indican a continuación para asignar los roles privateca.auditor y privateca.certificateManager:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.admin
    
  3. Crea el grupo de servicios de la CA raíz.

    gcloud privateca pools create ROOT_CA_POOL_NAME \
      --location ROOT_CA_POOL_LOCATION \
      --tier enterprise
    
  4. Crea una CA raíz.

    gcloud privateca roots create ROOT_CA_NAME --pool ROOT_CA_POOL_NAME \
      --subject "CN=ROOT_CA_NAME, O=ROOT_CA_ORGANIZATION" \
      --key-algorithm="ec-p256-sha256" \
      --max-chain-length=1 \
      --location ROOT_CA_POOL_LOCATION
    

    Para esta configuración de demostración, utilice los siguientes valores para las variables:

    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_NAME=pkcs2-ca
    • ROOT_CA_POOL_LOCATION=us-east1
    • ROOT_CA_ORGANIZATION="TestCorpLLC"
  5. Crea el grupo subordinado y la AC subordinada. Asegúrate de que el modo de emisión basado en la configuración predeterminado siga permitido.

    gcloud privateca pools create SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --tier devops
    
    gcloud privateca subordinates create SUBORDINATE_CA_NAME \
      --pool SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --issuer-pool ROOT_CA_POOL_NAME \
      --issuer-location ROOT_CA_POOL_LOCATION \
      --subject "CN=SUBORDINATE_CA_NAME, O=SUBORDINATE_CA_ORGANIZATION" \
      --key-algorithm "ec-p256-sha256" \
      --use-preset-profile subordinate_mtls_pathlen_0
    

    Para esta configuración de demostración, utilice los siguientes valores para las variables:

    • SUBORDINATE_CA_POOL_NAME="td-ca-pool"
    • SUBORDINATE_CA_POOL_LOCATION=us-east1
    • SUBORDINATE_CA_NAME="td-ca"
    • SUBORDINATE_CA_ORGANIZATION="TestCorpLLC"
    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_POOL_LOCATION=us-east1
  6. Asigna el rol privateca.auditor de gestión de identidades y accesos al grupo de AC raíz para permitir el acceso desde la cuenta de servicio de GKE:

    gcloud privateca pools add-iam-policy-binding ROOT_CA_POOL_NAME \
     --location ROOT_CA_POOL_LOCATION \
     --role roles/privateca.auditor \
     --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
    
  7. Concede el rol de gestión de identidades y accesos privateca.certificateManager al grupo de CAs subordinadas para permitir el acceso desde la cuenta de servicio de GKE:

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_NAME \
      --location SUBORDINATE_CA_POOL_LOCATION \
      --role roles/privateca.certificateManager \
      --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
    
  8. Guarda la siguiente configuración WorkloadCertificateConfig YAML para indicar a tu clúster cómo emitir certificados de malla:

    apiVersion: security.cloud.google.com/v1
    kind: WorkloadCertificateConfig
    metadata:
      name: default
    spec:
      # Required. The CA service that issues your certificates.
      certificateAuthorityConfig:
        certificateAuthorityServiceConfig:
          endpointURI: ISSUING_CA_POOL_URI
    
      # Required. The key algorithm to use. Choice of RSA or ECDSA.
      #
      # To maximize compatibility with various TLS stacks, your workloads
      # should use keys of the same family as your root and subordinate CAs.
      #
      # To use RSA, specify configuration such as:
      #   keyAlgorithm:
      #     rsa:
      #       modulusSize: 4096
      #
      # Currently, the only supported ECDSA curves are "P256" and "P384", and the only
      # supported RSA modulus sizes are 2048, 3072 and 4096.
      keyAlgorithm:
        rsa:
          modulusSize: 4096
    
      # Optional. Validity duration of issued certificates, in seconds.
      #
      # Defaults to 86400 (1 day) if not specified.
      validityDurationSeconds: 86400
    
      # Optional. Try to start rotating the certificate once this
      # percentage of validityDurationSeconds is remaining.
      #
      # Defaults to 50 if not specified.
      rotationWindowPercentage: 50
    
    

    Haz los cambios siguientes:

    • El ID del proyecto en el que se ejecuta el clúster:
      PROJECT_ID
    • El URI completo de la AC que emite los certificados de tu malla (ISSUING_CA_POOL_URI). Puede ser tu AC subordinada (opción recomendada) o tu AC raíz. El formato es el siguiente:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/SUBORDINATE_CA_POOL_LOCATION/caPools/SUBORDINATE_CA_POOL_NAME
  9. Guarda la siguiente configuración TrustConfig YAML para indicar a tu clúster cómo confiar en los certificados emitidos:

    apiVersion: security.cloud.google.com/v1
    kind: TrustConfig
    metadata:
      name: default
    spec:
      # You must include a trustStores entry for the trust domain that
      # your cluster is enrolled in.
      trustStores:
      - trustDomain: PROJECT_ID.svc.id.goog
        # Trust identities in this trustDomain if they appear in a certificate
        # that chains up to this root CA.
        trustAnchors:
        - certificateAuthorityServiceURI: ROOT_CA_POOL_URI
    

    Haz los cambios siguientes:

    • El ID del proyecto en el que se ejecuta el clúster:
      PROJECT_ID
    • El URI completo del grupo de AC raíz (ROOT_CA_POOL_URI). El formato es el siguiente:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/ROOT_CA_POOL_LOCATION/caPools/ROOT_CA_POOL_NAME
  10. Aplica las configuraciones a tu clúster:

    kubectl apply -f WorkloadCertificateConfig.yaml
    kubectl apply -f TrustConfig.yaml
    

Crear un servicio gRPC sin proxy con NEGs

Para la seguridad de PSM, necesitas un servidor gRPC sin proxy que pueda usar xDS para obtener la configuración de seguridad de Cloud Service Mesh. Este paso es similar a Configurar servicios de GKE con NEGs en la guía de configuración del balanceo de carga de PSM, pero se usa el servidor helloworld habilitado para xDS en el ejemplo de xDS del repositorio grpc-java en lugar de la imagen java-example-hostname.

Compila y ejecuta este servidor en un contenedor creado a partir de una imagen de openjdk:8-jdk. También puedes usar la función de NEG con nombre, que te permite especificar un nombre para el NEG. De esta forma, se simplifican los pasos posteriores, ya que tu despliegue conoce el nombre del NEG sin tener que buscarlo.

A continuación, se muestra un ejemplo completo de la especificación de Kubernetes del servidor gRPC. Ten en cuenta lo siguiente:

  • La especificación crea una cuenta de servicio de Kubernetes example-grpc-server que utiliza el pod del servidor gRPC.
  • La especificación usa el campo name en la anotación cloud.google.com/neg del servicio para especificar el nombre del NEG example-grpc-server.
  • La variable ${PROJNUM} representa el número de proyecto de tu proyecto.
  • La especificación usa la sección initContainers para ejecutar un generador de bootstrap que rellene el archivo de bootstrap que necesita la biblioteca gRPC sin proxy. Este archivo de arranque se encuentra en /tmp/grpc-xds/td-grpc-bootstrap.json en el contenedor del servidor gRPC llamado example-grpc-server.

Añade la siguiente anotación a tu especificación de Pod:

 annotations:
   security.cloud.google.com/use-workload-certificates: ""

Puedes ver la colocación correcta en las especificaciones completas que se indican a continuación.

Al crearse, cada Pod obtiene un volumen en /var/run/secrets/workload-spiffe-credentials. Este volumen contiene lo siguiente:

  • private_key.pem es una clave privada generada automáticamente.
  • certificates.pem es un paquete de certificados con formato PEM que se puede presentar a otro pod como cadena de certificados de cliente o usar como cadena de certificados de servidor.
  • ca_certificates.pem es un paquete de certificados con formato PEM que se usa como ancla de confianza al validar la cadena de certificados de cliente presentada por otro pod o la cadena de certificados de servidor recibida al conectarse a otro pod.

Ten en cuenta que ca_certificates.pem contiene certificados del dominio de confianza local de las cargas de trabajo, que es el grupo de cargas de trabajo del clúster.

El certificado de hoja de certificates.pem contiene la siguiente afirmación de identidad SPIFFE en texto sin formato:

spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT

En esta aserción:

  • WORKLOAD_POOL es el nombre del grupo de cargas de trabajo del clúster.
  • NAMESPACE es el espacio de nombres de tu cuenta de servicio de Kubernetes.
  • KUBERNETES_SERVICE_ACCOUNT es el nombre de tu cuenta de servicio de Kubernetes.

Las siguientes instrucciones para tu idioma crean la especificación que se usará en este ejemplo.

Java

  1. Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crea la especificación:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: openjdk:8-jdk
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 800m
               memory: 512Mi
             requests:
               cpu: 100m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

C++

  1. Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crea la especificación:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: phusion/baseimage:18.04-1.0.0
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 8
               memory: 8Gi
             requests:
               cpu: 300m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

Python

  1. Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crea la especificación:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: phusion/baseimage:18.04-1.0.0
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 8
               memory: 8Gi
             requests:
               cpu: 300m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

Go

  1. Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crea la especificación:

    cat << EOF > example-grpc-server.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: example-grpc-server
     namespace: default
     annotations:
       iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
     annotations:
       cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
    spec:
     ports:
     - name: helloworld
       port: 8080
       protocol: TCP
       targetPort: 50051
     selector:
       k8s-app: example-grpc-server
     type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: example-grpc-server
     namespace: default
     labels:
       k8s-app: example-grpc-server
    spec:
     replicas: 1
     selector:
       matchLabels:
         k8s-app: example-grpc-server
     strategy: {}
     template:
       metadata:
         annotations:
            security.cloud.google.com/use-workload-certificates: ""
         labels:
           k8s-app: example-grpc-server
       spec:
         containers:
         - image: golang:1.16-alpine
           imagePullPolicy: IfNotPresent
           name: example-grpc-server
           command:
           - /bin/sleep
           - inf
           env:
           - name: GRPC_XDS_BOOTSTRAP
             value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
           ports:
           - protocol: TCP
             containerPort: 50051
           resources:
             limits:
               cpu: 8
               memory: 8Gi
             requests:
               cpu: 300m
               memory: 512Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/grpc-xds/
         initContainers:
         - name: grpc-td-init
           image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
           imagePullPolicy: Always
           args:
           - --output
           - "/tmp/bootstrap/td-grpc-bootstrap.json"
           - --node-metadata=app=helloworld
           resources:
             limits:
               cpu: 100m
               memory: 100Mi
             requests:
               cpu: 10m
               memory: 100Mi
           volumeMounts:
           - name: grpc-td-conf
             mountPath: /tmp/bootstrap/
         serviceAccountName: example-grpc-server
         volumes:
         - name: grpc-td-conf
           emptyDir:
             medium: Memory
    EOF
    

    Completa el proceso de la siguiente manera.

  1. Aplica la especificación:

    kubectl apply -f example-grpc-server.yaml
    
  2. Asigna los roles necesarios a la cuenta de servicio:

    gcloud iam service-accounts add-iam-policy-binding \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \
      ${PROJNUM}-compute@developer.gserviceaccount.com
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \
      --role roles/trafficdirector.client
    
  3. Ejecuta estos comandos para comprobar que el servicio y el pod se han creado correctamente:

    kubectl get deploy/example-grpc-server
    kubectl get svc/example-grpc-server
    
  4. Verifica que el nombre del NEG sea correcto:

    gcloud compute network-endpoint-groups list \
        --filter "name=example-grpc-server" --format "value(name)"
    

    Se espera que el comando anterior devuelva el nombre del NEG example-grpc-server.

Configurar Cloud Service Mesh con componentes de Google Cloud balanceo de carga

Los pasos de esta sección son similares a los de Configurar Cloud Service Mesh con componentes de balanceo de carga, pero hay algunos cambios, como se describe en las siguientes secciones.

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

Cuando el servidor gRPC está configurado para usar mTLS, las comprobaciones de estado de gRPC no funcionan porque el cliente de comprobación de estado no puede presentar un certificado de cliente válido a los servidores. Puedes hacerlo de dos formas:

En el primer enfoque, el servidor crea un puerto de servicio adicional que se designa como puerto de comprobación del estado. Se adjunta a un servicio de comprobación del estado especial, como texto sin formato o TLS a ese puerto.

El servidor de ejemplo de xDS helloworld usa PORT_NUMBER + 1 como puerto de comprobación del estado de texto sin formato. En el ejemplo se usa el puerto 50052 para la comprobación del estado porque 50051 es el puerto del servidor de aplicaciones gRPC.

En el segundo enfoque, se configura la comprobación del estado para que solo compruebe la conectividad TCP al puerto de servicio de la aplicación. Esta opción solo comprueba la conectividad y también genera tráfico innecesario al servidor cuando no se completan las negociaciones TLS. Por este motivo, te recomendamos que uses el primer método.

  1. Crea la comprobación del estado. Ten en cuenta que la comprobación del estado no se inicia hasta que crees e inicies el servidor.

    • Si vas a crear un puerto de servicio designado para las comprobaciones del estado (que es el método que recomendamos), usa este comando:

      gcloud compute health-checks create grpc grpc-gke-helloworld-hc \
       --enable-logging --port 50052
      
    • Si vas a crear una comprobación del estado TCP, lo cual no te recomendamos, usa este comando:

      gcloud compute health-checks create tcp grpc-gke-helloworld-hc \
      --use-serving-port
      
  2. Crea el cortafuegos. Asegúrate de que el valor de --target-tags coincida con el valor que has proporcionado para --tags en la sección Crear o actualizar un clúster de GKE.

    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-50052
    
  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. Asocia el NEG 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 ${ZONE} \
       --balancing-mode RATE \
       --max-rate-per-endpoint 5
    

Crear el mapa de reglas de enrutamiento

Es similar a la forma en que crea un mapa de reglas de enrutamiento en Configuración de Cloud Service Mesh con Google Kubernetes Engine y servicios de gRPC sin proxy.

  1. Crea la asignación de URLs:

    gcloud compute url-maps create grpc-gke-url-map \
       --default-service grpc-gke-helloworld-service
    
  2. Añade el comparador de rutas al mapa de URLs:

    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
    

Configurar Cloud Service Mesh con seguridad de gRPC sin proxy

En este ejemplo se muestra cómo configurar mTLS en el cliente y en el servidor.

Formato de las referencias de la política

Ten en cuenta el siguiente formato obligatorio para hacer referencia a las políticas de TLS de servidor y de TLS de cliente:

projects/PROJECT_ID/locations/global/[serverTlsPolicies|clientTlsPolicies]/[server-tls-policy|client-mtls-policy]

Por ejemplo:

projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy

Configurar mTLS en el lado del servidor

Primero, crea una política de TLS de servidor. La política pide al lado del servidor de gRPC que use la configuración del complemento certificateProvicerInstance identificada por el nombre google_cloud_private_spiffe para el certificado de identidad, que forma parte de serverCertificate. La sección mtlsPolicy indica la seguridad de mTLS y usa el mismo google_cloud_private_spiffe que la configuración del complemento para clientValidationCa, que es la especificación del certificado raíz (de validación).

A continuación, crea una política de endpoint. Esto especifica que un backend, por ejemplo, un servidor gRPC que usa el puerto 50051 con ninguna o cualquier etiqueta de metadatos, recibe la política de TLS de servidor adjunta llamada server-mtls-policy. Para especificar las etiquetas de metadatos, usa MATCH_ALL. Crea la política de endpoint con un archivo temporal ep-mtls-psms.yaml que contenga los valores del recurso de política de endpoint con la política que ya has definido.

  1. Crea un archivo temporal server-mtls-policy.yaml en el directorio actual con los valores del recurso de política TLS del servidor:

    name: "projects/${PROJECT_ID}/locations/global/serverTlsPolicies/server-mtls-policy"
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    mtlsPolicy:
      clientValidationCa:
      - certificateProviderInstance:
          pluginInstance: google_cloud_private_spiffe
    
  2. Crea un recurso de política de TLS de servidor llamado server-mtls-policy importando el archivo temporal server-mtls-policy.yaml:

    gcloud network-security server-tls-policies import server-mtls-policy \
      --source=server-mtls-policy.yaml --location=global
    
  3. Crea la política de endpoint creando el archivo temporal ep-mtls-psms.yaml:

    name: "ep-mtls-psms"
    type: "GRPC_SERVER"
    serverTlsPolicy: "projects/${PROJECT_ID}/locations/global/serverTlsPolicies/server-mtls-policy"
    trafficPortSelector:
      ports:
      - "50051"
    endpointMatcher:
      metadataLabelMatcher:
        metadataLabelMatchCriteria: "MATCH_ALL"
        metadataLabels:
        - labelName: app
          labelValue: helloworld
    
  4. Crea el recurso de política de endpoint importando el archivo ep-mtls-psms.yaml:

    gcloud beta network-services endpoint-policies import ep-mtls-psms \
      --source=ep-mtls-psms.yaml --location=global
    

Configurar mTLS en el lado del cliente

La política de seguridad del lado del cliente se adjunta al servicio de backend. Cuando un cliente accede a un backend (el servidor gRPC) a través del servicio de backend, la política de seguridad del lado del cliente adjunta se envía al cliente.

  1. Crea el contenido del recurso de la política de TLS de cliente en un archivo temporal llamado client-mtls-policy.yaml en el directorio actual:

    name: "client-mtls-policy"
    clientCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    serverValidationCa:
    - certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. Crea el recurso de política de TLS de cliente llamado client-mtls-policy importando el archivo temporal client-mtls-policy.yaml:

    gcloud network-security client-tls-policies import client-mtls-policy \
      --source=client-mtls-policy.yaml --location=global
    
  3. Crea un fragmento en un archivo temporal para hacer referencia a esta política y añade detalles sobre subjectAltNames en el mensaje SecuritySettings, como en el ejemplo siguiente. Sustituye ${PROJECT_ID} por el valor del ID de tu proyecto, que es el valor de la variable de entorno ${PROJECT_ID} que se ha descrito anteriormente. Ten en cuenta que example-grpc-server en subjectAltNames es el nombre de la cuenta de servicio de Kubernetes que se usa para el pod del servidor gRPC en la especificación de la implementación.

    if [ -z "$PROJECT_ID" ] ; then echo Please make sure PROJECT_ID is set. ; fi
    cat << EOF > client-security-settings.yaml
    securitySettings:
      clientTlsPolicy: projects/${PROJECT_ID}/locations/global/clientTlsPolicies/client-mtls-policy
      subjectAltNames:
        - "spiffe://${PROJECT_ID}.svc.id.goog/ns/default/sa/example-grpc-server"
    EOF
    
  4. Añade el mensaje securitySettings al servicio backend que ya has creado. Con estos pasos se exporta el contenido del servicio de backend actual, se añade el mensaje del cliente securitySetting y se vuelve a importar el nuevo contenido para actualizar el servicio de backend.

    gcloud compute backend-services export grpc-gke-helloworld-service --global \
      --destination=/tmp/grpc-gke-helloworld-service.yaml
    
    cat /tmp/grpc-gke-helloworld-service.yaml client-security-settings.yaml \
      >/tmp/grpc-gke-helloworld-service1.yaml
    
    gcloud compute backend-services import grpc-gke-helloworld-service --global \
      --source=/tmp/grpc-gke-helloworld-service1.yaml -q
    

Verificar la configuración

La configuración de Cloud Service Mesh ya está completa, incluida la seguridad del lado del servidor y del cliente. A continuación, prepara y ejecuta las cargas de trabajo del servidor y del cliente. Con esto se completa el ejemplo.

Crear un cliente gRPC sin proxy

Este paso es similar al de la sección anterior Crear un servicio gRPC sin proxy. Utilizas el cliente helloworld habilitado para xDS del directorio de ejemplo de xDS en el repositorio grpc-java. Compila y ejecuta el cliente en un contenedor creado a partir de una imagen de openjdk:8-jdk. La especificación de Kubernetes del cliente de gRPC hace lo siguiente.

  • Crea una cuenta de servicio de Kubernetes example-grpc-client que usa el pod del cliente gRPC.
  • ${PROJNUM} representa el número de proyecto de tu proyecto y debe sustituirse por el número real.

Añade la siguiente anotación a tu especificación de Pod:

  annotations:
    security.cloud.google.com/use-workload-certificates: ""

Al crearse, cada Pod obtiene un volumen en /var/run/secrets/workload-spiffe-credentials. Este volumen contiene lo siguiente:

  • private_key.pem es una clave privada generada automáticamente.
  • certificates.pem es un paquete de certificados con formato PEM que se puede presentar a otro pod como cadena de certificados de cliente o usar como cadena de certificados de servidor.
  • ca_certificates.pem es un paquete de certificados con formato PEM que se usa como ancla de confianza al validar la cadena de certificados de cliente presentada por otro pod o la cadena de certificados de servidor recibida al conectarse a otro pod.

Ten en cuenta que ca_certificates.pem contiene los certificados raíz del dominio de confianza local de las cargas de trabajo, que es el grupo de cargas de trabajo del clúster.

El certificado de hoja de certificates.pem contiene la siguiente afirmación de identidad SPIFFE en texto sin formato:

spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT

En esta aserción:

  • WORKLOAD_POOL es el nombre del grupo de cargas de trabajo del clúster.
  • NAMESPACE es el nombre de tu cuenta de servicio de Kubernetes.
  • KUBERNETES_SERVICE_ACCOUNT es el espacio de nombres de tu cuenta de servicio de Kubernetes.

Las siguientes instrucciones para tu idioma crean la especificación que se usará en este ejemplo.

Java

  1. Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crea la siguiente especificación:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: openjdk:8-jdk
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 800m
                memory: 512Mi
              requests:
                cpu: 100m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

C++

  1. Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crea la siguiente especificación:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: phusion/baseimage:18.04-1.0.0
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 8
                memory: 8Gi
              requests:
                cpu: 300m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

Python

  1. Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crea la siguiente especificación:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: phusion/baseimage:18.04-1.0.0
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 8
                memory: 8Gi
              requests:
                cpu: 300m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

Go

  1. Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:

    if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
    
  2. Crea la siguiente especificación:

    cat << EOF > example-grpc-client.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: example-grpc-client
      namespace: default
      annotations:
        iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-grpc-client
      namespace: default
      labels:
        k8s-app: example-grpc-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: example-grpc-client
      strategy: {}
      template:
        metadata:
          annotations:
            security.cloud.google.com/use-workload-certificates: ""
          labels:
            k8s-app: example-grpc-client
        spec:
          containers:
          - image: golang:1.16-alpine
            imagePullPolicy: IfNotPresent
            name: example-grpc-client
            command:
            - /bin/sleep
            - inf
            env:
            - name: GRPC_XDS_BOOTSTRAP
              value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 8
                memory: 8Gi
              requests:
                cpu: 300m
                memory: 512Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/grpc-xds/
          initContainers:
          - name: grpc-td-init
            image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
            imagePullPolicy: Always
            args:
            - --output
            - "/tmp/bootstrap/td-grpc-bootstrap.json"
            resources:
              limits:
                cpu: 100m
                memory: 100Mi
              requests:
                cpu: 10m
                memory: 100Mi
            volumeMounts:
            - name: grpc-td-conf
              mountPath: /tmp/bootstrap/
          serviceAccountName: example-grpc-client
          volumes:
          - name: grpc-td-conf
            emptyDir:
              medium: Memory
    EOF
    

Completa el proceso de la siguiente manera.

  1. Aplica la especificación:

    kubectl apply -f example-grpc-client.yaml
    
  2. Asigna los roles necesarios a la cuenta de servicio:

    gcloud iam service-accounts add-iam-policy-binding \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \
      ${PROJNUM}-compute@developer.gserviceaccount.com
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \
      --role roles/trafficdirector.client
    
  3. Comprueba que el pod del cliente se está ejecutando:

    kubectl get pods
    

    El comando devuelve un texto similar al siguiente:

    NAMESPACE   NAME                                    READY   STATUS    RESTARTS   AGE
    default     example-grpc-client-7c969bb997-9fzjv    1/1     Running   0          104s
    [..skip..]
    

Ejecutar el servidor

Compila y ejecuta el servidor helloworld habilitado para xDS en el pod de servidor que has creado anteriormente.

Java

  1. Obtén el nombre del pod creado para el servicio example-grpc-server:

    kubectl get pods | grep example-grpc-server
    

    Recibes comentarios como los siguientes:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Abre un shell en el pod del servidor:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. En el shell, comprueba que el archivo de arranque de /tmp/grpc-xds/td-grpc-bootstrap.json coincida con el esquema descrito en la sección Archivo de arranque.

  4. Descarga la versión 1.42.1 de gRPC Java y crea la aplicación de servidor xds-hello-world.

    curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz
    
    cd grpc-java-1.42.1/examples/example-xds
    
    ../gradlew --no-daemon installDist
    
  5. Ejecuta el servidor con la marca --xds-creds para indicar la seguridad habilitada para xDS, usa 50051 como puerto de escucha y xds-server como nombre de identificación del servidor:

    ./build/install/example-xds/bin/xds-hello-world-server --xds-creds 50051 xds-server
    
  6. Una vez que el servidor obtiene la configuración necesaria de Cloud Service Mesh, verás el siguiente resultado:

    Listening on port 50051
    plain text health service listening on port 50052
    

C++

  1. Obtén el nombre del pod creado para el servicio example-grpc-server:

    kubectl get pods | grep example-grpc-server
    

    Recibes comentarios como los siguientes:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Abre un shell en el pod del servidor:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. En el shell, comprueba que el archivo de arranque de /tmp/grpc-xds/td-grpc-bootstrap.json coincida con el esquema descrito en la sección Archivo de arranque.

  4. Descarga gRPC C++ y crea la aplicación de servidor xds-hello-world.

    apt-get update -y && \
            apt-get install -y \
                build-essential \
                clang \
                python3 \
                python3-dev
    
    curl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz
    
    cd grpc-master
    
    tools/bazel build examples/cpp/helloworld:xds_greeter_server
    
  5. Ejecuta el servidor con 50051 como puerto de escucha y xds_greeter_server como nombre de identificación del servidor:

    bazel-bin/examples/cpp/helloworld/xds_greeter_server --port=50051 --maintenance_port=50052 --secure
    

    Para ejecutar el servidor sin credenciales, puedes especificar lo siguiente:

    bazel-bin/examples/cpp/helloworld/xds_greeter_server --nosecure
    
  6. Una vez que el servidor obtiene la configuración necesaria de Cloud Service Mesh, verás el siguiente resultado:

    Listening on port 50051
    plain text health service listening on port 50052
    

Python

  1. Obtén el nombre del pod creado para el servicio example-grpc-server:

    kubectl get pods | grep example-grpc-server
    

    Recibes comentarios como los siguientes:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Abre un shell en el pod del servidor:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
    
  3. En el shell, comprueba que el archivo de arranque de /tmp/grpc-xds/td-grpc-bootstrap.json coincida con el esquema descrito en la sección Archivo de arranque.

  4. Descarga gRPC Python versión 1.41.0 y crea la aplicación de ejemplo.

    apt-get update -y
    
    apt-get install -y python3 python3-pip
    
    curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz
    
    cd grpc-1.41.x/examples/python/xds/
    
    python3 -m virtualenv venv
    
    source venv/bin/activate
    
    python3 -m pip install -r requirements.txt
    

  5. Ejecuta el servidor con la marca --xds-creds para indicar que la seguridad está habilitada para xDS. Usa 50051 como puerto de escucha.

    python3 server.py 50051 --xds-creds
    
  6. Una vez que el servidor obtiene la configuración necesaria de Cloud Service Mesh, verás el siguiente resultado:

    2021-05-06 16:10:34,042: INFO     Running with xDS Server credentials
    2021-05-06 16:10:34,043: INFO     Greeter server listening on port 50051
    2021-05-06 16:10:34,046: INFO     Maintenance server listening on port 50052
    

Go

  1. Obtén el nombre del pod creado para el servicio example-grpc-server:

    kubectl get pods | grep example-grpc-server
    

    Recibes comentarios como los siguientes:

    default    example-grpc-server-77548868d-l9hmf     1/1    Running   0     105s
    
  2. Abre un shell en el pod del servidor:

    kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/sh
    
  3. En el shell, comprueba que el archivo de arranque de /tmp/grpc-xds/td-grpc-bootstrap.json coincida con el esquema descrito en la sección Archivo de arranque.

  4. Descarga la versión 1.41.0 de gRPC Go y ve al directorio que contiene la aplicación de servidor xds-hello-world.

    apk add curl
    
    curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz
    
    cd grpc-go-1.42.0/examples/features/xds/server
    
    
  5. Compila y ejecuta el servidor con la marca --xds_creds para indicar la seguridad habilitada para xDS. Usa 50051 como puerto de escucha:

    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY="info" \
      go run main.go \
      -xds_creds \
      -port 50051
    
  6. Una vez que el servidor obtiene la configuración necesaria de Cloud Service Mesh, verás el siguiente resultado:

    Using xDS credentials...
    Serving GreeterService on 0.0.0.0:50051 and HealthService on 0.0.0.0:50052
    

El proceso de comprobación del estado tarda entre 3 y 5 minutos en mostrar que tu servicio está en buen estado después de que se inicie el servidor.

Ejecuta el cliente y verifica la configuración

Compila y ejecuta el cliente helloworld habilitado para xDS en el pod de cliente que has creado anteriormente.

Java

  1. Obtén el nombre del pod del cliente:

    kubectl get pods | grep example-grpc-client
    

    Recibes comentarios como este:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Abre un shell en el pod del cliente:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. En el shell de comandos, descarga la versión 1.42.1 de gRPC Java y crea la aplicación cliente xds-hello-world.

    curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz
    
    cd grpc-java-1.42.1/examples/example-xds
    
    ../gradlew --no-daemon installDist
    
  4. Ejecuta el cliente con la marca --xds-creds para indicar la seguridad habilitada para xDS, el nombre del cliente y la cadena de conexión de destino:

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

    Debería ver un resultado similar a este:

    Greeting: Hello xds-client, from xds-server
    

C++

  1. Obtén el nombre del pod del cliente:

    kubectl get pods | grep example-grpc-client
    

    Recibes comentarios como este:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Abre un shell en el pod del cliente:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. Una vez que estés en la shell, descarga gRPC C++ y compila la aplicación cliente xds-hello-world.

    apt-get update -y && \
            apt-get install -y \
                build-essential \
                clang \
                python3 \
                python3-dev
    
    curl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz
    
    cd grpc-master
    
    tools/bazel build examples/cpp/helloworld:xds_greeter_client
    
  4. Ejecuta el cliente con la marca --xds-creds para indicar la seguridad habilitada para xDS, el nombre del cliente y la cadena de conexión de destino:

    bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000
    

    Para ejecutar el cliente sin credenciales, usa lo siguiente:

    bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000 --nosecure
    

    Debería ver un resultado similar a este:

    Greeter received: Hello world
    

Python

  1. Obtén el nombre del pod del cliente:

    kubectl get pods | grep example-grpc-client
    

    Recibes comentarios como este:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Abre un shell en el pod del cliente:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  3. Una vez que estés en la shell, descarga la versión 1.41.0 de gRPC Python y compila la aplicación cliente de ejemplo.

    apt-get update -y
    apt-get install -y python3 python3-pip
    python3 -m pip install virtualenv
    curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz
    cd grpc-1.41.x/examples/python/xds/
    python3 -m virtualenv venv
    source venv/bin/activate
    python3 -m pip install -r requirements.txt
    
  4. Ejecuta el cliente con la marca --xds-creds para indicar la seguridad habilitada para xDS, el nombre del cliente y la cadena de conexión de destino:

    python3 client.py xds:///helloworld-gke:8000 --xds-creds
    

    Debería ver un resultado similar a este:

    Greeter client received: Hello you from example-host!
    

Go

  1. Obtén el nombre del pod del cliente:

    kubectl get pods | grep example-grpc-client
    

    Recibes comentarios como este:

    default    example-grpc-client-7c969bb997-9fzjv     1/1    Running   0     105s
    
  2. Abre un shell en el pod del cliente:

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/sh
    
  3. Una vez que estés en la shell, descarga gRPC Go versión 1.42.0 y ve al directorio que contiene la aplicación xds-hello-world cliente.

    apk add curl
    
    curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz
    
    cd grpc-go-1.42.0/examples/features/xds/client
    
  4. Compila y ejecuta el cliente con la marca --xds_creds para indicar la seguridad habilitada para xDS, el nombre del cliente y la cadena de conexión de destino:

    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY="info" \
      go run main.go \
      -xds_creds \
      -name xds-client \
      -target xds:///helloworld-gke:8000
    

    Debería ver un resultado similar a este:

    Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
    

Configurar el acceso a nivel de servicio con una política de autorización

Se requiere la compatibilidad con gRFC A41 para la compatibilidad con la política de autorización. Puedes encontrar las versiones de idioma necesarias en GitHub.

Sigue estas instrucciones para configurar el acceso a nivel de servicio con políticas de autorización. Antes de crear políticas de autorización, lee la advertencia de la sección Restringir el acceso mediante la autorización.

Para que sea más fácil verificar la configuración, crea un nombre de host adicional que el cliente pueda usar para hacer referencia al servicio helloworld-gke.

gcloud compute url-maps add-host-rule grpc-gke-url-map \
   --path-matcher-name grpc-gke-path-matcher \
   --hosts helloworld-gke-noaccess:8000

En las siguientes instrucciones se crea una política de autorización que permite las solicitudes enviadas por la cuenta example-grpc-client en la que el nombre de host es helloworld-gke:8000 y el puerto es 50051.

gcloud

  1. Crea una política de autorización creando un archivo llamado helloworld-gke-authz-policy.yaml.

    action: ALLOW
    name: helloworld-gke-authz-policy
    rules:
    - sources:
      - principals:
        - spiffe://PROJECT_ID.svc.id.goog/ns/default/sa/example-grpc-client
      destinations:
      - hosts:
        - helloworld-gke:8000
        ports:
        - 50051
    
  2. Importa la política.

    gcloud network-security authorization-policies import \
      helloworld-gke-authz-policy \
      --source=helloworld-gke-authz-policy.yaml \
      --location=global
    
  3. Actualiza la política de endpoint para que haga referencia a la nueva política de autorización añadiendo lo siguiente al archivo ep-mtls-psms.yaml.

    authorizationPolicy: projects/${PROJECT_ID}/locations/global/authorizationPolicies/helloworld-gke-authz-policy
    

    La política de endpoints ahora especifica que tanto mTLS como la política de autorización deben aplicarse a las solicitudes entrantes a los pods cuyos archivos de arranque de gRPC contengan la etiqueta app:helloworld.

  4. Importa la política:

    gcloud network-services endpoint-policies import ep-mtls-psms \
      --source=ep-mtls-psms.yaml --location=global
    

Validar la política de autorización

Sigue estas instrucciones para confirmar que la política de autorización funciona correctamente.

Java

  1. Abre una shell en el pod de cliente que has usado anteriormente.

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  2. En el shell de comandos, ejecuta los siguientes comandos para validar la configuración.

    cd grpc-java-1.42.1/examples/example-xds
    ./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \
          xds:///helloworld-gke:8000
    

    Debería ver un resultado similar a este:

    Greeting: Hello xds-client, from xds-server
    
  3. Vuelve a ejecutar el cliente con el nombre del servidor alternativo. Ten en cuenta que este es un caso de error. La solicitud no es válida porque la política de autorización solo permite el acceso al nombre de host helloworld-gke:8000.

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

    Debería ver un resultado similar a este:

    WARNING: RPC failed: Status{code=PERMISSION_DENIED}
    

    Si no ves este resultado, es posible que la política de autorización aún no esté en uso. Espera unos minutos y vuelve a intentar todo el proceso de verificación.

Go

  1. Abre una shell en el pod de cliente que has usado anteriormente.

    kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
    
  2. En el shell de comandos, ejecuta los siguientes comandos para validar la configuración.

    cd grpc-go-1.42.0/examples/features/xds/client
    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY="info" \
      go run main.go \
      -xds_creds \
      -name xds-client \
      -target xds:///helloworld-gke:8000
    

    Debería ver un resultado similar a este:

    Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
    
  3. Vuelve a ejecutar el cliente con el nombre del servidor alternativo. Ten en cuenta que este es un caso de error. La solicitud no es válida porque la política de autorización solo permite el acceso al nombre de host helloworld-gke:8000.

    GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY="info" \
      go run main.go \
      -xds_creds \
      -name xds-client \
      -target xds:///helloworld-gke-noaccess:8000
    

    Debería ver un resultado similar a este:

    could not greet: rpc error: code = PermissionDenied desc = Incoming RPC is not allowed: rpc error: code = PermissionDenied desc = incoming RPC did not match an allow policy
    exit status 1
    

    Si no ves este resultado, es posible que la política de autorización aún no esté en uso. Espera unos minutos y vuelve a intentar todo el proceso de verificación.

Usar TLS en lugar de mTLS

Para usar TLS en este ejemplo, solo tienes que hacer un pequeño cambio.

  1. En ServerTlsPolicy, suelta mtlsPolicy:

    cat << EOF > server-tls-policy.yaml
    name: "server-tls-policy"
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    EOF
    
  2. Usa esta política en el EndpointPolicy:

    cat << EOF > ep-tls-psms.yaml
    name: "ep-mtls-psms"
    type: "GRPC_SERVER"
    serverTlsPolicy: "projects/${PROJECT_ID}/locations/global/serverTlsPolicies/server-tls-policy"
    trafficPortSelector:
      ports:
      - "50051"
    endpointMatcher:
      metadataLabelMatcher:
        metadataLabelMatchCriteria: "MATCH_ALL"
        metadataLabels: []
    EOF
    
  3. El ClientTlsPolicy de mTLS también funciona en el caso de TLS, pero se puede omitir la sección clientCertificate de la política, ya que no es necesaria para TLS:

    cat << EOF > client-tls-policy.yaml
    name: "client-tls-policy"
    serverValidationCa:
    - certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    EOF
    

Usar la seguridad de los servicios con el ejemplo de Wallet

En esta sección se ofrece una descripción general de alto nivel sobre cómo habilitar el ejemplo de Wallet con seguridad de servicio para Java, C++ y Go.

Java

Puedes encontrar el código fuente de ejemplo de Java en GitHub. El código ya usa las credenciales XdsChannel y XdsServer cuando configuras la seguridad sin proxy.

En estas instrucciones se describe cómo configurar el ejemplo de Wallet con Go. El proceso es similar para Java. En las instrucciones se usa una imagen de Docker que ya existe y que se obtiene del Google Cloud repositorio de contenedores.

Para crear el ejemplo, siga estas instrucciones:

  1. Clona el repositorio y obtén los archivos del directorio gRPC examples.
  2. Edita el archivo 00-common-env.sh. Comenta la línea que define el valor de WALLET_DOCKER_IMAGE en la imagen de Docker de Go y descomenta la línea que define el valor de WALLET_DOCKER_IMAGE en la imagen de Docker de Java.
  3. Crea y configura instancias de Cloud Router siguiendo las instrucciones de Crear y configurar instancias de Cloud Router o usando la función create_cloud_router_instances de la secuencia de comandos 10.apis.sh.
  4. Crea un clúster siguiendo las instrucciones del ejemplo hello world o con la función create_cluster de la secuencia de comandos 20-cluster.sh.
  5. Crea autoridades de certificación privadas siguiendo las instrucciones del Servicio de Autoridades de Certificación o con la secuencia de comandos 30-private-ca-setup.sh.
  6. Crea recursos de Kubernetes, incluidas cuentas de servicio, espacios de nombres, servicios de Kubernetes, NEGs y la implementación del lado del servidor para todos los servicios: account, stats, stats_premium, wallet_v1 y wallet_v2. Para ello, usa la secuencia de comandos 40-k8s-resources.sh.
  7. Para cada uno de los servicios que has creado, crea una comprobación del estado y un servicio de backend con create_health_check y create_backend_service en la secuencia de comandos 50-td-components.sh.
  8. Crea los componentes de enrutamiento de Cloud Service Mesh mediante create_routing_components en la secuencia de comandos 60-routing-components.sh.
  9. Crea los componentes de seguridad de la malla de servicios de Cloud para cada servicio de backend con create_security_components en la secuencia de comandos 70-security-components.sh.
  10. Crea la implementación del cliente de Wallet con create_client_deployment en el script 75-client-deployment.sh.
  11. Para verificar la configuración, inicia tu cliente tal como se describe en Verificar con clientes de grpc-wallet.

C++

Puedes encontrar el código fuente de ejemplo de C++ en GitHub. El código ya usa las credenciales XdsChannel y XdsServer cuando configuras la seguridad sin proxy.

En estas instrucciones se describe cómo configurar el ejemplo de Wallet con Go. El proceso es similar para C++. En las instrucciones se usa una imagen de Docker predefinida que se obtiene del Google Cloud repositorio de contenedores.

Para crear el ejemplo, siga estas instrucciones:

  1. Clona el repositorio y obtén los archivos del directorio gRPC examples.
  2. Edita el archivo 00-common-env.sh. Comenta la línea que asigna el valor de WALLET_DOCKER_IMAGE a la imagen de Docker de Go y descomenta la línea que asigna el valor de WALLET_DOCKER_IMAGE a la imagen de Docker de C++.
  3. Crea y configura instancias de Cloud Router siguiendo las instrucciones de Crear y configurar instancias de Cloud Router o usando la función create_cloud_router_instances de la secuencia de comandos 10.apis.sh.
  4. Crea un clúster siguiendo las instrucciones del ejemplo hello world o con la función create_cluster de la secuencia de comandos 20-cluster.sh.
  5. Crea autoridades de certificación privadas siguiendo las instrucciones del Servicio de Autoridades de Certificación o con la secuencia de comandos 30-private-ca-setup.sh.
  6. Crea recursos de Kubernetes, incluidas cuentas de servicio, espacios de nombres, servicios de Kubernetes, NEGs y la implementación del lado del servidor para todos los servicios: account, stats, stats_premium, wallet_v1 y wallet_v2. Para ello, usa la secuencia de comandos 40-k8s-resources.sh.
  7. Para cada uno de los servicios que has creado, crea una comprobación del estado y un servicio de backend con create_health_check y create_backend_service en la secuencia de comandos 50-td-components.sh.
  8. Crea los componentes de enrutamiento de Cloud Service Mesh mediante create_routing_components en la secuencia de comandos 60-routing-components.sh.
  9. Crea los componentes de seguridad de la malla de servicios de Cloud para cada servicio de backend con create_security_components en la secuencia de comandos 70-security-components.sh.
  10. Crea la implementación del cliente de Wallet con create_client_deployment en el script 75-client-deployment.sh.
  11. Para verificar la configuración, inicia tu cliente tal como se describe en Verificar con clientes de grpc-wallet.

Go

Puedes encontrar código fuente de ejemplo de Go en GitHub. El código ya usa las credenciales XdsChannel yXdsServer cuando configuras la seguridad sin proxy.

En las instrucciones se usa una imagen Docker predefinida que se obtiene del Google Cloud repositorio de contenedores.

Para crear el ejemplo, siga estas instrucciones:

  1. Clona el repositorio y obtén los archivos del directorio gRPC examples.
  2. Edita el archivo 00-common-env.sh para definir los valores correctos de las variables de entorno.
  3. Crea y configura instancias de Cloud Router siguiendo las instrucciones de Crear y configurar instancias de Cloud Router o usando la función create_cloud_router_instances de la secuencia de comandos 10.apis.sh.
  4. Crea un clúster siguiendo las instrucciones del ejemplo hello world o con la función create_cluster de la secuencia de comandos 20-cluster.sh.
  5. Crea autoridades de certificación privadas siguiendo las instrucciones del Servicio de Autoridades de Certificación o con la secuencia de comandos 30-private-ca-setup.sh.
  6. Crea recursos de Kubernetes, incluidas cuentas de servicio, espacios de nombres, servicios de Kubernetes, NEGs y la implementación del lado del servidor para todos los servicios: account, stats, stats_premium, wallet_v1 y wallet_v2. Para ello, usa la secuencia de comandos 40-k8s-resources.sh.
  7. Para cada uno de los servicios que has creado, crea una comprobación del estado y un servicio de backend con create_health_check y create_backend_service en la secuencia de comandos 50-td-components.sh.
  8. Crea los componentes de enrutamiento de Cloud Service Mesh mediante create_routing_components en la secuencia de comandos 60-routing-components.sh.
  9. Crea los componentes de seguridad de la malla de servicios de Cloud para cada servicio de backend con create_security_components en la secuencia de comandos 70-security-components.sh.
  10. Crea la implementación del cliente de Wallet con create_client_deployment en el script 75-client-deployment.sh.
  11. Para verificar la configuración, inicia tu cliente tal como se describe en Verificar con clientes de grpc-wallet.

Archivo de arranque

El proceso de configuración de esta guía usa un generador de bootstrap para crear el archivo de bootstrap necesario. En esta sección se proporciona información de referencia sobre el propio archivo de arranque.

El archivo de arranque contiene la información de configuración que necesita el código gRPC sin proxy, incluida la información de conexión del servidor xDS. El archivo de arranque contiene la configuración de seguridad que requiere la función de seguridad de gRPC sin proxy. El servidor gRPC requiere un campo adicional, como se describe en las secciones siguientes. Un archivo de arranque de ejemplo tiene este aspecto:

{
  "xds_servers": [
    {
      "server_uri": "trafficdirector.googleapis.com:443",
      "channel_creds": [
        {
          "type": "google_default"
        }
      ],
      "server_features": [
        "xds_v3"
      ]
    }
  ],
  "node": {
    "cluster": "cluster",
    "id": "projects/9876012345/networks/default/nodes/client1",
    "metadata": {
      "TRAFFICDIRECTOR_GCP_PROJECT_NUMBER": "9876012345",
      "TRAFFICDIRECTOR_NETWORK_NAME": "default",
      "INSTANCE_IP": "10.0.0.3"
    },
    "locality": {
      "zone": "us-central1-a"
    }
  },
  "server_listener_resource_name_template": "grpc/server?xds.resource.listening_address=%s",
  "certificate_providers": {
    "google_cloud_private_spiffe": {
      "plugin_name": "file_watcher",
      "config": {
        "certificate_file": "/var/run/secrets/workload-spiffe-credentials/certificates.pem",
        "private_key_file": "/var/run/secrets/workload-spiffe-credentials/private_key.pem",
        "ca_certificate_file": "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem",
        "refresh_interval": "600s"
      }
    }
  }
}

Actualizaciones del archivo de arranque del servicio de seguridad

Los siguientes campos reflejan las modificaciones relacionadas con la seguridad y el uso de xDS v3:

El campo id de node proporciona una identidad única al cliente de gRPC para Cloud Service Mesh. Debes proporcionar el Google Cloud número de proyecto y el nombre de la red con el ID de nodo en este formato:

projects/{project number}/networks/{network name}/nodes/[UNIQUE_ID]

Por ejemplo, para el proyecto con el número 1234 y la red predeterminada, sería:

projects/1234/networks/default/nodes/client1

El campo INSTANCE_IP es la dirección IP del pod o 0.0.0.0 para indicar INADDR_ANY. El servidor gRPC usa este campo para obtener el recurso Listener de Cloud Service Mesh para la seguridad del lado del servidor.

Campos de configuración de seguridad en el archivo de arranque

Clave JSON Tipo Valor Notas
server_listener_resource_name_template Cadena grpc/server?xds.resource.listening_address=%s Obligatorio para los servidores gRPC. gRPC usa este valor para componer el nombre del recurso para obtener el recurso `Listener` de Cloud Service Mesh para la seguridad del lado del servidor y otra configuración. gRPC usa este valor para formar la cadena del nombre del recurso.
certificate_providers Estructura JSON google_cloud_private_spiffe Obligatorio. El valor es una estructura JSON que representa un mapa de nombres a instancias de proveedor de certificados. Se usa una instancia de proveedor de certificados para obtener certificados de identidad y raíz. El archivo de arranque de ejemplo contiene un nombre: google_cloud_private_spiffe, con la estructura JSON de la instancia del proveedor de certificados como valor. Cada estructura JSON de instancia de proveedor de certificados tiene dos campos:
  • plugin_name. Valor obligatorio que identifica el complemento del proveedor de certificados que se va a usar, tal como requiere la arquitectura de complementos de gRPC para los proveedores de certificados. gRPC tiene compatibilidad integrada con el complemento de monitorización de archivos, que se usa en esta configuración. El nombre del complemento es file_watcher.
  • config. Valor obligatorio que identifica el blog de configuración JSON del complemento file_watcher. El esquema y el contenido dependen del complemento.

El contenido de la estructura JSON config del complemento file_watcher es el siguiente:

  • certificate_file: cadena obligatoria. Este valor es la ubicación del certificado de identidad.
  • private_key_file: cadena obligatoria. El valor es la ubicación del archivo de clave privada, que debe coincidir con el certificado de identidad.
  • ca_certificate_file: cadena obligatoria. El valor es la ubicación del certificado raíz, también conocido como paquete de confianza.
  • refresh_interval: cadena opcional. El valor indica el intervalo de actualización, especificado mediante la representación de cadena de la asignación JSON de una duración. El valor predeterminado es "600s", una duración de 10 minutos.

Generador de Bootstrap

La imagen del contenedor del generador de bootstrap está disponible en gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0. Su código fuente está disponible en https://github.com/GoogleCloudPlatform/traffic-director-grpc-bootstrap. Estas son las opciones de línea de comandos que se usan con más frecuencia:

  • --output: usa esta opción para especificar dónde se escribe el archivo de arranque de salida. Por ejemplo, el comando --output /tmp/bootstrap/td-grpc-bootstrap.json genera el archivo de arranque en /tmp/bootstrap/td-grpc-bootstrap.json en el sistema de archivos del pod.
  • --node-metadata: usa esta marca para rellenar los metadatos del nodo en el archivo de arranque. Esto es obligatorio cuando se usan matchers de etiquetas de metadatos en EndpointPolicy, donde Cloud Service Mesh usa los datos de etiquetas proporcionados en la sección de metadatos de nodos del archivo de arranque. El argumento se proporciona con el formato clave=valor. Por ejemplo: --node-metadata version=prod --node-metadata type=grpc

Estas opciones añaden lo siguiente a la sección de metadatos de nodos del archivo de arranque:

{
  "node": {
...
    "metadata": {
      "version": "prod",
      "type": "grpc",
...
    },
...
  },
...
}

Eliminar el despliegue

También puedes ejecutar estos comandos para eliminar el despliegue que has creado con esta guía.

Para eliminar el clúster, ejecuta este comando:

gcloud container clusters delete CLUSTER_NAME --zone ZONE --quiet

Para eliminar los recursos que has creado, ejecuta estos comandos:

gcloud compute backend-services delete grpc-gke-helloworld-service --global --quiet
cloud compute network-endpoint-groups delete example-grpc-server --zone ZONE --quiet
gcloud compute firewall-rules delete grpc-gke-allow-health-checks --quiet
gcloud compute health-checks delete grpc-gke-helloworld-hc --quiet
gcloud network-services endpoint-policies delete ep-mtls-psms \
    --location=global --quiet
gcloud network-security authorization-policies delete helloworld-gke-authz-policy \
   --location=global --quiet
gcloud network-security client-tls-policies delete client-mtls-policy \
    --location=global --quiet
gcloud network-security server-tls-policies delete server-tls-policy \
    --location=global --quiet
gcloud network-security server-tls-policies delete server-mtls-policy \
    --location=global --quiet

Solución de problemas

Sigue estas instrucciones para resolver los problemas con tu implementación de seguridad.

Las cargas de trabajo no pueden obtener la configuración de Cloud Service Mesh

Si aparece un error similar a este:

PERMISSION_DENIED: Request had insufficient authentication scopes.

Asegúrate de lo siguiente:

  • Has creado tu clúster de GKE con el argumento --scopes=cloud-platform argument.
  • Has asignado el roles/trafficdirector.client a tus cuentas de servicio de Kubernetes.
  • Has asignado el roles/trafficdirector.client a tu cuenta de servicio Google Cloud predeterminada (la cuenta ${GSA_EMAIL} de arriba).
  • Has habilitado el servicio (API) trafficdirector.googleapis.com.

Tu servidor gRPC no usa TLS ni mTLS aunque la configuración de Cloud Service Mesh sea correcta

Asegúrate de especificar GRPC_SERVER en la configuración de tus políticas de endpoint. Si has especificado SIDECAR_PROXY, gRPC ignora la configuración.

No puedes crear el clúster de GKE con la versión solicitada

Es posible que el comando de creación del clúster de GKE falle y se muestre un error similar a este:

Node version "1.20.5-gke.2000" is unsupported.

Asegúrate de usar el argumento --release-channel rapid en el comando de creación de clústeres. Debes usar el canal de lanzamiento rápido para obtener la versión correcta de esta actualización.

Aparece un error No usable endpoint

Si un cliente no puede comunicarse con el servidor debido a un error No usable endpoint, es posible que el comprobador de estado haya marcado los back-ends del servidor como no disponibles. Para comprobar el estado de los backends, ejecuta este comando gcloud:

gcloud compute backend-services get-health grpc-gke-helloworld-service --global

Si el comando devuelve el estado del backend como incorrecto, puede deberse a uno de estos motivos:

  • El cortafuegos no se ha creado o no contiene el intervalo de IPs de origen correcto.
  • Las etiquetas de destino de tu firewall no coinciden con las del clúster que has creado.

Las cargas de trabajo no pueden comunicarse en la configuración de seguridad

Si tus cargas de trabajo no pueden comunicarse después de configurar la seguridad de tu malla de servicios sin proxy, sigue estas instrucciones para determinar la causa.

  1. Inhabilita la seguridad sin proxy y elimina los problemas en los casos prácticos de balanceo de carga de malla de servicio sin proxy. Para inhabilitar la seguridad en la malla, haz una de las siguientes acciones:
    1. Usar credenciales de texto sin formato en el lado del cliente y del servidor
    2. No configures la seguridad del servicio de backend ni la política de endpoint en la configuración de Cloud Service Mesh.

Sigue los pasos que se indican en el artículo Solucionar problemas de implementaciones de malla de servicios de Cloud sin proxy, ya que no hay ninguna configuración de seguridad en tu implementación.

  1. Modifica tus cargas de trabajo para que usen credenciales xDS con texto sin formato o credenciales no seguras como credenciales alternativas. Mantén la configuración de Cloud Service Mesh con la seguridad inhabilitada, tal como se ha explicado anteriormente. En este caso, aunque gRPC permite que Cloud Service Mesh configure la seguridad, Cloud Service Mesh no envía información de seguridad, por lo que gRPC debería recurrir a las credenciales de texto sin formato (o no seguras), que deberían funcionar de forma similar al primer caso descrito anteriormente. Si este caso no funciona, haz lo siguiente:

    1. Aumenta el nivel de registro tanto en el cliente como en el servidor para que puedas ver los mensajes xDS intercambiados entre gRPC y Cloud Service Mesh.
    2. Asegúrate de que Cloud Service Mesh no tenga la seguridad habilitada en las respuestas de CDS y LDS que se envían a las cargas de trabajo.
    3. Asegúrate de que las cargas de trabajo no usen los modos TLS o mTLS en sus canales. Si ves algún mensaje de registro relacionado con negociaciones de TLS, comprueba el código fuente de tu aplicación y asegúrate de que no estés usando texto sin formato o inseguro como credenciales alternativas. Si el código fuente de la aplicación es correcto, puede que se trate de un error en la biblioteca gRPC.
  2. Para verificar que la integración del servicio de CA con GKE funciona correctamente en tu clúster de GKE, sigue los pasos de resolución de problemas que se indican en esa guía del usuario. Asegúrate de que los certificados y las claves que proporciona esa función estén disponibles en el directorio especificado, /var/run/secrets/workload-spiffe-credentials/.

  3. Habilita TLS (en lugar de mTLS) en tu malla, tal como se ha descrito anteriormente, y reinicia las cargas de trabajo del cliente y del servidor.

    1. Aumenta el nivel de registro tanto en el cliente como en el servidor para poder ver los mensajes xDS intercambiados entre gRPC y Cloud Service Mesh.
    2. Asegúrate de que Cloud Service Mesh haya habilitado la seguridad en las respuestas de CDS y LDS que se envían a las cargas de trabajo.

El cliente falla con un CertificateException y un mensaje Peer certificate SAN check failed

Esto indica que hay un problema con los valores de subjectAltNames en el mensaje SecuritySettings. Ten en cuenta que estos valores se basan en los servicios de Kubernetes que has creado para tu servicio backend. Por cada servicio de Kubernetes que hayas creado, hay un ID de SPIFFE asociado con este formato:

spiffe://${WORKLOAD_POOL}/ns/${K8S_NAMESPACE}/sa/${SERVICE_ACCOUNT}

Estos valores son los siguientes:

  • WORKLOAD_POOL: el pool de carga de trabajo del clúster, que es ${PROJECT_ID}.svc.id.goog
  • K8S_NAMESPACE: el espacio de nombres de Kubernetes que has usado en el despliegue del servicio.
  • SERVICE_ACCOUNT: la cuenta de servicio de Kubernetes que has usado en la implementación del servicio

Por cada servicio de Kubernetes que hayas asociado a tu servicio de backend como grupo de endpoints de red, asegúrate de haber calculado correctamente el ID de SPIFFE y de haberlo añadido al campo subjectAltNames del mensaje SecuritySettings.

Las aplicaciones no pueden usar los certificados mTLS con tu biblioteca gRPC

Si tus aplicaciones no pueden usar los certificados mTLS con tu biblioteca gRPC, haz lo siguiente:

  1. Verifica que la especificación del pod contenga la security.cloud.google.com/use-workload-certificatesanotación que se describe en Crear un servicio gRPC sin proxy con NEGs.

  2. Verifica que se pueda acceder a los archivos que contienen la cadena de certificados junto con el certificado de hoja, la clave privada y los certificados de CA de confianza en las siguientes rutas desde el Pod:

    1. Cadena de certificados junto con el certificado de hoja: "/var/run/secrets/workload-spiffe-credentials/certificates.pem"
    2. Clave privada: "/var/run/secrets/workload-spiffe-credentials/private_key.pem"
    3. Paquete de AC: "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem"
  3. Si los certificados del paso anterior no están disponibles, haz lo siguiente:

      gcloud privateca subordinates describe SUBORDINATE_CA_POOL_NAME 
    --location=LOCATION

    1. Verifica que el plano de control de GKE tenga el enlace de rol de IAM correcto, lo que le da acceso a Servicio de Autoridades de Certificación:

      # Get the IAM policy for the CA
      gcloud privateca roots get-iam-policy ROOT_CA_POOL_NAME
      
      # Verify that there is an IAM binding granting access in the following format
      - members:
      - serviceAccount:service-projnumber@container-engine-robot.iam.gserviceaccount.com
      role: roles/privateca.certificateManager
      
      # Where projnumber is the project number (e.g. 2915810291) for the GKE cluster.
      
    2. Comprueba que el certificado no haya caducado. Esta es la cadena de certificados y el certificado de hoja en /var/run/secrets/workload-spiffe-credentials/certificates.pem. Para comprobarlo, ejecuta este comando:

      cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
      

    3. Para comprobar que tu aplicación admite el tipo de clave, ejecuta este comando:

      cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
      

    4. Verifica que tu aplicación Java gRPC tenga lo siguiente keyAlgorithm en el archivo YAML WorkloadCertificateConfig:

      keyAlgorithm:
        rsa:
          modulusSize: 4096
    
  4. Verifica que la CA usa la misma familia de claves que la clave del certificado.

El cliente, el servidor o el peer rechazan el certificado de una aplicación

  1. Verifica que la aplicación del otro extremo usa el mismo paquete de confianza para verificar el certificado.
  2. Comprueba que el certificado en uso no haya caducado (cadena de certificados junto con el certificado de hoja: "/var/run/secrets/workload-spiffe-credentials/certificates.pem").

Los pods permanecen en estado pendiente

Si los pods permanecen en estado pendiente durante el proceso de configuración, aumenta los recursos de CPU y memoria de los pods en la especificación de tu implementación.

No se puede crear un clúster con la marca --enable-mesh-certificates

Asegúrate de que estás usando la versión más reciente de la CLI de gcloud:

gcloud components update

Ten en cuenta que la marca --enable-mesh-certificates solo funciona con gcloud beta.

Los pods no se inician

Es posible que los pods que usan certificados de malla de GKE no se inicien si falla el aprovisionamiento de certificados. Esto puede ocurrir en situaciones como las siguientes:

  • La configuración de WorkloadCertificateConfig o TrustConfig no es correcta o falta.
  • No se aprueban las CSRs.

Para comprobar si el aprovisionamiento de certificados está fallando, consulta los eventos de Pod.

  1. Comprueba el estado de tu Pod:

    kubectl get pod -n POD_NAMESPACE POD_NAME
    

    Haz los cambios siguientes:

    • POD_NAMESPACE: el espacio de nombres de tu pod.
    • POD_NAME: el nombre de tu Pod.
  2. Para consultar los eventos recientes de tu Pod, sigue estos pasos:

    kubectl describe pod -n POD_NAMESPACE POD_NAME
    
  3. Si el aprovisionamiento de certificados falla, verás un evento con Type=Warning, Reason=FailedMount y From=kubelet, así como un campo Message que empieza por MountVolume.SetUp failed for volume "gke-workload-certificates". El campo Message contiene información para solucionar problemas.

    Events:
      Type     Reason       Age                From       Message
      ----     ------       ----               ----       -------
      Warning  FailedMount  13s (x7 over 46s)  kubelet    MountVolume.SetUp failed for volume "gke-workload-certificates" : rpc error: code = Internal desc = unable to mount volume: store.CreateVolume, err: unable to create volume "csi-4d540ed59ef937fbb41a9bf5380a5a534edb3eedf037fe64be36bab0abf45c9c": caPEM is nil (check active WorkloadCertificateConfig)
    
  4. Consulta los siguientes pasos para solucionar problemas si tus pods no se inician debido a objetos mal configurados o a CSRs rechazadas.

WorkloadCertificateConfig o TrustConfig no están configurados correctamente

Asegúrate de que has creado los objetos WorkloadCertificateConfig y TrustConfig correctamente. Puedes diagnosticar errores de configuración en cualquiera de estos objetos con kubectl.

  1. Recupera el estado actual.

    Para WorkloadCertificateConfig:

    kubectl get WorkloadCertificateConfig default -o yaml
    

    Para TrustConfig:

    kubectl get TrustConfig default -o yaml
    
  2. Inspecciona el resultado del estado. Un objeto válido tendrá una condición con type: Ready y status: "True".

    status:
      conditions:
      - lastTransitionTime: "2021-03-04T22:24:11Z"
        message: WorkloadCertificateConfig is ready
        observedGeneration: 1
        reason: ConfigReady
        status: "True"
        type: Ready
    

    En el caso de los objetos no válidos, se muestra status: "False". Los campos reason y message contienen información adicional para solucionar problemas.

No se aprueban las CSRs

Si algo va mal durante el proceso de aprobación de la CSR, puede consultar los detalles del error en las condiciones type: Approved y type: Issued de la CSR.

  1. Lista las CSRs pertinentes con kubectl:

    kubectl get csr \
      --field-selector='spec.signerName=spiffe.gke.io/spiffe-leaf-signer'
    
  2. Elige un CSR que sea Approved y no Issued, o que no sea Approved.

  3. Obtén los detalles de la CSR seleccionada con kubectl:

    kubectl get csr CSR_NAME -o yaml
    

    Sustituye CSR_NAME por el nombre que hayas elegido para la CSR.

Una CSR válida tiene una condición con type: Approved y status: "True", y un certificado válido en el campo status.certificate:

status:
  certificate: <base64-encoded data>
  conditions:
  - lastTransitionTime: "2021-03-04T21:58:46Z"
    lastUpdateTime: "2021-03-04T21:58:46Z"
    message: Approved CSR because it is a valid SPIFFE SVID for the correct identity.
    reason: AutoApproved
    status: "True"
    type: Approved

La información para solucionar problemas relacionados con CSRs no válidos aparece en los campos message y reason.

Faltan certificados en los pods

  1. Obtén las especificaciones del pod:

    kubectl get pod -n POD_NAMESPACE POD_NAME -o yaml
    

    Haz los cambios siguientes:

    • POD_NAMESPACE: el espacio de nombres de tu pod.
    • POD_NAME: el nombre de tu Pod.
  2. Verifica que la especificación del pod contenga la security.cloud.google.com/use-workload-certificates anotación descrita en Configurar pods para recibir credenciales de mTLS.

  3. Verifica que el controlador de admisión de certificados de malla de GKE haya insertado correctamente un volumen de controlador CSI de tipo workloadcertificates.security.cloud.google.com en la especificación de tu pod:

    volumes:
    ...
    -csi:
      driver: workloadcertificates.security.cloud.google.com
      name: gke-workload-certificates
    ...
    
  4. Comprueba si hay un volumen montado en cada uno de los contenedores:

    containers:
    - name: ...
      ...
      volumeMounts:
      - mountPath: /var/run/secrets/workload-spiffe-credentials
        name: gke-workload-certificates
        readOnly: true
      ...
    
  5. Verifica que los siguientes paquetes de certificados y la clave privada estén disponibles en las siguientes ubicaciones del pod:

    • Paquete de cadena de certificados: /var/run/secrets/workload-spiffe-credentials/certificates.pem
    • Clave privada: /var/run/secrets/workload-spiffe-credentials/private_key.pem
    • Paquete de anclas de confianza de la AC: /var/run/secrets/workload-spiffe-credentials/ca_certificates.pem
  6. Si los archivos no están disponibles, sigue estos pasos:

    1. Recupera la instancia de CA Service (Preview) del clúster:

      kubectl get workloadcertificateconfigs default -o jsonpath '{.spec.certificateAuthorityConfig.certificateAuthorityServiceConfig.endpointURI}'
      
    2. Consulta el estado de la instancia del servicio de AC (vista previa):

      gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \
        --location ISSUING_CA_LOCATION
      

      Haz los cambios siguientes:

      • ISSUING_CA_TYPE: el tipo de CA emisora, que debe ser subordinates o roots.
      • ISSUING_CA_NAME: el nombre de la autoridad de certificación emisora.
      • ISSUING_CA_LOCATION: la región de la entidad certificadora emisora.
    3. Obtén la política de gestión de identidades y accesos de la CA raíz:

      gcloud privateca roots get-iam-policy ROOT_CA_NAME
      

      Sustituye ROOT_CA_NAME por el nombre de tu AC raíz.

    4. En la política de gestión de identidades y accesos, comprueba que existe el privateca.auditor enlace de política:

      ...
      - members:
        - serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
        role: roles/privateca.auditor
      ...
      

      En este ejemplo, PROJECT_NUMBER es el número de proyecto de tu clúster.

    5. Obtén la política de gestión de identidades y accesos de la CA subordinada:

      gcloud privateca subordinates get-iam-policy SUBORDINATE_CA_NAME
      

      Sustituye SUBORDINATE_CA_NAME por el nombre de la AC subordinada.

    6. En la política de gestión de identidades y accesos, comprueba que existe el enlace de política privateca.certificateManager:

      ...
      - members:
        - serviceAccount: service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
        role: roles/privateca.certificateManager
      ...
      

      En este ejemplo, PROJECT_NUMBER es el número de proyecto de tu clúster.

Las aplicaciones no pueden usar las credenciales de mTLS emitidas

  1. Comprueba que el certificado no haya caducado:

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  2. Comprueba que el tipo de clave que has usado sea compatible con tu aplicación.

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
    
  3. Comprueba que la AC emisora use la misma familia de claves que la clave del certificado.

    1. Obtén el estado de la instancia del servicio de CA (vista previa):

      gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \
        --location ISSUING_CA_LOCATION
      

      Haz los cambios siguientes:

      • ISSUING_CA_TYPE: el tipo de CA emisora, que debe ser subordinates o roots.
      • ISSUING_CA_NAME: el nombre de la autoridad de certificación emisora.
      • ISSUING_CA_LOCATION: la región de la entidad certificadora emisora.
    2. Comprueba que el keySpec.algorithm de la salida sea el mismo algoritmo de clave que has definido en el manifiesto YAML WorkloadCertificateConfig. La salida tiene este aspecto:

      config:
        ...
        subjectConfig:
          commonName: td-sub-ca
          subject:
            organization: TestOrgLLC
          subjectAltName: {}
      createTime: '2021-05-04T05:37:58.329293525Z'
      issuingOptions:
        includeCaCertUrl: true
      keySpec:
        algorithm: RSA_PKCS1_2048_SHA256
       ...
      

Se rechazan los certificados

  1. Verifica que la aplicación del otro extremo usa el mismo paquete de confianza para verificar el certificado.
  2. Comprueba que el certificado no haya caducado:

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  3. Verifica que el código de cliente, si no usa la API de recarga de credenciales de gRPC Go, actualice periódicamente las credenciales del sistema de archivos.

  4. Verifica que tus cargas de trabajo estén en el mismo dominio de confianza que tu CA. Los certificados de malla de GKE admiten la comunicación entre cargas de trabajo de un único dominio de confianza.

Limitaciones

La seguridad de los servicios de Cloud Service Mesh solo se admite en GKE. No puedes implementar la seguridad de los servicios con Compute Engine.

Cloud Service Mesh no admite situaciones en las que haya dos o más recursos de EndpointPolicy que coincidan por igual con un endpoint. Por ejemplo, dos políticas con las mismas etiquetas y puertos, o dos o más políticas con etiquetas diferentes que coincidan por igual con las etiquetas de un endpoint. Para obtener más información sobre cómo se asocian las políticas de puntos finales con las etiquetas de un punto final, consulta las APIs de EndpointPolicy.EndpointMatcher.MetadataLabelMatcher. En estas situaciones, Cloud Service Mesh no genera ninguna configuración de seguridad a partir de las políticas en conflicto.