Usar GKE Dataplane V2

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

Los nuevos clústeres de Autopilot tienen habilitado GKE Dataplane V2 en las versiones 1.22.7-gke.1500 y posteriores, y en las versiones 1.23.4-gke.1500 y posteriores. Si tienes problemas al usar Dataplane V2 de GKE, ve a la sección Solución de problemas.

Crear un clúster de GKE con GKE Dataplane V2

Puedes habilitar GKE Dataplane V2 al crear clústeres con GKE versión 1.20.6-gke.700 y posteriores mediante la CLI de gcloud o la API de GKE. También puedes habilitar GKE Dataplane V2 en Vista previa al crear clústeres con la versión 1.17.9 de GKE o una posterior.

Consola

Para crear un clúster con GKE Dataplane V2, realiza las siguientes tareas:

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

    Ir a Crear un clúster de Kubernetes

  2. En la sección Redes, marca la casilla Habilitar Dataplane V2. La opción Habilitar política de red de Kubernetes está inhabilitada cuando se selecciona Habilitar Dataplane V2 porque la aplicación de la política de red está integrada en GKE Dataplane V2.

  3. Haz clic en Crear.

gcloud

Para crear un clúster con GKE Dataplane V2, usa el siguiente comando:

gcloud container clusters create CLUSTER_NAME \
    --enable-dataplane-v2 \
    --enable-ip-alias \
    --release-channel CHANNEL_NAME \
    --location COMPUTE_LOCATION

Haz los cambios siguientes:

  • CLUSTER_NAME: el nombre del nuevo clúster.
  • CHANNEL_NAME: un canal de lanzamiento que incluya la versión 1.20.6-gke.700 o posterior de GKE. Si prefieres no usar un canal de lanzamiento, puedes usar la marca --cluster-version en lugar de --release-channel y especificar la versión 1.20.6-gke.700 o posterior.
  • COMPUTE_LOCATION: la ubicación de Compute Engine del nuevo clúster.

API

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

El siguiente fragmento de JSON muestra la configuración necesaria para habilitar Dataplane V2 de GKE:

"cluster":{
   "initialClusterVersion":"VERSION",
   "ipAllocationPolicy":{
      "useIpAliases":true
   },
   "networkConfig":{
      "datapathProvider":"ADVANCED_DATAPATH"
   },
   "releaseChannel":{
      "channel":"CHANNEL_NAME"
   }
}

Haz los cambios siguientes:

  • VERSION: la versión de tu clúster, que debe ser GKE 1.20.6-gke.700 o una posterior.
  • CHANNEL_NAME: un canal de lanzamiento que incluya la versión 1.20.6-gke.700 de GKE o una posterior.

Solucionar problemas con GKE Dataplane V2

En esta sección se explica 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 se está ejecutando GKE Dataplane V2, el resultado incluye pods con el prefijo anetd-. anetd es el controlador de redes de GKE Dataplane V2.

  2. Si el problema está relacionado con los servicios o la aplicación de la política de red, consulta los registros de anetdpod. Usa los siguientes selectores de registro en Cloud Logging:

    resource.type="k8s_container"
    labels."k8s-pod/k8s-app"="cilium"
    resource.labels.cluster_name="CLUSTER_NAME"
    
  3. Si no se pueden crear pods, consulta los registros de kubelet para obtener información. Usa los siguientes selectores de registro en Cloud Logging:

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

    Sustituye CLUSTER_NAME por el nombre del clúster o elimínalo por completo para ver los registros de todos los clústeres.

  4. Si los pods anetd no se están ejecutando, examina el ConfigMap cilium-config para ver si hay alguna modificación. No modifiques los campos de este ConfigMap, ya que estos cambios pueden desestabilizar el clúster e interrumpir anetd. El ConfigMap vuelve al estado predeterminado solo si se le añaden campos nuevos. Los cambios en los campos no se aplican y le recomendamos que no cambie ni personalice el ConfigMap.

Problemas conocidos

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

En los clústeres de GKE Dataplane V2, pueden producirse problemas de conectividad intermitentes con el tráfico enmascarado o con el uso de puertos efímeros. Estos problemas se deben a posibles conflictos de puertos con el intervalo NodePort reservado y suelen producirse en los siguientes casos:

  • Personalizado ip-masq-agent: si usas un ip-masq-agent personalizado (versión 2.10 o posterior) en el que el clúster tiene servicios NodePort o de balanceador de carga, es posible que observes problemas de conectividad intermitentes debido a su conflicto con el intervalo NodePort. Desde la versión 2.10 y posteriores, ip-masq-agent tiene el argumento --random-fully implementado de forma interna de forma predeterminada. Para evitarlo, define explícitamente --random-fully=false (aplicable desde la versión 2.11) en los argumentos de tu configuración de ip-masq-agent. Para obtener información sobre la configuración, consulta Configurar un agente de enmascaramiento de IP en clústeres estándar.

  • Solapamiento del intervalo de puertos efímeros: si el intervalo de puertos efímeros definido por net.ipv4.ip_local_port_range en tus nodos de GKE se solapa con el intervalo NodePort (30000-32767), también puede provocar problemas de conectividad. Para evitar este problema, asegúrese de que estos dos intervalos no se solapen.

Revisa la configuración de ip-masq-agent y los ajustes del intervalo de puertos efímeros para asegurarte de que no entran en conflicto con el intervalo de NodePort. Si tienes problemas de conectividad intermitentes, ten en cuenta estas posibles causas y ajusta tu configuración en consecuencia.

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

Versiones de GKE afectadas: 1.29 y posteriores

En los clústeres que usan GKE Dataplane V2, es posible que se produzcan fallos de conectividad cuando el tráfico se dirija a la dirección IP y el puerto de un nodo, donde el puerto es el hostPort definido en el pod. Estos problemas se producen en dos situaciones principales:

  • Nodos con hostPort detrás de un balanceador de carga de red con paso a través:

    hostPort vincula un pod al puerto de un nodo específico, y un balanceador de carga de red de transferencia directa distribuye el tráfico entre todos los nodos. Cuando expones pods a Internet mediante hostPort y un balanceador de carga de red de tipo pasarela, el balanceador de carga puede enviar tráfico a un nodo en el que no se esté ejecutando el pod, lo que provoca errores de conexión. Esto se debe a una limitación conocida de GKE Dataplane V2, donde el tráfico del balanceador de carga de red de transferencia no se reenvía de forma coherente a los pods de hostPort.

    Solución alternativa: Cuando expongas los hostPort de un pod en el nodo con un balanceador de carga de red de pases, especifica la dirección IP interna o externa del balanceador de carga 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.
    
  • hostPort conflicto con el intervalo reservado NodePort:

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

No tenemos previsto solucionar estas limitaciones en versiones posteriores. La causa principal de estos problemas está relacionada 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 a hostPort para mejorar la fiabilidad. NodePort Los servicios ofrecen funciones similares.

Los intervalos de puertos de la política de red no se aplican

Si especifica un campo endPort en una política de red de un clúster que tiene habilitado GKE Dataplane V2, no tendrá efecto.

A partir de GKE 1.22, la API de políticas de red de Kubernetes te permite especificar un intervalo de puertos en el que se aplica la política de red. Esta API se admite en clústeres con la política de red de Calico, pero no en clústeres con GKE Dataplane V2.

Puedes verificar el comportamiento de tus objetos NetworkPolicy leyéndolos después de escribirlos en el servidor de la API. Si el objeto sigue conteniendo el campo endPort, la función se aplica. Si falta el campo endPort, la función no se aplica. En todos los casos, el objeto almacenado en el servidor de la API es la fuente de información veraz de la política de red.

Para obtener más información, consulta KEP-2079: Network Policy to support Port Ranges (KEP-2079: política de red para admitir intervalos de puertos).

Los pods muestran el mensaje de error failed to allocate for range 0: no IP addresses available in range set

Versiones de GKE afectadas: de la 1.22 a la 1.25

Los clústeres de GKE que ejecutan grupos de nodos que usan containerd y tienen habilitado GKE Dataplane V2 pueden experimentar problemas de filtración de direcciones IP y agotar todas las direcciones IP de los pods de un nodo. Un pod programado en un nodo afectado muestra un mensaje de error similar al siguiente:

failed to allocate for range 0: no IP addresses available in range set: 10.48.131.1-10.48.131.62

Para obtener más información sobre el problema, consulta el problema #5768 de containerd.

Versiones corregidas

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

  • 1.22.17-gke.3100 o una versión posterior.
  • 1.23.16-gke.200 o una versión posterior.
  • 1.24.9-gke.3200 o una versión posterior.
  • 1.25.6-gke.200 o una versión posterior.

Soluciones alternativas para clústeres de GKE estándar

Puedes mitigar este problema eliminando las direcciones IP de los pods filtradas del nodo.

Para eliminar las direcciones IP de Pod filtradas, obtén las credenciales de autenticación del clúster y sigue estos pasos para limpiar un solo nodo, si conoces su nombre.

  1. Guarda la siguiente secuencia de comandos de shell en un archivo llamado cleanup.sh:

    for hash in $(sudo find /var/lib/cni/networks/gke-pod-network -iregex '/var/lib/cni/networks/gke-pod-network/[0-9].*' -exec head -n1 {} \;); do hash="${hash%%[[:space:]]}"; if [ -z $(sudo ctr -n k8s.io c ls | grep $hash | awk '{print $1}') ]; then sudo grep -ilr $hash /var/lib/cni/networks/gke-pod-network; fi; done | sudo xargs -r rm
    
  2. Ejecuta la secuencia de comandos en un nodo del clúster:

    gcloud compute ssh --zone "ZONE" --project "PROJECT" NODE_NAME --command "$(cat cleanup.sh)"
    

    Sustituye NODE_NAME por el nombre del nodo.

También puedes ejecutar una versión de DaemonSet de esta secuencia de comandos para que se ejecute en paralelo en todos los nodos a la vez:

  1. Guarda el siguiente manifiesto en un archivo llamado cleanup-ips.yaml:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: cleanup-ipam-dir
      namespace: kube-system
    spec:
      selector:
        matchLabels:
          name: cleanup-ipam
      template:
        metadata:
          labels:
            name: cleanup-ipam
        spec:
          hostNetwork: true
          securityContext:
            runAsUser: 0
            runAsGroup: 0
          containers:
          - name: cleanup-ipam
            image: gcr.io/gke-networking-test-images/ubuntu-test:2022
            command:
              - /bin/bash
              - -c
              - |
                while true; do
                for hash in $(find /hostipam -iregex '/hostipam/[0-9].*' -mmin +10 -exec head -n1 {} \; ); do
                hash="${hash%%[[:space:]]}"
                if [ -z $(ctr -n k8s.io c ls | grep $hash | awk '{print $1}') ]; then
                grep -ilr $hash /hostipam
                fi
                done | xargs -r rm
                echo "Done cleaning up /var/lib/cni/networks/gke-pod-network at $(date)"
                sleep 120s
                done
            volumeMounts:
            - name: host-ipam
              mountPath: /hostipam
            - name: host-ctr
              mountPath: /run/containerd
          volumes:
          - name: host-ipam
            hostPath:
              path: /var/lib/cni/networks/gke-pod-network
          - name: host-ctr
            hostPath:
              path: /run/containerd
    
  2. Ejecuta el daemonset en el clúster:

    kubectl apply -f cleanup-ips.yaml
    

    Para ejecutar este comando, debes tener acceso a kubectl como administrador del clúster.

  3. Consulta los registros del DaemonSet en ejecución:

    kubectl -n kube-system logs -l name=cleanup-ipam
    

Network Policy elimina una conexión debido a una búsqueda de seguimiento de conexiones incorrecta

Cuando un pod de cliente se conecta a sí mismo mediante un servicio o la dirección IP virtual de un balanceador de carga de red de transferencia interno, el paquete de respuesta no se identifica como parte de una conexión existente debido a una búsqueda incorrecta de conntrack en el plano de datos. Esto significa que una política de red que restringe el tráfico de entrada del pod se aplica incorrectamente al paquete.

El impacto de este problema depende del número de pods configurados para el servicio. Por ejemplo, si el servicio tiene un pod de backend, la conexión siempre falla. Si el servicio tiene dos pods backend, la conexión falla el 50% de las veces.

Versiones corregidas

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

  • 1.28.3-gke.1090000 o versiones posteriores.

Soluciones

Para mitigar este problema, configure los valores de port y containerPort en el manifiesto de servicio para que sean iguales.

Paquetes descartados en flujos de conexión en bucle

Cuando un pod crea una conexión TCP consigo mismo mediante un servicio, de forma que el pod es tanto el origen como el destino de la conexión, el seguimiento de conexiones eBPF de Dataplane V2 de GKE registra incorrectamente los estados de la conexión, lo que provoca que se filtren entradas de conntrack.

Cuando se ha filtrado una tupla de conexión (protocolo, IP de origen o destino y puerto de origen o destino), las nuevas conexiones que usen la misma tupla de conexión pueden provocar que se descarten los paquetes de retorno.

Versiones corregidas

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

  • 1.28.3-gke.1090000 o posterior
  • 1.27.11-gke.1097000 o versiones posteriores

Soluciones

Usa una de las siguientes soluciones alternativas:

  • Habilita la reutilización de TCP (keep-alives) para las aplicaciones que se ejecutan en pods que pueden comunicarse entre sí mediante un servicio. De esta forma, se evita que se emita la marca FIN de TCP y que se filtre la entrada de conntrack.

  • Cuando se usan conexiones de corta duración, expón el pod mediante un balanceador de carga de proxy, como Gateway, para exponer el servicio. De este modo, el destino de la solicitud de conexión se establece en la dirección IP del balanceador de carga, lo que impide que GKE Dataplane V2 realice SNAT en la dirección IP de bucle de retorno.

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

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 sufran 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 los requisitos de recursos de los componentes de GKE Dataplane V2. Este aumento puede provocar una contención de recursos, lo que interrumpe la comunicación entre el complemento de interfaz de red de contenedores (CNI) de Cilium y el daemon de Cilium.

Síntomas

Es posible que veas los siguientes síntomas:

  • Los anetd pods se quedan atascados en el estado Pending.
  • Los pods de carga de trabajo se bloquean en el estado Terminating.
  • Errores que indican fallos de comunicación de Cilium, como failed to connect to Cilium daemon.
  • Errores durante la limpieza de recursos de red de los sandboxes 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

Clústeres estándar: para resolver el problema y permitir que se programe el anetd pod, aumenta temporalmente los recursos asignables en el nodo afectado.

  1. Para identificar el nodo afectado y comprobar la CPU y la memoria asignables, ejecuta el siguiente comando:

    kubectl get nodes $NODE_NAME -o json | jq '.status.allocatable | {cpu, memory}'
    
  2. Para aumentar temporalmente la CPU y la memoria asignables, ejecuta el siguiente comando:

    kubectl patch
    

Clústeres de Autopilot: para resolver el problema de interbloqueo en los clústeres de Autopilot, libera recursos eliminando el pod afectado de forma forzada:

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

Haz los cambios siguientes:

  • POD_NAME: el nombre del pod.
  • NAMESPACE: el espacio de nombres del pod.

Después de aumentar los recursos asignables del 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.

Siguientes pasos