Usa GKE Dataplane V2

En esta página, se explica cómo habilitar y solucionar problemas de GKE Dataplane V2 para clústeres de Google Kubernetes Engine (GKE).

GKE Dataplane V2 siempre está habilitado en los clústeres nuevos de Autopilot. Si tienes problemas para usar GKE Dataplane V2, ve a Solución de problemas.

Antes de comenzar

Antes de comenzar, asegúrate de haber realizado las siguientes tareas:

  • Habilita la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Si deseas usar Google Cloud CLI para esta tarea, instala y, luego, inicializa gcloud CLI. Si ya instalaste la gcloud CLI, ejecuta el comando gcloud components update para obtener la versión más reciente. Es posible que las versiones anteriores de gcloud CLI no admitan la ejecución de los comandos que se indican en este documento.

Roles obligatorios

Para obtener los permisos que necesitas para crear un clúster de GKE, pídele a tu administrador que te otorgue el rol de IAM de administrador de clústeres de Kubernetes Engine (container.clusterAdmin) en tu proyecto. Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

También puedes obtener los permisos necesarios a través de roles personalizados o cualquier otro rol predefinido.

Crea un clúster de GKE con GKE Dataplane V2

Solo puedes habilitar GKE Dataplane V2 cuando creas un clúster de GKE nuevo. No puedes modificar este parámetro de configuración para un clúster existente.

Para crear un clúster estándar que use GKE Dataplane V2, selecciona una de las siguientes opciones:

Console

  1. En la consola de Google Cloud , ve a la página Crea un clúster de Kubernetes.

    Ir a Crea un clúster de Kubernetes

  2. En el menú de navegación, haz clic en Herramientas de redes.

  3. Expande la sección Interfaz de red de contenedor (CNI).

  4. Selecciona la casilla de verificación Dataplane V2.

  5. Haz clic en Crear.

gcloud

Ejecuta el siguiente comando:

gcloud container clusters create CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-dataplane-v2

Reemplaza lo siguiente:

  • CLUSTER_NAME: Es un nombre para tu clúster nuevo.
  • CONTROL_PLANE_LOCATION: Es una ubicación para el plano de control del clúster.

API

Para crear un clúster nuevo con GKE Dataplane V2, especifica el campo datapathProvider en el objeto networkConfig, en la solicitud create del clúster.

En el siguiente fragmento de código JSON, se muestra la configuración necesaria para habilitar GKE Dataplane V2:

"cluster":{
    "networkConfig":{
      "datapathProvider":"ADVANCED_DATAPATH"
    }
}

Soluciona problemas con GKE Dataplane V2

En esta sección, se muestra cómo investigar y resolver problemas con GKE Dataplane V2.

  1. Confirma que GKE Dataplane V2 esté habilitado:

    kubectl -n kube-system get pods -l k8s-app=cilium -o wide
    

    Si GKE Dataplane V2 está en ejecución, el resultado incluye Pods con el prefijo anetd-. anetd es el controlador de herramientas de redes para GKE Dataplane V2.

  2. Si el problema es con los servicios o la aplicación de la política de red, verifica los registros del Pod anetd: Usa los siguientes selectores de registros en Cloud Logging:

    resource.type="k8s_container"
    labels."k8s-pod/k8s-app"="cilium"
    resource.labels.cluster_name="CLUSTER_NAME"
    
  3. Si falla la creación de un Pod, revisa los registros de kubelet para obtener pistas. Usa los siguientes selectores de registros en Cloud Logging:

    resource.type="k8s_node"
    log_name=~".*/logs/kubelet"
    resource.labels.cluster_name="CLUSTER_NAME"
    

    Reemplaza CLUSTER_NAME por el nombre del clúster o quítalo por completo para ver los registros de todos los clústeres.

  4. Si los Pods de anetd no se están ejecutando, examina el ConfigMap de cilium-config para detectar cualquier modificación. Evita modificar los campos existentes dentro de este ConfigMap, ya que estos cambios pueden desestabilizar el clúster y perturbar anetd. El ConfigMap se parchea de nuevo al estado predeterminado solo si se le agregan campos nuevos. No se aplican parches a los cambios en los campos existentes, y recomendamos no cambiar ni personalizar el ConfigMap.

Problemas conocidos

Cuando usas GKE Dataplane V2, es posible que encuentres los siguientes problemas conocidos.

Tiempos de espera de conexión para Pods no listos

Cuando un Pod no está listo, las conexiones al Service asociado pueden agotarse. Este es el comportamiento esperado de GKE Dataplane V2 y difiere de kube-proxy, que puede devolver un error connection refused más rápido.

El filtrado de etiquetas relevantes para la identidad de Cilium no tiene efecto y los Pods se atascan en el estado ContainerCreating

Versiones afectadas: 1.34 y 1.35

En los clústeres de GKE Dataplane V2, el uso de emergencia del filtrado de etiquetas pertinentes para la identidad a través de ConfigMap kube-system/cilium-config-emergency-override no se aplica correctamente en las versiones afectadas.

Este enfoque limita las etiquetas de Pod que se usan para la generación de identidades de Cilium.

Cuando no hay otros mecanismos disponibles para evitar o quitar los valores o las claves de etiquetas de alta cardinalidad de los Pods (por ejemplo, cuando una herramienta o un framework aplican etiquetas), se puede usar el filtrado de etiquetas pertinentes para la identidad para excluir las claves de etiquetas del cálculo de la identidad de Cilium. Para obtener más información sobre cómo configurar estas reglas, consulta Identity-Relevant Labels en la documentación de Cilium.

En el caso de las versiones de GKE afectadas, las identidades de Cilium creadas por el operador siguen incluyendo las etiquetas excluidas.

Síntomas

  • Es posible que los Pods con etiquetas que se deben filtrar para la generación de identidades de Cilium no se inicien y queden atascados en el estado ContainerCreating. Es posible que los eventos de Pod muestren errores de tiempo de espera:

      {"level":"warning", "msg":"Error changing endpoint identity", "error":"unable to resolve identity: timed out waiting for cilium-operator to allocate CiliumIdentity for key ...;, error: exponential backoff cancelled via context: context canceled", "k8sPodName":"...", "subsys":"endpoint"}
    
  • En lugar de compartir identidades basadas en etiquetas filtradas, los Pods con valores de etiquetas únicos siguen generando identidades de Cilium únicas. Esto puede generar un aumento considerable de identidades, lo que podría agotar las identidades de Cilium disponibles (hasta un límite de 65,536) y causar problemas de escalabilidad.

Versiones corregidas

Para solucionar este problema, actualiza tu clúster a una de las siguientes versiones de GKE:

  • 1.34.6-gke.1307000 o versiones posteriores
  • 1.35.2-gke.1962000 o versiones posteriores

Solución alternativa

Como solución alternativa, aplica las reglas de filtrado de etiquetas al campo data.labels en el ConfigMap cilium-config principal y quítalas de cilium-config-emergency-override. Esta situación persiste durante las operaciones del plano de control, como las actualizaciones, ya que GKE conserva las modificaciones del usuario en los campos que no administra dentro del ConfigMap de cilium-config.

  1. Quita la clave labels de la sección data del ConfigMap de cilium-config-emergency-override si existe.
  2. Edita el ConfigMap cilium-config agregando o modificando la clave labels en la sección data. Por ejemplo, para evitar que se usen etiquetas llamadas uuid para la generación de identidades, haz lo siguiente:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: cilium-config
      namespace: kube-system
    data:
      # ... other existing keys
      labels: "!uuid"
      # ... other existing keys
    
  3. Reinicia anet-operator en el plano de control actualizando el plano de control a la misma versión que está ejecutando. Esto obliga al operador a reiniciar y volver a cargar su configuración:

    gcloud container clusters upgrade CLUSTER_NAME \
        --location CLUSTER_LOCATION \
        --project PROJECT_ID \
        --cluster-version $(gcloud container clusters describe CLUSTER_NAME --location CLUSTER_LOCATION --project PROJECT_ID --format="value(currentMasterVersion)") \
        --master
    
  4. Después de que se reinicie el plano de control, reinicia el DaemonSet anetd para asegurarte de que los agentes de nodos también apliquen los cambios necesarios:

    kubectl rollout restart daemonset anetd -n kube-system
    

Problemas de conectividad intermitentes relacionados con conflictos de rango de NodePort en clústeres de GKE Dataplane V2

En los clústeres de GKE Dataplane V2, pueden ocurrir problemas de conectividad intermitentes para el tráfico enmascarado o con el uso de puertos efímeros. Estos problemas se deben a posibles conflictos de puertos con el rango de NodePort reservado y, por lo general, ocurren en las siguientes situaciones:

  • ip-masq-agent personalizado: Si usas un ip-masq-agent personalizado (versión 2.10 o posterior), en el que el clúster tiene servicios de NodePort o de balanceador de cargas, es posible que observes problemas de conectividad intermitente debido a su conflicto con el rango de NodePort. A partir de la versión 2.10 y versiones posteriores, ip-masq-agent tiene el argumento --random-fully implementado internamente de forma predeterminada. Para mitigar esto, configura de forma explícita --random-fully=false (aplicable desde la versión 2.11) en los argumentos de la configuración de ip-masq-agent. Para obtener más información sobre la configuración, consulta Configura un agente de enmascaramiento de IP en clústeres de Standard.

  • Superposición del rango de puertos efímeros: Si el rango de puertos efímeros definido por net.ipv4.ip_local_port_range en tus nodos de GKE se superpone con el rango de NodePort (30000-32767), también puede generar problemas de conectividad. Para evitar este problema, asegúrate de que estos dos rangos no se superpongan.

Revisa la configuración de ip-masq-agent y la configuración del rango de puertos efímero para asegurarte de que no entren en conflicto con el rango de NodePort. Si tienes problemas de conectividad intermitentes, considera estas posibles causas y ajusta tu configuración según corresponda.

Problemas de conectividad con hostPort en clústeres de GKE Dataplane V2

Versiones afectadas de GKE: 1.29 y versiones posteriores

En los clústeres que usan GKE Dataplane V2, es posible que se produzcan errores de conectividad cuando el tráfico se dirige a la IP:Puerto de un nodo, en el que el puerto es el hostPort definido en el Pod. Estos problemas surgen en dos situaciones principales:

  • Nodos con hostPort detrás de un balanceador de cargas de red de transferencia:

    hostPort vincula un Pod al puerto de un nodo específico, y un balanceador de cargas de red de transferencia distribuye el tráfico entre todos los nodos. Cuando expones Pods a Internet con hostPort y un balanceador de cargas de red de transferencia, es posible que el balanceador de cargas envíe tráfico a un nodo en el que no se ejecuta el Pod, lo que provoca errores de conexión. Esto se debe a una limitación conocida en GKE Dataplane V2, en la que el tráfico del balanceador de cargas de red de transferencia no se reenvía de manera coherente a los Pods hostPort.

    Solución alternativa: Cuando expongas hostPorts de un Pod en el nodo con un balanceador de cargas de red de transferencia, especifica la dirección IP interna o externa del balanceador de cargas de red en el campo hostIP del Pod.

    ports:
    - containerPort: 62000
      hostPort: 62000
      protocol: TCP
      hostIP: 35.232.62.64
    - containerPort: 60000
      hostPort: 60000
      protocol: TCP
      hostIP: 35.232.62.64
      # Assuming 35.232.62.64 is the external IP address of a passthrough Network Load Balancer.
    
  • Conflicto de hostPort con el rango reservado NodePort:

    Si el hostPort de un Pod entra en conflicto con el rango de NodePort reservado (30000-32767), es posible que Cilium no pueda reenviar el tráfico al Pod. Este comportamiento se observó en las versiones de clúster 1.29 y posteriores, ya que Cilium ahora administra las capacidades de hostPort, lo que reemplaza el método anterior de Portmap. Este es un comportamiento esperado de Cilium y se menciona en su documentación pública.

No planeamos corregir estas limitaciones en versiones posteriores. La causa raíz de estos problemas se relaciona con el comportamiento de Cilium y está fuera del control directo de GKE.

Recomendación: Te recomendamos que migres a los servicios de NodePort en lugar de hostPort para mejorar la confiabilidad. NodePort Los servicios proporcionan capacidades similares.

Los rangos de puertos de las políticas de red no se aplican

Versiones afectadas de GKE: Anteriores a la 1.32

Si especificas el campo endPort en un objeto NetworkPolicy en un clúster que tiene habilitado GKE Dataplane V2 y ejecuta una versión de GKE anterior a la 1.32, Kubernetes ignorará el campo.

La API de Kubernetes NetworkPolicy te permite especificar un rango de puertos en los que Kubernetes aplica la política de red. Esta API es compatible con clústeres con la política de red Calico y con clústeres con GKE Dataplane V2 que ejecutan la versión 1.32 o posterior de GKE. La API no es compatible con los clústeres de GKE Dataplane V2 que ejecutan versiones anteriores a la 1.32.

Para verificar el comportamiento de tus objetos NetworkPolicy, vuelve a leerlos después de escribirlos en el servidor de la API. Si el objeto todavía contiene el campo endPort, Kubernetes aplica la función. Si falta el campo endPort, Kubernetes no aplica la función. El objeto almacenado en el servidor de la API es la fuente de información de la política de red.

Para obtener más información, consulta KEP-2079: Política de red que admite rangos de puertos.

Versiones fijas

Para resolver este problema, actualiza tu clúster a la versión 1.32 o posterior de GKE.

La política de red descarta una conexión debido a una búsqueda de seguimiento de conexión incorrecta

Cuando un Pod de cliente se conecta consigo mismo a través de un Service o la dirección IP virtual de un balanceador de cargas de red de transferencia interno, el paquete de respuesta no se identifica como parte de una conexión existente debido a una búsqueda de conntrack incorrecta en el plano de datos. Esto significa que una política de red que restringe el tráfico de entrada para el Pod se aplica de forma incorrecta en el paquete.

El impacto de este problema depende de la cantidad de Pods configurados para el Service. Por ejemplo, si el Service tiene 1 Pod de backend, la conexión siempre falla. Si el Service tiene 2 Pods de backend, la conexión falla el 50% del tiempo.

Versiones fijas

Para solucionar este problema, actualiza tu clúster a una de las siguientes versiones de GKE:

  • 1.28.3-gke.1090000 o superior.

Soluciones alternativas

Puedes mitigar este problema si configuras port y containerPort en el manifiesto del Service para que tengan el mismo valor.

Pérdida de paquetes para los flujos de conexión en horquilla

Cuando un Pod crea una conexión TCP a sí misma usando un Service, de modo que el Pod sea la fuente y el destino de la conexión, el seguimiento de conexión de eBPF de GKE Dataplane V2 realiza un seguimiento incorrecto de los estados de conexión, lo que genera entradas de conntrack filtradas.

Cuando se filtra una tupla de conexión (protocolo, dirección IP de origen o destino, y puerto de origen o destino), las conexiones nuevas que usan la misma tupla de conexión pueden provocar que se pierdan paquetes de retorno.

Versiones fijas

Para solucionar este problema, actualiza tu clúster a una de las siguientes versiones de GKE:

  • 1.28.3-gke.1090000 o superior
  • 1.27.11-gke.1097000 o superior

Soluciones alternativas

Aplica una de las siguientes soluciones:

  • Habilita la reutilización de TCP (keep-alive) para las aplicaciones que se ejecutan en Pods que pueden comunicarse con sí mismas a través de un Service. Esto evita que se emita la marca TCP FIN y se evite que se filtre la entrada de conntrack.

  • Cuando uses conexiones de corta duración, expón el Pod con un balanceador de cargas de proxy, como Gateway, para exponer el Service. Esto hace que el destino de la solicitud de conexión se establezca en la dirección IP del balanceador de cargas, lo que evita que GKE Dataplane V2 realice SNAT a la dirección IP de bucle invertido.

La actualización del plano de control de GKE provoca un bloqueo del pod anetd

Cuando actualizas un clúster de GKE que tiene habilitado GKE Dataplane V2 (ruta de datos avanzada) de la versión 1.27 a la 1.28, es posible que se produzca un interbloqueo. Es posible que las cargas de trabajo experimenten interrupciones debido a la imposibilidad de finalizar Pods antiguos o programar componentes necesarios, como anetd.

Causa

El proceso de actualización del clúster aumenta el requisito de recursos para los componentes de GKE Dataplane V2. Este aumento puede generar contención de recursos, lo que interrumpe la comunicación entre el complemento de la interfaz de red de contenedores (CNI) de Cilium y el daemon de Cilium.

Síntomas

Es posible que veas los siguientes síntomas:

  • Los Pods anetd permanecen atascados en el estado Pending.
  • Los Pods de carga de trabajo se atascan en el estado Terminating.
  • Errores que indican fallas de comunicación de Cilium, como failed to connect to Cilium daemon.
  • Se producen errores durante la limpieza de los recursos de red para los espacios de aislamiento de Pods, por ejemplo:

    1rpc error: code = Unknown desc = failed to destroy network for sandbox "[sandbox_id]": plugin type="cilium-cni" failed (delete): unable to connect to Cilium daemon... connection refused
    

Solución alternativa

Clústeres estándar: Para resolver el problema y permitir que se programe el Pod anetd, aumenta temporalmente los recursos asignables en el nodo afectado siguiendo estos pasos:

  1. Identifica el nodo afectado y verifica su CPU y memoria asignables:

    kubectl get nodes NODE_NAME -o json | jq '.status.allocatable | {cpu, memory}'
    
  2. Aumenta temporalmente la CPU y la memoria asignables:

    kubectl patch node NODE_NAME -p '{"status":{"allocatable":{"cpu":CPU_VALUE, "memory":MEMORY_VALUE}}}'
    

    Reemplaza lo siguiente:

    • NODE_NAME: Es el nombre del nodo afectado.
    • CPU_VALUE: Es el nuevo valor de la CPU. Agrega un búfer de 500m al valor de CPU actual identificado en el paso anterior. Por ejemplo, si el valor actual es 1500m, usa 2 (que es equivalente a 2000m).
    • MEMORY_VALUE: Es el valor de memoria nuevo. Agrega un búfer de 512Mi (que equivale a 0.5Gi) al valor de memoria actual identificado en el paso anterior. Por ejemplo, si el valor actual es 3.5Gi, usa 4Gi.

    Por ejemplo, para aumentar la CPU asignable a 2 y la memoria a 4Gi en el nodo gke-cluster-node-1, ejecuta el siguiente comando:

    kubectl patch node gke-cluster-node-1 -p '{"status":{"allocatable":{"cpu":"2", "memory":"4Gi"}}}'
    

Clústeres de Autopilot: Para resolver el problema de interbloqueo en los clústeres de Autopilot, libera recursos borrando a la fuerza el Pod afectado:

kubectl delete pod POD_NAME -n NAMESPACE --grace-period=0 --force

Reemplaza lo siguiente:

  • POD_NAME: el nombre del Pod.
  • NAMESPACE: Es el espacio de nombres del Pod.

Después de aumentar los recursos asignables en el nodo y cuando se complete la actualización de la versión 1.27 a la 1.28 de GKE, el Pod anetd se ejecutará en la versión más reciente.

Nodos en estado NodeNotReady debido a un error de containerID faltante

Cuando los clústeres se actualizan a la versión 1.35.1-gke.1616000 y versiones posteriores de GKE, es posible que los nodos ingresen de inmediato en un estado NodeNotReady si se habilitan GKE Dataplane V2 y Cloud Service Mesh.

Causa

A partir de la versión 1.35.1-gke.1616000 de GKE, los clústeres de GKE Dataplane V2 usan la versión 1.1.0 de CNI en sus archivos de configuración de CNI. Este cambio requiere que los complementos de CNI descendentes, como Istio administrado por Google, también admitan la versión 1.1.0 de CNI. Debido a una demora en el lanzamiento de Istio administrado, algunos clústeres aún no recibieron la versión compatible (1.23), lo que provocó la falla de inicialización.

Síntomas

Los nodos afectados se muestran de inmediato como NodeNotReady. El siguiente mensaje de error aparece en los registros de containerd:

NetworkPluginNotReady message:Network plugin returns error: missing containerID

Solución alternativa

Para mitigar el problema, cambia la versión del clúster afectado a una versión de GKE anterior a la 1.35.1-gke.1616000.

Interferencia de programas de eBPF personalizados

GKE usa programas eBPF para administrar las redes de GKE Dataplane V2. Si implementas programas de eBPF personalizados en interfaces de red de nodos administrados por GKE, estos programas pueden interferir con los programas de eBPF administrados por GKE y causar problemas de redes.

GKE no admite programas de eBPF personalizados conectados a las siguientes interfaces de red:

  • eth*
  • ens4
  • lo
  • cilium*
  • gke*
  • veth*

La presencia de programas eBPF personalizados en estas interfaces puede interferir con los programas anetd instalados por el agente de GKE Dataplane V2, lo que puede interrumpir las redes del clúster. Te recomendamos que quites de tu clúster los programas o las cargas de trabajo de eBPF personalizados que inserten esos programas.

Descubre programas de eBPF personalizados

Para descubrir programas eBPF personalizados que se ejecutan en nodos del clúster, puedes crear un DaemonSet configurado con el parámetro de configuración hostNetwork: true que usa bpftool para consultar esos programas eBPF:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: bpftool-logger
  labels:
    app: bpftool-logger
spec:
  selector:
    matchLabels:
      app: bpftool-logger
  template:
    metadata:
      labels:
        app: bpftool-logger
    spec:
      hostPID: true
      hostNetwork: true
      containers:
      - name: bpftool
        image: ubuntu:22.04
        securityContext:
          privileged: true
        env:
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        command:
        - /bin/bash
        - -c
        - |
          echo "Installing dependencies..."
          apt-get update -y > /dev/null 2>&1
          apt-get install -y curl tar > /dev/null 2>&1

          echo "Downloading and setting up bpftool..."
          curl -sL https://github.com/libbpf/bpftool/releases/download/v7.7.0/bpftool-v7.7.0-amd64.tar.gz | tar xz
          chmod +x bpftool
          mv bpftool /usr/local/bin/

          echo "========== $(date) | Node: ${NODE_NAME} =========="
          bpftool net | grep -E '^(eth|ens4|lo|cilium|gke|veth)' | grep -v ' cil_'
          sleep infinity
  1. Guarda el manifiesto como ebpf-discovery.yaml y aplica el DaemonSet:

    kubectl apply -f ebpf-discovery.yaml
    
  2. Espera a que los Pods se estén ejecutando:

    kubectl rollout status ds/bpftool-logger
    
  3. Revisa los registros de los Pods para descubrir programas eBPF:

    kubectl logs -l app=bpftool-logger
    
  4. Cuando termines, borra el DaemonSet:

    kubectl delete -f ebpf-discovery.yaml
    

¿Qué sigue?