Mise en réseau de la double pile IPv4/IPv6

GKE sur Bare Metal est compatible avec la mise en réseau double pile IPv4/IPv6. Cela signifie qu'un cluster peut accepter le trafic provenant d'appareils externes utilisant la version 4 du protocole Internet (IPv4) ou le protocole Internet version 6 (IPv6).

La mise en réseau de la pile double attribue des adresses IPv4 et IPv6 aux pods et aux nœuds. Un service Kubernetes peut avoir une adresse IPv4, une adresse IPv6 ou les deux.

Tous les clusters à double pile utilisent le mode plat pour IPv6. Par défaut, un cluster à double pile utilise le mode insulaire pour IPv4, mais vous pouvez le configurer pour utiliser le mode plat pour IPv4.

Pour créer un cluster à deux piles, votre réseau sous-jacent doit être activé pour la double pile. Si votre réseau sous-jacent est un réseau IPv4 ou IPv6 à pile unique, vous ne pouvez pas démarrer un cluster à deux piles.

Avant de commencer

Si les nœuds de votre cluster exécutent CentOS ou RedHat Enterprise Linux et que SELinux est activé, procédez comme suit sur chaque nœud:

  • Dans /etc/firewalld/firewalld.conf, définissez IPv6_rpfilter=no.

  • Exécutez systemctl restart firewalld.

Présentation de la création d'un cluster à deux piles

Vous pouvez activer la mise en réseau de double pile lorsque vous créez un cluster, mais vous ne pouvez pas l'activer pour un cluster existant.

Suivez les instructions de l'un des documents de création du cluster.

Dans votre fichier de configuration, incluez des fichiers manifestes pour les éléments suivants:

  • Une ressource d'espace de noms
  • Une ressource Cluster
  • Une ou plusieurs ressources NodePool
  • Une ou plusieurs ressources ClusterCIDRConfig

Remplissez le fichier manifeste d'espaces de noms et les fichiers manifestes NodePool comme vous le feriez pour un cluster à pile unique.

Dans le fichier manifeste du cluster, sous clusterNetwork.services.cidrBlocks, spécifiez une plage CIDR IPv4 et une plage CIDR IPv6. Il s'agit du critère d'activation d'un cluster à deux piles. En d'autres termes, si vous fournissez des plages CIDR de service pour IPv4 et IPv6, votre cluster aura un réseau à deux piles.

Dans le fichier manifeste du cluster, sous clusterNetwork.pods.cidrBlocks, spécifiez une plage CIDR IPv4, mais pas de plage CIDR IPv6. Les plages CIDR IPv6 des pods sont spécifiées dans les fichiers manifestes ClusterCIDRConfig.

Si vous utilisez l'équilibrage de charge groupé, indiquez les adresses IPv4 et IPv6 dans la section loadBalancer.addressPools du fichier manifeste du cluster.

Les ressources ClusterCIDRConfig permettent de spécifier les plages CIDR IPv4 et IPv6 pour les pods. Vous pouvez utiliser une seule ressource ClusterCIDRConfig pour spécifier des plages CIDR à l'échelle du cluster. Autrement dit, les adresses de pod IPv4 pour tous les nœuds proviennent d'une seule plage CIDR et les adresses de pod IPv6 de tous les nœuds proviennent d'une seule plage CIDR. Vous pouvez également utiliser plusieurs ressources ClusterCIDRConfig pour spécifier des plages CIDR qui s'appliquent à un pool de nœuds particulier ou à un nœud particulier.

Joignabilité pour les adresses IP de pods

Un cluster à double pile utilise le mode plat pour la mise en réseau IPv6. L'exemple donné dans ce document concerne un cluster qui utilise une mise en réseau statique en mode plat pour IPv6. Autrement dit, le cluster n'est pas configuré pour utiliser le protocole BGP (Border Gateway Protocol).

Pour un cluster qui utilise une mise en réseau statique en mode plat, vous devez spécifier les adresses IP des nœuds et des pods qui font toutes partie du même sous-réseau. Cela permet aux clients extérieurs au cluster, mais appartenant au même domaine de couche 2 (L2) que les nœuds du cluster, d'envoyer des paquets directement aux adresses IP de pod.

Par exemple, supposons que les nœuds de votre cluster et d'autres machines se trouvent tous dans le même domaine L2. Voici une façon de spécifier des plages d'adresses:

ObjectifPlageNombre d'adresses
Tout le domaine L2fd12::/1082^20
Podsfd12::1:0/1122^16
Nœudsfd12::2:0/1122^16
Autres machinesfd12::3:0/1122^16
Adresses IP virtuellesfd12::4:0/1122^16

Dans l'exemple précédent, voici les points clés à comprendre:

  • Toutes les adresses de nœud, de pod et de machine sont comprises dans la plage étendue: fd12::/108.

  • Les adresses IP des pods font partie d'un sous-ensemble de la plage étendue.

  • Les adresses IP des nœuds se trouvent dans un sous-ensemble différent de la grande plage.

  • Les adresses IP d'autres machines se trouvent dans un sous-ensemble différent de la grande plage.

  • Toutes les plages de sous-ensembles sont distinctes les unes des autres.

Dans l'exemple précédent, chaque machine du domaine L2, y compris les nœuds de cluster, doit disposer d'une règle de transfert pour la grande plage. Exemple :

inet fd12::/108 scope global eth0

Exemple: créer un cluster à deux piles

Lorsque vous créez un cluster à deux piles, vous disposez de plusieurs options. Par exemple, vous pouvez avoir des plages CIDR à l'échelle du cluster ou des plages CIDR qui s'appliquent à des pools de nœuds particuliers. Vous pouvez associer un réseau plat IPv6 à un réseau en mode île IPv4. Ou vos réseaux IPv4 et IPv6 peuvent tous les deux être en mode plat. Vous pouvez utiliser l'équilibrage de charge groupé ou manuel.

Cette section donne un exemple de création d'un cluster à deux piles. Le cluster de cet exemple présente les caractéristiques suivantes:

  • Un réseau IPv4 en mode île
  • Un réseau IPv6 en mode plat
  • Plage CIDR IPv4 à l'échelle du cluster pour les pods
  • Plage CIDR IPv6 à l'échelle du cluster pour les pods
  • Plage CIDR IPv4 à l'échelle du cluster pour les services
  • Plage CIDR IPv6 à l'échelle du cluster pour les services
  • Un pool d'adresses IPv4 à utiliser pour les services de type LoadBalancer
  • Un pool d'adresses IPv6 à utiliser pour les services de type LoadBalancer
  • Équilibrage de charge groupé

Pour obtenir d'autres exemples de configuration, consultez la section Variantes sur l'utilisation de ClusterCIDRConfig.

Remplir un fichier de configuration

Suivez les instructions de l'un des documents de création du cluster.

Dans votre fichier de configuration, dans le fichier manifeste Cluster:

  • Pour clusterNetwork.pods.cidrBlocks, fournissez une seule plage CIDR IPv4.

  • Pour clusterNetwork.services.cidrBlocks, fournissez deux plages CIDR: une pour IPv4 et une pour IPv6.

  • Pour loadBalancer.addressPools, fournissez deux plages d'adresses: une pour IPv4 et une pour IPv6. Lorsque vous créez un service de type LoadBalancer, les adresses IP externes du service sont choisies dans ces plages.

Voici un exemple illustrant les parties pertinentes d'un fichier manifeste 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"

Dans le même fichier de configuration, incluez un fichier manifeste pour un objet ClusterCIDRConfig.

  • Définissez ipv4.cidr sur la même plage CIDR que celle que vous avez fournie dans le fichier manifeste Cluster. Cela est obligatoire si IPv4 est en mode île.

  • Définissez namespace sur la même valeur que celle fournie dans le fichier manifeste Cluster.

  • Définissez ipv6.cidr sur une plage CIDR IPv6 pour les pods.

  • Pour chaque plage CIDR, indiquez une valeur pour perNodeMaskSize afin de spécifier le nombre d'adresses de pod qui seront attribuées à chaque nœud. Le nombre d'adresses IPv4 attribuées à chaque nœud doit être identique au nombre d'adresses IPv6 attribuées à chaque nœud. Vous devez définir vos valeurs pour perNodeMaskSize en conséquence. Par exemple, si vous souhaitez 2^8 adresses par nœud, définissez vos valeurs perNodeMaskSize comme suit:

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

Voici un exemple de fichier manifeste 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

Dans l'exemple précédent :

  • La plage CIDR du pod IPv4 contient 2^(32-16) = 2^16 adresses. La taille du masque par nœud est de 24. Le nombre d'adresses attribuées à chaque nœud est donc de 2^(32-24) = 2^8.

  • La plage CIDR du pod IPv6 contient 2^(128-112) = 2^16 adresses. La taille du masque par nœud est de 120. Le nombre d'adresses attribuées à chaque nœud est donc de 2^(128-120) = 2^8.

Exemple de fichier de configuration

Terminer la création du cluster

Terminez la création de votre cluster, comme décrit dans le document de création de cluster.

Afficher les nœuds et les pods du cluster

Répertoriez les nœuds du cluster:

kubectl --kubeconfig CLUSTER_KUBECONFIG get nodes --output yaml

Remplacez CLUSTER_KUBECONFIG par le chemin d'accès du fichier kubeconfig de votre cluster.

Le résultat affiche les adresses IPv4 et IPv6 de chaque nœud. Vous pouvez également afficher les plages d'adresses IPv4 et IPv6 des pods du nœud. Exemple :

- 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

Affichez la liste des pods du cluster :

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

Choisissez un pod et listez les détails. Exemple :

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

La sortie indique les adresses IPv4 et IPv6 du pod. Exemple :

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

Variantes lors de l'utilisation de ClusterCIDRConfig

L'exemple précédent utilisait un objet ClusterCIDRConfig pour spécifier des plages CIDR de pods à l'échelle du cluster. Autrement dit, une seule plage CIDR IPv4 est utilisée pour tous les pods du cluster. Une seule plage CIDR IPv6 est utilisée pour tous les pods du cluster.

Dans certains cas, il est possible que vous ne souhaitiez pas utiliser une seule plage CIDR pour tous les pods d'un cluster. Par exemple, vous pouvez spécifier une plage CIDR distincte pour chaque pool de nœuds ou spécifier une plage CIDR distincte pour chaque nœud.

Par exemple, la configuration ClusterCIDRConfig suivante spécifie une plage CIDR pour un pool de nœuds nommé "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"

Le ClusterCIDRConfig suivant spécifie une plage CIDR pour un seul nœud dont l'adresse IP est 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"

Créer un service double pile de type ClusterIP

Voici le fichier manifeste d'un déploiement :

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"

Enregistrez le fichier manifeste dans un fichier nommé my-deployment.yaml et créez le déploiement :

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

Remplacez CLUSTER_KUBECONFIG par le chemin d'accès du fichier kubeconfig de votre cluster.

Voici le fichier manifeste d'un service de type 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

Dans le contexte de cet exercice, voici les points clés à retenir concernant le fichier manifeste Service précédent:

  • Le champ ipFamilyPolicy est défini sur RequireDualStack, ce qui signifie que les adresses IPv6 et IPv4 ClusterIP sont allouées au service.

  • Le champ ipFamilies spécifie d'abord la famille IPv6, puis la famille IPv4. Cela signifie que spec.ClusterIP pour le service est une adresse IPv6 choisie parmi clusterNetwork.services.cidrBlocks dans le fichier manifeste du cluster.

Enregistrez le fichier manifeste dans un fichier nommé my-cip-service.yaml et créez le service :

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

Répertoriez les détails du service:

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

Dans le résultat, vous pouvez voir les adresses IP des clusters pour le service. Exemple :

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

Sur un nœud de cluster, appelez le service:

curl IPV4_CLUSTER_IP
curl [IPV6_CLUSTER_IP]

Le résultat affiche le message "Hello world" :

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

Créer un service double pile de type LoadBalancer

Voici le fichier manifeste d'un service de type 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

Enregistrez le fichier manifeste dans un fichier nommé my-lb-service.yaml et créez le service :

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

Rappelez-vous que dans votre fichier manifeste de cluster, vous avez spécifié une plage d'adresses IPv6 et une plage d'adresses IPv4 à utiliser pour les services de type LoadBalancer:

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

Votre service se voit attribuer une adresse IPv4 externe choisie dans la plage IPv4 et une adresse IPv6 externe choisie dans la plage IPv6.

Listez les détails du service:

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

Dans la sortie, vous pouvez voir les adresses externes du service. Exemple :

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

Les valeurs possibles pour ipFamilyPolicy

Lorsque vous créez un service à deux piles, vous pouvez définir ipFamilyPolicy sur l'une des valeurs suivantes:

  • SingleStack: le contrôleur attribue une adresse IP de cluster pour le service, choisie dans la première plage spécifiée dans le fichier manifeste du cluster sous clusterNetwork.services.cidrBlocks.

  • PreferDualStack: le contrôleur alloue les adresses IP de cluster IPv4 et IPv6 du service, choisies dans les plages spécifiées dans le fichier manifeste du cluster sous clusterNetwork.services.cidrBlocks. Si le cluster n'est pas un cluster à deux piles, le comportement est le même que pour SingleStack.

  • RequireDualStack: le contrôleur alloue les adresses IP de cluster IPv4 et IPv6 du service, choisies dans les plages spécifiées dans le fichier manifeste du cluster sous clusterNetwork.services.cidrBlocks. Il définit la valeur de spec.clusterIP en fonction de la première famille d'adresses spécifiée dans le fichier manifeste du service sous ipFamilies.

Informations complémentaires

Pour en savoir plus sur la création de services de double pile, consultez la section Options de double pile sur les nouveaux services.