IPv4/IPv6-Dual-Stack-Netzwerk

GDCV für Bare Metal unterstützt IPv4/IPv6-Dual-Stack-Netzwerke. Das bedeutet, dass ein Cluster Traffic von externen Geräten akzeptieren kann, die entweder Internet Protocol Version 4 (IPv4) oder Internet Protocol Version 6 (IPv6)

Dual-Stack-Netzwerke weisen Pods und Knoten sowohl IPv4- als auch IPv6-Adressen zu. Ein Kubernetes-Dienst kann eine IPv4-Adresse, eine IPv6-Adresse oder beides haben.

Alle Dual-Stack-Cluster verwenden den flachen Modus für IPv6. Standardmäßig verwendet ein Dual-Stack-Cluster für IPv4 den Inselmodus. Sie können ihn aber auch für die Verwendung des flachen Modus für IPv4 konfigurieren.

Zum Erstellen eines Dual-Stack-Clusters muss das zugrunde liegende Netzwerk Dual-Stack-aktiviert sein. Wenn das zugrunde liegende Netzwerk ein Single-Stack-IPv4- oder IPv6-Netzwerk ist, können Sie keinen Dual-Stack-Cluster starten.

Hinweise

Wenn auf Ihren Clusterknoten CentOS oder RedHat Enterprise Linux ausgeführt wird und SELinux aktiviert ist, führen Sie auf jedem Knoten folgende Schritte aus:

  • Legen Sie in /etc/firewalld/firewalld.conf IPv6_rpfilter=no fest.

  • Führen Sie systemctl restart firewalld aus.

Übersicht: Erstellen eines Dual-Stack-Clusters

Sie können die Verwendung eines Dual-Stack-Netzwerks beim Erstellen eines neuen Clusters aktivieren. Für einen vorhandenen Cluster ist eine solche Aktivierung aber nicht möglich.

Folgen Sie der Anleitung in einem der Dokumente zur Clustererstellung.

Fügen Sie in Ihrer Konfigurationsdatei Manifeste für Folgendes ein:

  • Eine Namespace-Ressource
  • Eine Clusterressource
  • Eine oder mehrere NodePool-Ressourcen
  • Eine oder mehrere ClusterCIDRConfig-Ressourcen

Füllen Sie das Namespace-Manifest und die NodePool-Manifeste aus, wie Sie es auch bei einem Single-Stack-Cluster tun würden.

Geben Sie im Clustermanifest unter clusterNetwork.services.cidrBlocks sowohl einen IPv4-CIDR-Bereich als auch einen IPv6-CIDR-Bereich an. Dies ist das Aktivierungskriterium für einen Dual-Stack-Cluster. Das heißt, wenn Sie Dienst-CIDR-Bereiche sowohl für IPv4 als auch für IPv6 angeben, hat Ihr Cluster ein Dual-Stack-Netzwerk.

Geben Sie im Clustermanifest unter clusterNetwork.pods.cidrBlocks einen IPv4-CIDR-Bereich an, aber keinen IPv6-CIDR-Bereich. IPv6-CIDR-Bereiche für Pods werden in ClusterCIDRConfig-Manifesten angegeben.

Wenn Sie das gebündelte Load-Balancing verwenden, geben Sie im loadBalancer.addressPools-Abschnitt des Clustermanifests sowohl IPv4- als auch IPv6-Adressen an.

Die ClusterCIDRConfig-Ressourcen dienen zur Angabe von IPv4- und IPv6-CIDR-Bereichen für Pods. Sie können eine einzelne ClusterCIDRConfig-Ressource verwenden, um clusterweite CIDR-Bereiche anzugeben. Das heißt, die IPv4-Pod-Adressen für alle Knoten werden aus einem einzelnen CIDR-Bereich und die IPv6-Pod-Adressen für alle Knoten aus einem einzelnen CIDR-Bereich übernommen. Sie können auch mehrere ClusterCIDRConfig-Ressourcen verwenden, um CIDR-Bereiche anzugeben, die für einen bestimmten Knotenpool oder einen bestimmten Knoten gelten.

Erreichbarkeit für Pod-IP-Adressen

Ein Dual-Stack-Cluster verwendet den flachen Modus für IPv6-Netzwerke. Das in diesem Dokument angegebene Beispiel bezieht sich auf einen Cluster, der ein statisches Flat-Mode-Netzwerk für IPv6 verwendet. Das heißt, der Cluster ist nicht für die Verwendung des Border Gateway Protocol (BGP) konfiguriert.

Für einen Cluster, der statische Netzwerke im Flat-Modus verwendet, müssen Sie Knoten- und Pod-IP-Adressen angeben, die alle Teil desselben Subnetzes sind. Dadurch können Clients, die sich außerhalb des Clusters befinden, jedoch in derselben Ebene-2-Domain (L2) wie die Clusterknoten, Pakete direkt an Pod-IP-Adressen senden.

Angenommen, Ihre Clusterknoten und einige andere Maschinen befinden sich alle in derselben L2-Domain. Hier ist eine Möglichkeit, wie Sie Adressbereiche angeben können:

ZweckBereichAnzahl der Adressen
Gesamte L2-Domainfd12::/1082^20
Podsfd12::1:0/1122^16
Knotenfd12::2:0/1122^16
Sonstige Maschinenfd12::3:0/1122^16
VIPsfd12::4:0/1122^16

Im vorstehenden Beispiel sind dies die wichtigsten Punkte, die Sie verstehen sollten:

  • Alle Knoten-, Pod- und Maschinenadressen befinden sich im großen Bereich: fd12::/108.

  • Die Pod-IP-Adressen sind nur ein Teil des großen Bereichs.

  • Die Knoten-IP-Adressen befinden sich in einer anderen Teilmenge des großen Bereichs.

  • Die IP-Adressen anderer Maschinen befinden sich in einer anderen Teilmenge des großen Bereichs.

  • Alle Teilmengenbereiche unterscheiden sich voneinander.

Im vorherigen Beispiel muss jede Maschine in der L2-Domain, einschließlich der Clusterknoten, eine Weiterleitungsregel für den großen Bereich haben. Beispiel:

inet fd12::/108 scope global eth0

Beispiel: Dual-Stack-Cluster erstellen

Wenn Sie einen Dual-Stack-Cluster erstellen, haben Sie verschiedene Möglichkeiten. Beispielsweise könnten Sie clusterweite CIDR-Bereiche haben oder CIDR-Bereiche, die für bestimmte Knotenpools gelten. Sie können ein einfaches IPv6-Netzwerk mit einem IPv4-Inseln-Netzwerk kombinieren. Oder Ihre IPv4- und IPv6-Netzwerke könnten flach sein. Sie können gebündeltes oder manuelles Load-Balancing verwenden.

In diesem Abschnitt wird ein Beispiel für das Erstellen eines Dual-Stack-Clusters beschrieben. Der Cluster in diesem Beispiel hat folgende Merkmale:

  • Ein IPv4-Netzwerk im Inselmodus
  • Ein IPv6-Netzwerk im flachen Modus
  • Einen clusterübergreifenden IPv4-CIDR-Bereich für Pods
  • Einen clusterübergreifenden IPv6-CIDR-Bereich für Pods
  • Einen clusterübergreifenden IPv4-CIDR-Bereich für Dienste
  • Einen clusterübergreifenden IPv6-CIDR-Bereich für Dienste
  • Ein IPv4-Adresspool, der für Dienste vom Typ LoadBalancer
  • Ein IPv6-Adresspool für Dienste vom Typ LoadBalancer
  • Gebündeltes Load-Balancing

Weitere Konfigurationsbeispiele finden Sie unter Variationen: Verwendung von ClusterCIDRConfig.

Konfigurationsdatei ausfüllen

Folgen Sie der Anleitung in einem der Dokumente zur Clustererstellung.

In Ihrer Konfigurationsdatei im Cluster-Manifest:

  • Geben Sie für clusterNetwork.pods.cidrBlocks einen einzelnen IPv4-CIDR-Bereich an.

  • Geben Sie für clusterNetwork.services.cidrBlocks zwei CIDR-Bereiche an: einen für IPv4 und einen für IPv6.

  • Geben Sie für loadBalancer.addressPools zwei Adressbereiche an: einen für IPv4 und einen für IPv6. Wenn Sie einen Dienst vom Typ LoadBalancer erstellen, werden die externen IP-Adressen für den Dienst aus diesen Bereichen ausgewählt.

Hier ist ein Beispiel, das die relevanten Teile eines Clustermanifests zeigt:

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"

Fügen Sie in derselben Konfigurationsdatei ein Manifest für eine ClusterCIDRConfig hinzu.

  • Setzen Sie ipv4.cidr auf denselben CIDR-Bereich, den Sie im Manifest Cluster angegeben haben. Dies ist eine Voraussetzung, wenn sich IPv4 im Inselmodus befindet.

  • Legen Sie für namespace den Wert fest, den Sie im Cluster-Manifest angegeben haben.

  • Setzen Sie ipv6.cidr auf einen IPv6-CIDR-Bereich für Pods.

  • Geben Sie für jeden CIDR-Bereich einen Wert für perNodeMaskSize an, um zu bestimmen, wie viele Pod-Adressen den einzelnen Knoten zugewiesen werden. Die Anzahl der IPv4-Adressen, die jedem Knoten zugewiesen werden, muss mit der Anzahl der IPv6-Adressen übereinstimmen, die jedem Knoten zugewiesen sind. Sie müssen Ihre Werte für perNodeMaskSize entsprechend festlegen. Wenn Sie beispielsweise 2^8 Adressen pro Knoten haben, legen Sie die perNodeMaskSize-Werte so fest:

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

Hier ist ein Beispiel für ein ClusterCIDRConfig-Manifest:

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

Im obigen Beispiel gilt Folgendes:

  • Der CIDR-Bereich des IPv4-Pods hat 2^(32-16) = 2^16 Adressen. Die Maskengröße pro Knoten beträgt 24. Die Anzahl der jedem Knoten zugewiesenen Adressen beträgt also 2^(32-24) = 2^8.

  • Der CIDR-Bereich des IPv6-Pods hat 2^(128–112) = 2^16 Adressen. Die Maskengröße pro Knoten beträgt 120, sodass die Anzahl der jedem Knoten zugewiesenen Adressen 2^(128–120) = 2^8 beträgt.

Beispiel: Konfigurationsdatei

Cluster erstellen beenden

Schließen Sie das Erstellen des Clusters ab, wie im Dokument zur Clustererstellung beschrieben.

Clusterknoten und Pods ansehen

Listen Sie die Clusterknoten auf:

kubectl --kubeconfig CLUSTER_KUBECONFIG get nodes --output yaml

Ersetzen Sie CLUSTER_KUBECONFIG durch den Pfad der kubeconfig-Datei des Clusters.

In der Ausgabe werden die IPv4- und IPv6-Adressen der einzelnen Knoten angezeigt. Sie können auch die IPv4- und IPv6-Adressbereiche für Pods auf dem Knoten sehen. Beispiel:

- 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

Lassen Sie die im Cluster enthaltenen Pods auflisten:

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

Wählen Sie einen Pod aus und listen Sie die Details auf. Beispiel:

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

In der Ausgabe werden die IPv4- und IPv6-Adressen des Pods angezeigt. Beispiel:

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

Variationen: Verwendung von ClusterCIDRConfig

Im vorherigen Beispiel wurde ein ClusterCIDRConfig-Objekt verwendet, um clusterweite Pod-CIDR-Bereiche anzugeben. Das heißt, dass für alle Pods im Cluster ein einzelner IPv4-CIDR-Bereich verwendet wird. Für alle Pods im Cluster wird ein einziger IPv6-CIDR-Bereich verwendet.

In bestimmten Situationen möchten Sie vielleicht nicht einen einzelnen CIDR-Bereich für alle Pods in einem Cluster verwenden. Beispiel: Sie können einen separaten CIDR-Bereich für jeden Knotenpool oder einen separaten CIDR-Bereich für jeden Knoten angeben wollen. Weitere Informationen zu ClusterCIDRConfig und Beispiele zu seiner Verwendung finden Sie unter Benutzerdefinierte Ressource „ClusterCIDRConfig“.

Die folgende ClusterCIDRConfig gibt beispielsweise einen CIDR-Bereich für einen Knotenpool mit dem Namen "workers" an.

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"

Die folgende ClusterCIDRConfig gibt einen CIDR-Bereich für einen einzelnen Knoten mit der IP-Adresse 10.2.0.5 an:

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"

Erstellen eines Dual-Stack-Diensts vom Typ ClusterIP

Hier ist ein Manifest für ein 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"

Speichern Sie das Manifest in einer Datei mit dem Namen my-deployment.yaml und erstellen Sie die Bereitstellung:

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

Ersetzen Sie CLUSTER_KUBECONFIG durch den Pfad der kubeconfig-Datei des Clusters.

Dies ist ein Manifest für einen Dienst vom Typ 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

Im Zusammenhang mit dieser Übung sind dies die wichtigsten Punkte zum Verständnis des vorherigen Dienstmanifests:

  • Das Feld ipFamilyPolicy ist auf RequireDualStack gesetzt. Dies bedeutet, dass dem Dienst sowohl IPv6- als auch IPv4-ClusterIP-Adressen zugewiesen werden.

  • Im ipFamilies-Feld wird zuerst die IPv6-Familie und dann die IPv4-Familie angegeben. Das bedeutet, dass spec.ClusterIP für den Dienst eine IPv6-Adresse ist, die aus dem Clustermanifest von clusterNetwork.services.cidrBlocks ausgewählt wird.

Speichern Sie das Manifest in einer Datei mit dem Namen my-cip-service.yaml und erstellen Sie den Dienst:

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

Listen Sie Details zum Dienst auf:

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

In der Ausgabe werden die Cluster-IP-Adressen für den Dienst angezeigt. Beispiel:

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

Rufen Sie auf einem Clusterknoten den Dienst auf:

curl IPV4_CLUSTER_IP
curl [IPV6_CLUSTER_IP]

In der Ausgabe wird die Nachricht „Hello world“ angezeigt:

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

Erstellen eines Dual-Stack-Diensts vom Typ LoadBalancer

Dies ist ein Manifest für einen Dienst vom Typ 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

Speichern Sie das Manifest in einer Datei mit dem Namen my-lb-service.yaml und erstellen Sie den Dienst:

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

In Ihrem Clustermanifest haben Sie einen Bereich von IPv6-Adressen und einen Bereich von IPv4-Adressen für Dienste vom Typ LoadBalancer angegeben:

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

Ihrem Dienst wird eine externe IPv4-Adresse zugewiesen, die aus dem IPv4-Bereich ausgewählt wird, und eine externe IPv6-Adresse, die aus dem IPv6-Bereich ausgewählt wird.

Listen Sie Details zum Dienst auf:

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

In der Ausgabe sehen Sie die externen Adressen für den Dienst. Beispiel:

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

Mögliche Werte für ipFamilyPolicy

Wenn Sie einen Dual-Stack-Dienst erstellen, können Sie ipFamilyPolicy auf einen der folgenden Werte setzen:

  • SingleStack: Der Controller weist dem Dienst eine Cluster-IP-Adresse zu, die aus dem ersten Bereich im Clustermanifest unter clusterNetwork.services.cidrBlocks ausgewählt wird.

  • PreferDualStack: Der Controller weist dem Service IPv4- und IPv6-Cluster-IP-Adressen zu. Diese werden aus den Bereichen ausgewählt, die im Clustermanifest unter clusterNetwork.services.cidrBlocks angegeben sind. Ist der Cluster kein Dual-Stack-Cluster, ist sein Verhalten wie bei SingleStack.

  • RequireDualStack: Der Controller weist dem Service IPv4- und IPv6-Cluster-IP-Adressen zu. Diese werden aus den Bereichen ausgewählt, die im Clustermanifest unter clusterNetwork.services.cidrBlocks angegeben sind. Er legt den Wert von spec.clusterIP anhand der ersten Adressfamilie fest, die im Dienstmanifest unter ipFamilies angegeben ist.

Weitere Informationen

Weitere Informationen zum Erstellen von Dual-Stack-Diensten finden Sie unter Dual-Stack-Optionen in neuen Diensten.