Networking dual stack IPv4/IPv6

GKE su Bare Metal supporta il networking IPv4/IPv6 dual stack. Ciò significa che un cluster può accettare il traffico da dispositivi esterni che utilizzano Internet Protocol versione 4 (IPv4) o Internet Protocol versione 6 (IPv6).

Il networking a due stack assegna indirizzi IPv4 e IPv6 a pod e nodi. Un servizio Kubernetes può avere un indirizzo IPv4, un indirizzo IPv6 o entrambi.

Tutti i cluster a doppio stack utilizzano la modalità flat per IPv6. Per impostazione predefinita, un cluster a due stack utilizza la modalità isola per IPv4, ma puoi configurarlo in modo da utilizzare la modalità flat per IPv4.

Per creare un cluster a due stack, la rete sottostante deve essere abilitata in modalità dual stack. Se la rete sottostante è una rete IPv4 o IPv6 a stack singolo, non puoi avviare un cluster a due stack.

Prima di iniziare

Se i nodi del cluster eseguono CentOS o RedHat Enterprise Linux e hanno SELinux abilitato, su ciascun nodo:

  • In /etc/firewalld/firewalld.conf, imposta IPv6_rpfilter=no.

  • Esegui systemctl restart firewalld.

Panoramica della creazione di un cluster a due stack

Puoi abilitare il networking a due stack quando crei un nuovo cluster, ma non per un cluster esistente.

Segui le istruzioni in uno dei documenti di creazione del cluster.

Nel file di configurazione, includi file manifest per i seguenti elementi:

  • Una risorsa spazio dei nomi
  • Una risorsa cluster
  • Una o più risorse del pool di nodi
  • Una o più risorse ClusterCIDRConfig

Compila il manifest dello spazio dei nomi e i manifest del pool di nodi come faresti per un cluster a stack singolo.

Nel file manifest del cluster, in clusterNetwork.services.cidrBlocks, specifica un intervallo CIDR IPv4 e un intervallo CIDR IPv6. Questo è il criterio di attivazione per un cluster a due stack. In altre parole, se fornisci intervalli CIDR del servizio sia per IPv4 sia per IPv6, il cluster avrà una rete a doppio stack.

Nel manifest del cluster, in clusterNetwork.pods.cidrBlocks, specifica un intervallo CIDR IPv4, ma non specificarne uno IPv6. Gli intervalli CIDR IPv6 per i pod sono specificati nei manifest di ClusterCIDRConfig.

Se utilizzi il bilanciamento del carico in bundle, fornisci sia indirizzi IPv4 sia indirizzi IPv6 nella sezione loadBalancer.addressPools del manifest del cluster.

Le risorse ClusterCIDRConfig consentono di specificare intervalli CIDR IPv4 e IPv6 per i pod. Puoi utilizzare una singola risorsa ClusterCIDRConfig per specificare intervalli CIDR a livello di cluster. In altre parole, gli indirizzi dei pod IPv4 per tutti i nodi vengono ricavati da un singolo intervallo CIDR e gli indirizzi dei pod IPv6 per tutti i nodi vengono ricavati da un singolo intervallo CIDR. In alternativa, puoi utilizzare diverse risorse ClusterCIDRConfig per specificare intervalli CIDR da applicare a un determinato pool di nodi o a uno specifico nodo.

Raggiungibilità per gli indirizzi IP dei pod

Un cluster a due stack utilizza la modalità flat per le reti IPv6. L'esempio fornito in questo documento riguarda un cluster che utilizza il networking statico in modalità flat per IPv6. Questo significa che il cluster non è configurato per utilizzare il protocollo BGP (Border Gateway Protocol).

Per un cluster che utilizza una rete di rete statica in modalità flat, devi specificare gli indirizzi IP di nodi e pod che fanno tutti parte della stessa subnet. In questo modo, i client esterni al cluster, ma nello stesso dominio di livello 2 (L2) dei nodi del cluster, possono inviare pacchetti direttamente agli indirizzi IP dei pod.

Ad esempio, supponiamo che i nodi del cluster e alcune altre macchine siano tutti nello stesso dominio L2. Ecco un modo per specificare gli intervalli di indirizzi:

FinalitàIntervalloNumero di indirizzi
Intero dominio L2FD12::/1082^20
Podfd12::1:0/1122^16
Nodifd12::2:0/1122^16
Altre macchinefd12::3:0/1122^16
VIPfd12::4:0/1122^16

Nell'esempio precedente, ecco i punti chiave da comprendere:

  • L'intervallo di indirizzi di tutti i nodi, pod e macchine è ampio: fd12::/108.

  • Gli indirizzi IP dei pod sono in un sottoinsieme dell'intervallo ampio.

  • Gli indirizzi IP dei nodi si trovano in un sottoinsieme diverso dell'intervallo ampio.

  • Gli indirizzi IP delle altre macchine si trovano in un sottoinsieme diverso dell'intervallo ampio.

  • Tutti gli intervalli di sottoinsiemi sono diversi tra loro.

Nell'esempio precedente, ogni macchina nel dominio L2, inclusi i nodi del cluster, deve avere una regola di forwarding per l'intervallo ampio. Ad esempio:

inet fd12::/108 scope global eth0

Esempio: creare un cluster a due stack

Quando crei un cluster a due stack, hai varie opzioni. Ad esempio, potresti avere intervalli CIDR a livello di cluster o avere intervalli CIDR applicabili a determinati pool di nodi. Puoi combinare una rete flat IPv6 con una rete in modalità isola IPv4. Oppure entrambe le reti IPv4 e IPv6 potrebbero essere stabili. Puoi utilizzare il bilanciamento del carico in bundle o il bilanciamento del carico manuale.

Questa sezione fornisce un esempio di come creare un cluster a due stack. Il cluster in questo esempio ha le seguenti caratteristiche:

  • Una rete IPv4 in modalità isola
  • Una rete IPv6 in modalità flat
  • Un intervallo CIDR IPv4 a livello di cluster per i pod
  • Un intervallo CIDR IPv6 a livello di cluster per i pod
  • Un intervallo CIDR IPv4 a livello di cluster per i servizi
  • Un intervallo CIDR IPv6 a livello di cluster per i servizi
  • Un pool di indirizzi IPv4 da utilizzare per i servizi di tipo LoadBalancer
  • Un pool di indirizzi IPv6 da utilizzare per i servizi di tipo LoadBalancer
  • Bilanciamento del carico in bundle

Per ulteriori esempi di configurazione, consulta Variazioni sull'utilizzo di ClusterCIDRConfig.

Compilare un file di configurazione

Segui le istruzioni in uno dei documenti di creazione del cluster.

Nel file di configurazione, nel file manifest Cluster:

  • Per clusterNetwork.pods.cidrBlocks, specifica un singolo intervallo CIDR IPv4.

  • Per clusterNetwork.services.cidrBlocks, specifica due intervalli CIDR: uno per IPv4 e uno per IPv6.

  • Per loadBalancer.addressPools, specifica due intervalli di indirizzi: uno per IPv4 e uno per IPv6. Quando crei un servizio di tipo LoadBalancer, gli indirizzi IP esterni per il servizio vengono scelti da questi intervalli.

Ecco un esempio che mostra le parti pertinenti di un manifest del 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"

Nello stesso file di configurazione, includi un manifest per un ClusterCIDRConfig.

  • Imposta ipv4.cidr sullo stesso intervallo CIDR fornito nel manifest Cluster. Questo è un requisito se IPv4 è in modalità isola.

  • Imposta namespace sullo stesso valore che hai fornito nel file manifest Cluster.

  • Imposta ipv6.cidr su un intervallo CIDR IPv6 per i pod.

  • Per ogni intervallo CIDR, fornisci un valore per perNodeMaskSize per specificare quanti indirizzi di pod verranno assegnati a ciascun nodo. Il numero di indirizzi IPv4 assegnati a ciascun nodo deve essere uguale al numero di indirizzi IPv6 assegnati a ciascun nodo. Devi impostare i valori per perNodeMaskSize di conseguenza. Ad esempio, se vuoi 2^8 indirizzi per nodo, imposta i tuoi valori perNodeMaskSize come segue:

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

Ecco un esempio di manifest 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

Nell'esempio precedente:

  • L'intervallo CIDR dei pod IPv4 ha 2^(32-16) = 2^16 indirizzi. La dimensione della maschera per nodo è 24, quindi il numero di indirizzi assegnati a ciascun nodo è 2^(32-24) = 2^8.

  • L'intervallo CIDR dei pod IPv6 ha 2^(128-112) = 2^16 indirizzi. La dimensione della maschera per nodo è 120, quindi il numero di indirizzi assegnati a ciascun nodo è 2^(128-120)=2^8.

Esempio di file di configurazione

Completa la creazione del cluster

Completa la creazione del cluster come descritto nel documento sulla creazione del cluster.

Visualizza nodi e pod del cluster

Elenca i nodi del cluster:

kubectl --kubeconfig CLUSTER_KUBECONFIG get nodes --output yaml

Sostituisci CLUSTER_KUBECONFIG con il percorso del file kubeconfig del cluster.

Nell'output, puoi vedere gli indirizzi IPv4 e IPv6 di ciascun nodo. Puoi anche vedere gli intervalli di indirizzi IPv4 e IPv6 per i pod sul nodo. Ad esempio:

- 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

Elenca i pod presenti nel cluster:

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

Scegli un pod ed elenca i dettagli. Ad esempio:

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

Nell'output, puoi vedere gli indirizzi IPv4 e IPv6 del pod. Ad esempio:

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

Variazioni sull'utilizzo di ClusterCIDRConfig

L'esempio precedente utilizzava un oggetto ClusterCIDRConfig per specificare intervalli CIDR per pod a livello di cluster. In altre parole, viene utilizzato un singolo intervallo CIDR IPv4 per tutti i pod nel cluster. Inoltre, viene utilizzato un singolo intervallo CIDR IPv6 per tutti i pod nel cluster.

In determinate situazioni, potresti non voler utilizzare un singolo intervallo CIDR per tutti i pod di un cluster. Ad esempio, potresti voler specificare un intervallo CIDR separato per ogni pool di nodi oppure specificare un intervallo CIDR separato per ogni nodo.

Ad esempio, il seguente ClusterCIDRConfig specifica un intervallo CIDR per un pool di nodi denominato "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"

Il seguente ClusterCIDRConfig specifica un intervallo CIDR per un singolo nodo con indirizzo 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 servizio dual-stack di tipo ClusterIP

Ecco il manifest per 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"

Salva il manifest in un file denominato my-deployment.yaml e crea il deployment:

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

Sostituisci CLUSTER_KUBECONFIG con il percorso del file kubeconfig del cluster.

Ecco un manifest per un servizio di 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

Nel contesto di questo esercizio, ecco i punti chiave da comprendere in merito al precedente manifest del servizio:

  • Il campo ipFamilyPolicy è impostato su RequireDualStack, il che significa che per il servizio sono allocati sia gli indirizzi IPv6 sia quelli ClusterIP IPv4.

  • Il campo ipFamilies specifica prima la famiglia IPv6 e la seconda famiglia IPv4. Ciò significa che spec.ClusterIP per il servizio sarà un indirizzo IPv6 scelto da clusterNetwork.services.cidrBlocks nel manifest del cluster.

Salva il manifest in un file denominato my-cip-service.yaml e crea il servizio:

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

Elenca i dettagli del Servizio:

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

Nell'output puoi vedere gli indirizzi IP del cluster per il servizio. Ad esempio:

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

Su un nodo cluster, chiama il servizio:

curl IPV4_CLUSTER_IP
curl [IPV6_CLUSTER_IP]

L'output visualizza un messaggio "Hello world":

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

Crea un servizio dual-stack di tipo LoadBalancer

Ecco un manifest per un servizio di 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

Salva il manifest in un file denominato my-lb-service.yaml e crea il servizio:

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

Ricorda che nel manifest del cluster hai specificato un intervallo di indirizzi IPv6 e un intervallo di indirizzi IPv4 da utilizzare per i servizi di tipo LoadBalancer:

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

Al servizio verrà assegnato un indirizzo IPv4 esterno scelto dall'intervallo IPv4 e un indirizzo IPv6 esterno scelto dall'intervallo IPv6.

Elenco dettagli per il Servizio:

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

Nell'output puoi vedere gli indirizzi esterni del servizio. Ad esempio:

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

Valori possibili per ipFamilyPolicy

Quando crei un servizio a due stack, puoi impostare ipFamilyPolicy su uno di questi valori:

  • SingleStack: il controller alloca un indirizzo IP del cluster per il servizio, scelto dal primo intervallo specificato nel manifest del cluster in clusterNetwork.services.cidrBlocks.

  • PreferDualStack: il controller alloca gli indirizzi IP dei cluster IPv4 e IPv6 per il servizio, scelti tra gli intervalli specificati nel manifest del cluster in clusterNetwork.services.cidrBlocks. Se il cluster non è a doppio stack, il comportamento è lo stesso di SingleStack.

  • RequireDualStack: il controller alloca gli indirizzi IP del cluster IPv4 e IPv6 per il servizio, scelti tra gli intervalli specificati nel manifest del cluster in clusterNetwork.services.cidrBlocks. Imposta il valore di spec.clusterIP in base alla prima famiglia di indirizzi specificata nel manifest del servizio in ipFamilies.

Informazioni dettagliate

Per ulteriori informazioni su come creare servizi dual-stack, consulta Opzioni dual stack sui nuovi servizi.