Herramientas de redes de pila doble IPv4/IPv6

Las redes de pila doble en Google Distributed Cloud permiten que tus clústeres acepten tráfico de dispositivos externos que usan IPv4 o IPv6. Los Pods y los nodos obtienen direcciones IPv4 e IPv6, y un Service de Kubernetes puede tener una dirección IPv4, una dirección IPv6 o ambas.

Los clústeres de pila doble siempre usan el modo plano para IPv6. Para IPv4, los clústeres de pila doble usan el modo isla de forma predeterminada, pero puedes configurar el modo plano en su lugar. Para crear un clúster de pila doble, la red subyacente debe tener habilitada la pila doble. No puedes iniciar un clúster de pila doble en una red IPv4 o IPv6 de pila única.

Antes de comenzar

Si los nodos del clúster ejecutan RedHat Enterprise Linux y tienen SELinux habilitado, en cada nodo, haz lo siguiente:

  • En /etc/firewalld/firewalld.conf, establece IPv6_rpfilter=no.

  • Ejecuta systemctl restart firewalld.

Descripción general de la creación de un clúster de pila doble

Puedes habilitar las herramientas de redes de pila doble cuando creas un clúster nuevo, pero no puedes habilitarlas en un clúster existente.

Sigue las instrucciones de uno de los documentos de creación de clústeres.

En tu archivo de configuración, incluye manifiestos para lo siguiente:

  • Un recurso de espacio de nombres
  • Un recurso de clúster
  • Uno o más recursos de NodePool
  • Uno o más recursos de ClusterCIDRConfig

Completa el manifiesto de espacio de nombres y los manifiestos de NodePool como lo harías para un clúster de pila única.

En el manifiesto del clúster, en clusterNetwork.services.cidrBlocks, especifica un rango CIDR IPv4 y un rango CIDR IPv6. Este es el criterio de habilitación para un clúster de pila doble. Es decir, si proporcionas rangos CIDR de Service para IPv4 e IPv6, tu clúster tendrá una red de pila doble.

En el manifiesto del clúster, en clusterNetwork.pods.cidrBlocks, especifica un rango CIDR de IPv4, pero no especifiques un rango CIDR de IPv6. Los rangos CIDR de IPv6 para Pods se especifican en los manifiestos de ClusterCIDRConfig.

Si usas el balanceo de cargas empaquetado, proporciona direcciones IPv4 e IPv6 en la sección loadBalancer.addressPools del manifiesto del clúster.

Los recursos ClusterCIDRConfig sirven para especificar rangos CIDR IPv4 e IPv6 para los Pods. Puedes usar un solo recurso ClusterCIDRConfig para especificar rangos CIDR que se apliquen a todo el clúster. Es decir, las direcciones IPv4 de Pod para todos los nodos se toman de un solo rango CIDR, y las direcciones IPv6 de Pod para todos los nodos se toman de un solo rango CIDR. También puedes usar varios recursos ClusterCIDRConfig para especificar rangos de CIDR que se apliquen a un grupo de nodos o un nodo en particular.

Accesibilidad para las direcciones IP del Pod

Un clúster de pila doble usa el modo plano para las herramientas de redes IPv6. El ejemplo que se proporciona en este documento es para un clúster que usa redes estáticas de modo plano para IPv6. Es decir, el clúster no está configurado para usar el protocolo de puerta de enlace de frontera (BGP).

Para un clúster que usa redes estáticas de modo plano, debes especificar las direcciones IP de los nodos y los Pods que forman parte de la misma subred. Esta configuración permite que los clientes fuera del clúster, pero en el mismo dominio de capa 2 que los nodos del clúster, envíen paquetes directamente a las direcciones IP de los Pods.

Por ejemplo, supongamos que los nodos del clúster y algunas otras máquinas están en el mismo dominio de capa 2. Esta es una forma en la que podrías especificar los rangos de direcciones:

ObjetivoRangoCantidad de direcciones
Dominio completo de capa 2fd12::/108220
Podsfd12::1:0/112216
Nodosfd12::2:0/112216
Otras máquinasfd12::3:0/112216
VIPfd12::4:0/112216

En el ejemplo anterior, estos son los puntos clave que debes comprender:

  • Todas las direcciones de nodos, Pods y máquinas están en el rango grande: fd12::/108.

  • Las direcciones IP de los Pods se encuentran en un subconjunto del rango grande.

  • Las direcciones IP de los nodos se encuentran en un subconjunto diferente del rango grande.

  • Las direcciones IP de otras máquinas se encuentran en un subconjunto diferente del rango grande.

  • Todos los rangos de subconjuntos son distintos entre sí.

En el ejemplo anterior, cada máquina del dominio de capa 2, incluidos los nodos del clúster, debe tener una regla de reenvío para el rango grande. Por ejemplo:

inet fd12::/108 scope global eth0

Ejemplo: Crea un clúster de pila doble

Cuando creas un clúster de pila doble, tienes varias opciones. Por ejemplo, podrías tener rangos CIDR para todo el clúster o rangos CIDR que se apliquen a grupos de nodos específicos. Podrías combinar una red IPv6 plana con una red IPv4 en modo de isla. O bien, tus redes IPv4 e IPv6 podrían ser planas. Puedes usar el balanceo de cargas agrupado o el balanceo de cargas manual.

En esta sección, se proporciona un ejemplo de cómo crear un clúster de pila doble. El clúster de este ejemplo tiene las siguientes características:

  • Una red IPv4 en modo isla
  • Una red IPv6 en modo plano
  • Un rango CIDR IPv4 para todo el clúster para los Pods
  • Un rango CIDR IPv6 para Pods en todo el clúster
  • Un rango CIDR IPv4 para los objetos Service en todo el clúster
  • Un rango CIDR IPv6 para Services en todo el clúster
  • Un grupo de direcciones IPv4 que se usará para los Services de tipo LoadBalancer
  • Un grupo de direcciones IPv6 que se usará para los Services de tipo LoadBalancer
  • Balanceo de cargas en paquetes

Para obtener ejemplos de configuración adicionales, consulta Variaciones en el uso de ClusterCIDRConfig.

Completa un archivo de configuración

Sigue las instrucciones de uno de los documentos de creación de clústeres.

En el archivo de configuración, en el manifiesto Cluster, haz lo siguiente:

  • Para clusterNetwork.pods.cidrBlocks, proporciona un solo rango CIDR IPv4.

  • Para clusterNetwork.services.cidrBlocks, proporciona dos rangos CIDR: uno para IPv4 y otro para IPv6.

  • En loadBalancer.addressPools, proporciona dos rangos de direcciones: uno para IPv4 y otro para IPv6. Cuando creas un servicio de tipo LoadBalancer, las direcciones IP externas del Service se eligen a partir de estos rangos.

A continuación, se muestra un ejemplo de las partes relevantes de un manifiesto de clúster:

apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
  name: "dual-stack"
  namespace: "cluster-dual-stack"

spec:
  clusterNetwork:
    pods:
      cidrBlocks:
      - "192.168.0.0/16"
    services
      cidrBlocks:
       - "172.16.0.0/20"
       - "fd12::5:0/116"
...
  loadBalancer:
    mode: "bundled"
    ...
    addressPools:
    - name: "pool-1"
      addresses:
       - "10.2.0.212-10.2.0.221"
       - "fd12::4:101-fd12::4:110"

En el mismo archivo de configuración, incluye un manifiesto para un ClusterCIDRConfig.

  • Establece ipv4.cidr en el mismo rango CIDR que proporcionaste en el manifiesto Cluster. Este es un requisito si IPv4 está en modo de isla.

  • Establece namespace con el mismo valor que proporcionaste en el manifiesto Cluster.

  • Establece ipv6.cidr en un rango CIDR IPv6 para Pods.

  • Para cada rango CIDR, proporciona un valor para perNodeMaskSize para especificar cuántas direcciones de Pods se asignarán a cada nodo. La cantidad de direcciones IPv4 asignadas a cada nodo debe ser la misma que la cantidad de direcciones IPv6 asignadas a cada nodo. Debes establecer los valores de perNodeMaskSize en consecuencia. Por ejemplo, si deseas 28 direcciones por nodo, establece los valores de perNodeMaskSize de la siguiente manera:

    • ipv4.perNodeMaskSize: 24 # (32 - 8 = 24)
    • ipv6.perNodeMaskSize: 120 # (128 - 8 = 120)

Este un ejemplo de un manifiesto ClusterCIDRConfig.

apiVersion: baremetal.cluster.gke.io/v1alpha1
kind: ClusterCIDRConfig
metadata:
  name: "cluster-wide-ranges"
  namespace: "cluster-dual-stack"  # Must be the same as the Cluster namespace.
spec:
  ipv4:
    cidr: "192.168.0.0/16"  #  For island mode, must be the same as the Cluster CIDR.
    perNodeMaskSize: 24
  ipv6:
    cidr: "fd12::1:0/112"
    perNodeMaskSize: 120

En el ejemplo anterior:

  • El rango CIDR del Pod IPv4 tiene 2(32-16) = 216 direcciones. El tamaño de la máscara por nodo es 24, por lo que la cantidad de direcciones asignadas a cada nodo es 2(32-24) = 28.

  • El rango CIDR del Pod IPv6 tiene 2(128-112) = 216 direcciones. El tamaño de la máscara por nodo es 120, por lo que la cantidad de direcciones asignadas a cada nodo es 2(128-120) = 28.

Archivo de configuración de ejemplo

Termina de crear el clúster

Termina de crear tu clúster como se describe en el documento de creación de clústeres.

Visualiza los nodos y Pods del clúster

Enumera los nodos del clúster:

kubectl --kubeconfig CLUSTER_KUBECONFIG get nodes --output yaml

Reemplaza CLUSTER_KUBECONFIG por la ruta del archivo kubeconfig del clúster de administrador.

En el resultado, puedes ver las direcciones IPv4 e IPv6 de cada nodo. También puedes ver los rangos de direcciones IPv4 e IPv6 para los Pods en el nodo. Por ejemplo:

- apiVersion: v1
  kind: Node
  ...
  spec:
    podCIDR: 192.168.1.0/24
    podCIDRs:
    - 192.168.1.0/24
    - fd12::1:100/120
    providerID: baremetal://10.2.0.5
  status:
    addresses:
    - address: 10.2.0.5
      type: InternalIP
    - address: fd12::2:5
      type: InternalIP

Obtén una lista de los Pods del clúster:

kubectl --kubeconfig CLUSTER_KUBECONFIG get pods --all-namespaces

Elige un Pod y enumera los detalles. Por ejemplo:

kubectl --kubeconfig CLUSTER_KUBECONFIG get pod gke-metrics-agent-b9qrv \
  --namespace kube-system \
  -- output yaml

En el resultado, puedes ver las direcciones IPv4 e IPv6 del Pod. Por ejemplo:

apiVersion: v1
kind: Pod
metadata:
  ...
  name: gke-metrics-agent-b9qrv
  namespace: kube-system
...
status:
  ...
  podIPs:
  - ip: 192.168.1.146
  - ip: fd12::1:11a

Variaciones en el uso de ClusterCIDRConfig

En el ejemplo anterior, se usó un objeto ClusterCIDRConfig para especificar los rangos CIDR de Pods en todo el clúster. Es decir, se usa un solo rango CIDR IPv4 para todos los Pods del clúster. Además, se usa un solo rango CIDR de IPv6 para todos los Pods del clúster.

En ciertas situaciones, es posible que no quieras usar un solo rango de CIDR para todos los Pods de un clúster. Por ejemplo, es posible que desees especificar un rango CIDR independiente para cada grupo de nodos o un rango CIDR independiente para cada nodo. Para obtener más información sobre ClusterCIDRConfig y ejemplos sobre cómo usarlo, consulta Información sobre el recurso personalizado ClusterCIDRConfig.

Por ejemplo, el siguiente ClusterCIDRConfig especifica un rango CIDR para un grupo de nodos llamado "workers".

apiVersion: baremetal.cluster.gke.io/v1alpha1
kind: ClusterCIDRConfig
metadata:
  name: "worker-pool-ccc"
  namespace: "cluster-dual-stack"
spec:
  ipv4:
    cidr: "192.168.0.0/16"
    perNodeMaskSize: 24
  ipv6:
    cidr: "fd12::1:0/112"
    perNodeMaskSize: 120
  nodeSelector:
    matchLabels:
      baremetal.cluster.gke.io/node-pool: "workers"

En el siguiente ClusterCIDRConfig, se especifica un rango CIDR para un solo nodo que tiene la dirección IP 10.2.0.5:

apiVersion: baremetal.cluster.gke.io/v1alpha1
kind: ClusterCIDRConfig
metadata:
  name: "range-node1"
  namespace: "cluster-dual-stack"
spec:
  ipv4:
    cidr: "192.168.1.0/24"
    perNodeMaskSize: 24
  ipv6:
    cidr: "fd12::1:0/120"
    perNodeMaskSize: 120
  nodeSelector:
    matchLabels:
      baremetal.cluster.gke.io/k8s-ip: "10.2.0.5"

Crea un Service de pila doble de tipo ClusterIP

A continuación, se muestra un manifiesto de Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: "my-deployment"
spec:
  selector:
    matchLabels:
      app: "try-dual-stack"
  replicas: 3
  template:
    metadata:
      labels:
        app: "try-dual-stack"
    spec:
      containers:
      - name: "hello"
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"

Guarda el manifiesto en un archivo llamado my-deployment.yaml y crea el Deployment.

kubectl --kubeconfig CLUSTER_KUBECONFIG apply -f my-deployment.yaml

Reemplaza CLUSTER_KUBECONFIG por la ruta del archivo kubeconfig del clúster de administrador.

Aquí hay un manifiesto para un servicio de tipo ClusterIP:

apiVersion: v1
kind: Service
metadata:
  name: "my-service"
spec:
  selector:
    app: "try-dual-stack"
  type: "ClusterIP"
  ipFamilyPolicy: "RequireDualStack"
  ipFamilies:
  - "IPv6"
  - "IPv4"
  ports:
  - port: 80
    targetPort: 8080

En el contexto de este ejercicio, estos son los puntos clave que debes comprender sobre el manifiesto de Service anterior:

  • El campo ipFamilyPolicy se establece en RequireDualStack. Esto significa que se asignan las direcciones IPv6 e IPv4 ClusterIP para el Service.

  • El campo ipFamilies especifica primero la familia IPv6 y, luego, la familia IPv4. Esto significa que la spec.ClusterIP del Service será una dirección IPv6 elegida de clusterNetwork.services.cidrBlocks en el manifiesto del clúster.

Guarda el manifiesto en un archivo llamado my-cip-service.yaml y crea el Ingress.

kubectl --kubeconfig CLUSTER_KUBECONFIG apply -f my-cip-service.yaml

Enumera los detalles sobre el Service:

kubectl --kubeconfig CLUSTER_KUBECONFIG get service my-service --output yaml

En el resultado, puedes ver las direcciones IP del clúster para el Service. Por ejemplo:

apiVersion: v1
kind: Service
metadata:
  name: my-service
  …
spec:
  clusterIP: fd12::5:9af
  clusterIPs:
  - fd12::5:9af
  - 172.16.12.197

En un nodo del clúster, llama al Service:

curl IPV4_CLUSTER_IP
curl IPV6_CLUSTER_IP

El resultado muestra un mensaje “Hello World”:

Hello, world!
Version: 2.0.0
Hostname: my-deployment-xxx

Crea un Service de pila doble de tipo LoadBalancer

Aquí hay un manifiesto para un servicio de tipo LoadBalancer:

apiVersion: v1
kind: Service
metadata:
  name: "my-lb-service"
spec:
  selector:
    app: "try-dual-stack"
  type: "LoadBalancer"
  ipFamilyPolicy: "RequireDualStack"
  ipFamilies:
  - "IPv6"
  - "IPv4"
  ports:
  - port: 80
    targetPort: 8080

Guarda el manifiesto en un archivo llamado my-lb-service.yaml y crea el Ingress.

kubectl --kubeconfig CLUSTER_KUBECONFIG apply -f my-lb-service.yaml

Recuerda que, en el manifiesto del clúster, especificaste un rango de direcciones IPv6 y un rango de direcciones IPv4 que se usarán para los Services de tipo LoadBalancer:

  loadBalancer:
    mode: "bundled"
    ...
    addressPools:
    - name: "pool-1"
      addresses:
      - "10.2.0.112-10.2.0.221"
      - "fd12::4:101-fd12::4:110"

A tu Service se le asignará una dirección IPv4 externa elegida del rango de IPv4 y una dirección IPv6 externa elegida del rango de IPv6.

Enumera los detalles del Service:

kubectl --kubeconfig CLUSTER_KUBECONFIG get service my-lb-service --output yaml

En el resultado, puedes ver las direcciones externas del Service. Por ejemplo:

apiVersion: v1
kind: Service
metadata:
  name: my-lb-service
...
status:
  loadBalancer:
    ingress:
    - ip: 10.2.0.213
    - ip: fd12::4:101

Valores posibles para ipFamilyPolicy

Cuando creas un Service de pila doble, puedes establecer ipFamilyPolicy en uno de estos valores:

  • SingleStack: El controlador asigna una dirección IP del clúster para el Service, que se elige del primer rango especificado en el manifiesto del clúster en clusterNetwork.services.cidrBlocks.

  • PreferDualStack: El controlador asigna direcciones IP de clúster IPv4 e IPv6 para el Service, elegidas de los rangos especificados en el manifiesto del clúster en clusterNetwork.services.cidrBlocks. Si el clúster no es de pila doble, el comportamiento es el mismo que con SingleStack.

  • RequireDualStack: El controlador asigna direcciones IP de clúster IPv4 e IPv6 para el Service, elegidas de los rangos especificados en el manifiesto del clúster en clusterNetwork.services.cidrBlocks. Establece el valor de spec.clusterIP según la primera familia de direcciones especificada en el manifiesto del Service en ipFamilies.

Más información

Para obtener más información sobre cómo crear Services de pila doble, consulta Opciones de pila doble en Services nuevos.