Redes de doble pila IPv4/IPv6

Google Distributed Cloud admite redes de pila dual IPv4/IPv6. Esto significa que un clúster puede aceptar tráfico de dispositivos externos que usen Protocolo de Internet versión 4 (IPv4) o Protocolo de Internet versión 6 (IPv6).

La red de doble pila asigna direcciones IPv4 e IPv6 a los pods y los nodos. Un servicio de Kubernetes puede tener una dirección IPv4, una dirección IPv6 o ambas.

Todos los clústeres de doble pila usan el modo plano para IPv6. De forma predeterminada, un clúster de doble pila usa el modo aislado para IPv4, pero puedes configurarlo para que use el modo plano para IPv4.

Para crear un clúster de doble pila, la red subyacente debe tener habilitada la doble pila. Si tu red subyacente es una red de pila única IPv4 o IPv6, no puedes iniciar un clúster de doble pila.

Antes de empezar

Si los nodos de tu clúster ejecutan Red Hat Enterprise Linux y tienen SELinux habilitado, haz lo siguiente en cada nodo:

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

  • Ejecuta systemctl restart firewalld.

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

Puedes habilitar la red de doble pila al crear un clúster, pero no puedes hacerlo en un clúster que ya tengas.

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

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

  • Un recurso Namespace
  • Un recurso de clúster
  • Uno o varios recursos NodePool
  • Uno o varios recursos ClusterCIDRConfig

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

En el manifiesto del clúster, en clusterNetwork.services.cidrBlocks, especifica un intervalo CIDR IPv4 y un intervalo CIDR IPv6. Este es el criterio para habilitar un clúster de doble pila. Es decir, si proporcionas intervalos CIDR de servicio tanto para IPv4 como para IPv6, tu clúster tendrá una red de doble pila.

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

Si usas el balanceo de carga agrupado, proporciona direcciones IPv4 e IPv6 en la sección loadBalancer.addressPools del manifiesto de Cluster.

Los recursos ClusterCIDRConfig se usan para especificar intervalos CIDR de IPv4 e IPv6 para los pods. Puedes usar un solo recurso ClusterCIDRConfig para especificar intervalos CIDR que abarquen todo el clúster. Es decir, las direcciones IPv4 de los pods de todos los nodos se toman de un único intervalo CIDR, y las direcciones IPv6 de los pods de todos los nodos se toman de un único intervalo CIDR. También puede usar varios recursos ClusterCIDRConfig para especificar intervalos CIDR que se apliquen a un grupo de nodos o a un nodo concretos.

Accesibilidad de las direcciones IP de los pods

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

En un clúster que usa redes estáticas en modo plano, debes especificar direcciones IP de nodos y pods que formen parte de la misma subred. Esta configuración permite que los clientes que estén 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 de tu clúster y otras máquinas están en el mismo dominio de capa 2. Esta es una de las formas en las que puedes especificar intervalos de direcciones:

FinalidadIntervaloNúmero de direcciones
Todo el dominio de capa 2fd12::/108220
Podsfd12::1:0/112216
Nodosfd12::2:0/112216
Otras máquinasfd12::3:0/112216
IP virtualesfd12::4:0/112216

En el ejemplo anterior, estos son los puntos clave que debes tener en cuenta:

  • Todas las direcciones de nodos, pods y máquinas se encuentran en el intervalo grande: fd12::/108.

  • Las direcciones IP de los pods se encuentran en un subconjunto del intervalo grande.

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

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

  • Todos los intervalos 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 intervalo grande. Por ejemplo:

inet fd12::/108 scope global eth0

Ejemplo: Crear un clúster de doble pila

Cuando creas un clúster de doble pila, tienes varias opciones. Por ejemplo, puedes tener intervalos CIDR en todo el clúster o intervalos CIDR que se apliquen a grupos de nodos concretos. Podrías combinar una red plana IPv6 con una red en modo isla IPv4. También es posible que tus redes IPv4 e IPv6 sean planas. Puedes usar el balanceo de carga agrupado o el manual.

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

  • Una red IPv4 en modo aislado
  • Una red IPv6 en modo Flat
  • Intervalo CIDR IPv4 de todo el clúster para pods
  • Un intervalo CIDR IPv6 de todo el clúster para los pods
  • Intervalo CIDR IPv4 de todo el clúster para los servicios
  • Intervalo CIDR IPv6 de todo el clúster para los servicios
  • Un pool de direcciones IPv4 que se usará para los servicios de tipo LoadBalancer
  • Un pool de direcciones IPv6 que se usará para los servicios de tipo LoadBalancer
  • Balanceo de carga agrupado

Para ver más ejemplos de configuración, consulta Variaciones del uso de ClusterCIDRConfig.

Rellenar 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:

  • En clusterNetwork.pods.cidrBlocks, proporciona un único intervalo CIDR de IPv4.

  • En clusterNetwork.services.cidrBlocks, proporcione dos intervalos CIDR: uno para IPv4 y otro para IPv6.

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

Aquí tienes un ejemplo que muestra las partes relevantes de un manifiesto de Cluster:

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.

  • Define ipv4.cidr en el mismo intervalo CIDR que has proporcionado en el Cluster manifiesto. Este requisito es obligatorio si IPv4 está en modo aislado.

  • Asigne a namespace el mismo valor que proporcionó en el manifiesto Cluster.

  • Define ipv6.cidr en un intervalo CIDR de IPv6 para los pods.

  • En cada intervalo CIDR, proporcione un valor para perNodeMaskSize para especificar cuántas direcciones de pod se asignarán a cada nodo. El número de direcciones IPv4 asignadas a cada nodo debe ser el mismo que el número de direcciones IPv6 asignadas a cada nodo. Debe definir los valores de perNodeMaskSize en consecuencia. Por ejemplo, si quiere 28 direcciones por nodo, defina los valores de perNodeMaskSize de la siguiente manera:

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

A continuación, se muestra un ejemplo de 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 intervalo CIDR de pods IPv4 tiene 2(32-16) = 216 direcciones. El tamaño de la máscara por nodo es 24, por lo que el número de direcciones asignadas a cada nodo es 2(32-24) = 28.

  • El intervalo CIDR de pods IPv6 tiene 2(128-112) = 216 direcciones. El tamaño de la máscara por nodo es 120, por lo que el número de direcciones asignadas a cada nodo es 2(128-120) = 28.

Ejemplo de archivo de configuración

Terminar de crear el clúster

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

Ver nodos y pods de un clúster

Lista los nodos del clúster:

kubectl --kubeconfig CLUSTER_KUBECONFIG get nodes --output yaml

Sustituye CLUSTER_KUBECONFIG por la ruta del archivo kubeconfig de tu clúster.

En el resultado, puedes ver las direcciones IPv4 e IPv6 de cada nodo. También puedes ver los intervalos de direcciones IPv4 e IPv6 de los pods del 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

Lista 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 ha usado un objeto ClusterCIDRConfig para especificar los intervalos de CIDR de los pods de todo el clúster. Es decir, se usa un único intervalo CIDR IPv4 para todos los pods del clúster. Se usa un único intervalo CIDR IPv6 para todos los pods del clúster.

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

Por ejemplo, el siguiente ClusterCIDRConfig especifica un intervalo 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"

El siguiente ClusterCIDRConfig especifica un intervalo 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 servicio de doble pila de tipo ClusterIP

Aquí tienes un manifiesto de un 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 la implementación:

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

Sustituye CLUSTER_KUBECONFIG por la ruta del archivo kubeconfig de tu clúster.

A continuación, se muestra un manifiesto de 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 tener en cuenta sobre el manifiesto de servicio anterior:

  • El campo ipFamilyPolicy se define como RequireDualStack, lo que significa que se asignan direcciones IPv6 e IPv4 ClusterIP al servicio.

  • El campo ipFamilies especifica primero la familia IPv6 y, después, la familia IPv4. Esto significa que spec.ClusterIP del servicio 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 servicio:

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

Detalles sobre el Servicio:

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

En el resultado, puedes ver las direcciones IP del clúster del servicio. 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 de clúster, llama al servicio:

curl IPV4_CLUSTER_IP
curl IPV6_CLUSTER_IP

El resultado muestra el mensaje "Hello world":

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

Crea un servicio de doble pila de tipo LoadBalancer

A continuación, se muestra un manifiesto de 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 servicio:

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

Recuerda que, en el manifiesto de tu clúster, especificaste un intervalo de direcciones IPv6 y un intervalo de direcciones IPv4 que se usarán para los servicios 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 Servicio se le asignará una dirección IPv4 externa elegida del intervalo IPv4 y una dirección IPv6 externa elegida del intervalo IPv6.

Lista los detalles del servicio:

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

En el resultado, puede ver las direcciones externas del servicio. 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 de ipFamilyPolicy

Cuando creas un servicio de doble pila, puedes asignar uno de los siguientes valores a ipFamilyPolicy:

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

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

  • RequireDualStack: el controlador asigna direcciones IP de clúster IPv4 e IPv6 al servicio, elegidas entre los intervalos especificados en el manifiesto del clúster en clusterNetwork.services.cidrBlocks. Define el valor de spec.clusterIP en función de la primera familia de direcciones especificada en el manifiesto de servicio, en ipFamilies.

Más información

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