Ce document explique comment configurer des pods dans Google Kubernetes Engine (GKE) avec plusieurs interfaces réseau à l'aide des plug-ins Multus CNI, IPVLAN CNI et Whereabouts IPAM.
Le plug-in CNI IPVLAN fournit une connectivité de couche 2 pour les interfaces de pod supplémentaires, et le plug-in IPAM Whereabouts leur attribue des adresses IP de manière dynamique.
Cette configuration permet des configurations réseau avancées, telles que la séparation du trafic du plan de contrôle et du plan de données pour une isolation et une segmentation réseau améliorées.
Ce document s'adresse aux architectes cloud et aux spécialistes de la mise en réseau qui conçoivent et implémentent le réseau pour leur organisation. Pour en savoir plus sur les rôles courants et les exemples de tâches que nous citons dans le contenu Google Cloud , consultez Rôles utilisateur et tâches courantes de GKE.
Avant de lire ce document, assurez-vous de maîtriser les concepts suivants :
- Mise en réseau GKE
- Mise en réseau Kubernetes.
- Container Network Interface (CNI).
- IPVLAN.
- Gestion des adresses IP (IPAM)
Avantages de l'utilisation de Multus avec IPVLAN
La configuration de vos pods avec plusieurs interfaces réseau à l'aide de cette solution présente plusieurs avantages clés. Les principaux cas d'utilisation de la configuration de Multus avec IPVLAN en mode couche 2 concernent la segmentation du réseau qui nécessite une adjacence de couche 2 :
- Isolation du trafic : isolez différents types de trafic pour améliorer la sécurité et les performances. Par exemple, vous pouvez séparer le trafic de gestion sensible du trafic de données d'application.
- Séparation du plan de contrôle et du plan de données : dédiez l'interface réseau principale au trafic du plan de contrôle tout en dirigeant le trafic du plan de données à haut débit via une interface IPVLAN secondaire.
- Adjacence de couche 2 : respectez les exigences des applications qui ont besoin d'une connectivité de couche 2 directe entre les pods sur le même réseau secondaire.
Limites
Les pods configurés avec des interfaces Multus ne peuvent pas utiliser simultanément les fonctionnalités multiréseaux intégrées de GKE. La configuration réseau d'un pod doit utiliser Multus ou la fonctionnalité de multiréseau intégrée du cluster.
Fonctionnement de Multus avec IPVLAN et Whereabouts
Multus est un méta-plug-in CNI qui permet aux pods de se connecter à plusieurs réseaux. Multus sert de répartiteur et appelle d'autres plug-ins CNI pour configurer les interfaces réseau en fonction des ressources NetworkAttachmentDefinition. Vous définissez chaque réseau supplémentaire à l'aide d'un NetworkAttachmentDefinition, qui spécifie le plug-in CNI (tel qu'IPVLAN) et le plug-in IPAM (tel que Whereabouts) à utiliser pour ce réseau.
Le schéma suivant illustre l'architecture Multus avec les plug-ins IPVLAN et Whereabouts.Le plug-in Whereabouts fonctionne avec Multus et IPVLAN pour gérer la gestion des adresses IP (IPAM) pour les interfaces réseau supplémentaires des pods.
Ce diagramme montre deux nœuds, chacun avec un pod. Chaque pod possède une interface principale et une interface supplémentaire. Les deux interfaces principales se connectent à une carte d'interface réseau partagée, et les deux interfaces supplémentaires se connectent à une autre carte d'interface réseau partagée.
Lorsque vous utilisez Multus avec IPVLAN et Whereabouts sur GKE, les pods ont généralement la configuration d'interface suivante :
- Interface principale (
eth0) : GKE Dataplane V2 gère cette interface, qui fournit la connectivité par défaut du cluster. - Interfaces supplémentaires (
net1, etc.) : Multus gère ces interfaces. Multus appelle le plug-in CNI IPVLAN en mode couche 2 pour chaqueNetworkAttachmentDefinitionque vous spécifiez dans les annotations d'un pod. Cette configuration fournit une connectivité de couche 2 à un réseau VPC secondaire. - Gestion des adresses IP (IPAM) : vous configurez le plug-in Whereabouts IPAM dans
NetworkAttachmentDefinition. Le plug-in IPAM Whereabouts attribue dynamiquement des adresses IP aux interfaces IPVLAN supplémentaires à partir d'une plage prédéfinie.
Planification des pods avec plusieurs réseaux
Lorsque vous créez un pod et spécifiez un NetworkAttachmentDefinition dans ses annotations, le planificateur GKE place le pod uniquement sur un nœud capable de répondre aux exigences réseau. Le planificateur identifie les nœuds d'un pool de nœuds pour lesquels l'interface réseau secondaire requise est configurée. Ce processus d'identification des nœuds garantit que le planificateur planifie le pod sur un nœud pouvant se connecter au réseau supplémentaire et recevoir une adresse IP de la plage spécifiée.
Les sections suivantes vous guident dans la configuration de Multus avec les plug-ins IPVLAN et Whereabouts sur votre cluster GKE.
Avant de commencer
Avant de commencer, effectuez les tâches suivantes :
- Activez l'API Google Kubernetes Engine. Activer l'API Google Kubernetes Engine
- Si vous souhaitez utiliser Google Cloud CLI pour cette tâche, installez puis initialisez la gcloud CLI. Si vous avez déjà installé la gcloud CLI, obtenez la dernière version en exécutant la commande
gcloud components update. Il est possible que les versions antérieures de la gcloud CLI ne permettent pas d'exécuter les commandes de ce document.
- Installez l'outil de ligne de commande
kubectl. - Configurez un cluster GKE exécutant la version 1.28 ou ultérieure avec Dataplane V2, l'alias d'adresse IP et le multiréseau activés. Pour en savoir plus, consultez Configurer la compatibilité multiréseau pour les pods. L'activation du multiréseau active également les fonctionnalités de sous-réseau multi-IP et de stratégie HA d'adresse IP persistante, qui éliminent la nécessité de configurer manuellement la connectivité entre les nœuds.
- Utilisez une version validée par GKE de Multus CNI (par exemple, la version 4.2.1) pour assurer la compatibilité.
Configurer un VPC
Pour configurer le cloud privé virtuel (VPC) à utiliser avec Multus, y compris créer un sous-réseau pour la mise en réseau des nœuds et des plages secondaires pour la mise en réseau des pods, procédez comme suit :
Créez un VPC ou utilisez-en un existant :
gcloud compute networks create VPC_NAME \ --subnet-mode=customRemplacez
VPC_NAMEpar le nom du VPC.Créez un sous-réseau dans ce VPC :
gcloud compute networks subnets create SUBNET_NAME \ --range=PRIMARY_RANGE \ --network=VPC_NAME \ --region=REGION \ --secondary-range=SECONDARY_RANGE_NAME=SECONDARY_RANGE_CIDRRemplacez les éléments suivants :
SUBNET_NAME: nom du nouveau sous-réseau.PRIMARY_RANGE: plage CIDR principale du sous-réseau, telle que10.0.1.0/24. Cette commande utilise cette plage pour les interfaces de nœud.VPC_NAME: nom du VPC.REGION: région du sous-réseau, par exempleus-central1.SECONDARY_RANGE_NAME: nom de la plage d'adresses IP secondaire pour les pods du sous-réseau.SECONDARY_RANGE_CIDR: plage CIDR secondaire pour les pods, telle que172.16.1.0/24. Les interfaces supplémentaires sur les pods utilisent cette plage.
Cette commande crée un sous-réseau avec une plage CIDR principale pour une interface de nœud supplémentaire et une plage secondaire pour les interfaces de pod supplémentaires.
Créer un cluster GKE standard
Créez un cluster GKE Standard avec le multiréseau activé :
gcloud container clusters create CLUSTER_NAME \
--cluster-version=CLUSTER_VERSION \
--enable-dataplane-v2 \
--enable-ip-alias \
--enable-multi-networking
Remplacez les éléments suivants :
CLUSTER_NAME: nom du nouveau clusterCLUSTER_VERSION: version de votre cluster GKE. Vous devez utiliser la version 1.28 ou ultérieure.
L'activation du multiréseau vous permet de créer des pools de nœuds avec plusieurs interfaces réseau, ce qui est requis par Multus CNI.
Créer un pool de nœuds GKE Standard
Créez un pool de nœuds GKE Standard connecté à des réseaux VPC supplémentaires :
gcloud container node-pools create NODEPOOL_NAME \
--cluster CLUSTER_NAME \
--zone "ZONE" \
--additional-node-network network=VPC_NAME,subnetwork=SUBNET_NAME \
--additional-pod-network subnetwork=SUBNET_NAME,pod-ipv4-range=SECONDARY_RANGE_NAME,max-pods-per-node=8
Remplacez les éléments suivants :
NODEPOOL_NAME: nom du nouveau pool de nœuds.CLUSTER_NAME: nom du clusterZONE: zone du pool de nœuds, telle queus-central1-c.VPC_NAME: nom du VPC supplémentaire.SUBNET_NAME: nom du sous-réseau.SECONDARY_RANGE_NAME: nom de la plage d'adresses IP secondaire pour les pods du sous-réseau.
Cette commande crée un pool de nœuds dans lequel les nœuds disposent d'une interface réseau supplémentaire dans SUBNET_NAME, et les pods de ces nœuds peuvent utiliser des adresses IP de SECONDARY_RANGE_NAME.
Pour en savoir plus sur la création de clusters GKE avec des fonctionnalités multiréseaux, consultez Configurer la compatibilité multiréseau pour les pods.
Appliquer le déploiement Multus
Pour activer plusieurs interfaces réseau pour vos pods, installez le plug-in Multus CNI. Enregistrez le fichier manifeste suivant, qui inclut le DaemonSet et la définition de ressource personnalisée (CRD) requis, sous le nom multus-manifest.yaml :
apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: ippools.whereabouts.cni.cncf.io spec: group: whereabouts.cni.cncf.io names: kind: IPPool listKind: IPPoolList plural: ippools singular: ippool scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: description: IPPool is the Schema for the ippools API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: IPPoolSpec defines the desired state of IPPool properties: allocations: additionalProperties: description: IPAllocation represents metadata about the pod/container owner of a specific IP properties: id: type: string podref: type: string required: - id type: object description: Allocations is the set of allocated IPs for the given range. Its indices are a direct mapping to the IP with the same index/offset for the pools range. type: object range: description: Range is a RFC 4632/4291-style string that represents an IP address and prefix length in CIDR notation type: string required: - allocations - range type: object type: object served: true storage: true status: acceptedNames: kind: "" plural: "" conditions: [] storedVersions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.4.1 name: overlappingrangeipreservations.whereabouts.cni.cncf.io spec: group: whereabouts.cni.cncf.io names: kind: OverlappingRangeIPReservation listKind: OverlappingRangeIPReservationList plural: overlappingrangeipreservations singular: overlappingrangeipreservation scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: description: OverlappingRangeIPReservation is the Schema for the OverlappingRangeIPReservations API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: OverlappingRangeIPReservationSpec defines the desired state of OverlappingRangeIPReservation properties: containerid: type: string podref: type: string required: - containerid type: object required: - spec type: object served: true storage: true status: acceptedNames: kind: "" plural: "" conditions: [] storedVersions: [] --- kind: ConfigMap apiVersion: v1 metadata: name: multus-cni-config namespace: kube-system labels: app: gke-multinet data: cni-conf.json: | { "name": "multus-cni-network", "type": "multus", "confDir": "/etc/cni/net.d", "namespaceIsolation": true, "logLevel": "verbose", "logFile": "/var/log/multus.log", "kubeconfig": "/var/lib/kubelet/kubeconfig", "clusterNetwork": "gke-pod-network" } --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: network-attachment-definitions.k8s.cni.cncf.io spec: group: k8s.cni.cncf.io scope: Namespaced names: plural: network-attachment-definitions singular: network-attachment-definition kind: NetworkAttachmentDefinition shortNames: - net-attach-def versions: - name: v1 served: true storage: true schema: openAPIV3Schema: description: 'NetworkAttachmentDefinition is a CRD schema specified by the Network Plumbing Working Group to express the intent for attaching pods to one or more logical or physical networks. More information available at: https://github.com/k8snetworkplumbingwg/multi-net-spec' type: object properties: apiVersion: description: 'APIVersion defines the versioned schema of this represen tation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: 'NetworkAttachmentDefinition spec defines the desired state of a network attachment' type: object properties: config: description: 'NetworkAttachmentDefinition config is a JSON-formatted CNI configuration' type: string --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: multus-role rules: - apiGroups: ["k8s.cni.cncf.io"] resources: - '*' verbs: - '*' --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: whereabouts rules: - apiGroups: - whereabouts.cni.cncf.io resources: - ippools - overlappingrangeipreservations verbs: - get - list - watch - create - update - patch - delete - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - apiGroups: - coordination.k8s.io resources: - leases resourceNames: - whereabouts verbs: - '*' - apiGroups: [""] resources: - pods verbs: - list - get --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: multus-role-binding subjects: - kind: Group name: system:nodes roleRef: kind: ClusterRole name: multus-role apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: whereabouts-role-binding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: whereabouts subjects: - kind: ServiceAccount name: whereabouts-sa namespace: kube-system --- apiVersion: v1 kind: ServiceAccount metadata: name: whereabouts-sa namespace: kube-system --- apiVersion: apps/v1 kind: DaemonSet metadata: name: gke-multinet namespace: kube-system labels: app: gke-multinet spec: selector: matchLabels: app: gke-multinet template: metadata: labels: app: gke-multinet spec: priorityClassName: system-node-critical hostNetwork: true tolerations: - operator: Exists serviceAccountName: whereabouts-sa containers: - name: whereabouts-gc command: [/ip-control-loop] args: - "--log-level=debug" - "--enable-pod-watch=false" - "--cron-schedule=* * * * *" image: gcr.io/gke-release/whereabouts:v0.7.0-gke.3@sha256:2bb8450a99d86c73b262f5ccd8c433d3e3abf17d36ee5c3bf1056a1fe479e8c2 env: - name: NODENAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - name: WHEREABOUTS_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" initContainers: - name: install-multus-config image: gcr.io/gke-release/multus-cni:v4.2.1-gke.6@sha256:25b48b8dbbf6c78a10452836f52dee456514783565b70633a168a39e6d322310 args: - "--cni-conf-dir=/host/etc/cni/net.d" - "--multus-conf-file=/tmp/multus-conf/00-multus.conf" - "--multus-log-level=verbose" - "--multus-kubeconfig-file-host=/var/lib/kubelet/kubeconfig" - "--skip-multus-binary-copy=true" - "--skip-config-watch=true" resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" securityContext: privileged: true volumeMounts: - name: cni mountPath: /host/etc/cni/net.d - name: multus-cfg mountPath: /tmp/multus-conf - name: install-whereabouts command: ["/bin/sh"] args: - -c - > SLEEP=false /install-cni.sh image: gcr.io/gke-release/whereabouts:v0.7.0-gke.3@sha256:2bb8450a99d86c73b262f5ccd8c433d3e3abf17d36ee5c3bf1056a1fe479e8c2 env: - name: NODENAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - name: WHEREABOUTS_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace resources: requests: cpu: "100m" memory: "50Mi" limits: cpu: "100m" memory: "50Mi" securityContext: privileged: true volumeMounts: - name: cni mountPath: /host/etc/cni/net.d - name: cnibin mountPath: /host/opt/cni/bin - name: install-binary image: gcr.io/gke-release/multus-cni:v4.2.1-gke.6@sha256:25b48b8dbbf6c78a10452836f52dee456514783565b70633a168a39e6d322310 command: ["/gkecmd"] args: - "-operation=copy" - "-cni-bin-dir=/host/opt/cni/bin" resources: requests: cpu: "10m" memory: "100Mi" limits: cpu: "10m" memory: "100Mi" securityContext: privileged: true volumeMounts: - name: cnibin mountPath: /host/opt/cni/bin volumes: - hostPath: path: /var/lib/kubelet/kubeconfig type: File name: kubelet-credentials - name: cni hostPath: path: /etc/cni/net.d type: DirectoryOrCreate - name: cnibin hostPath: path: /home/kubernetes/bin type: DirectoryOrCreate - name: multus-cfg configMap: name: multus-cni-config items: - key: cni-conf.json path: 00-multus.conf updateStrategy: rollingUpdate: maxUnavailable: 2 type: RollingUpdate
Appliquez ensuite le fichier manifeste à votre cluster :
kubectl apply -f multus-manifest.yaml
Créer un fichier manifeste NetworkAttachmentDefinition
Pour permettre aux pods de se connecter à des réseaux supplémentaires, créez un fichier manifeste NetworkAttachmentDefinition. Ce fichier manifeste définit la manière dont les pods se connectent à un réseau et spécifie la plage d'adresses IP qu'un plug-in IPAM, tel que Whereabouts, attribue. Cette plage doit faire partie du sous-réseau qui connecte les interfaces réseau supplémentaires de vos nœuds.
Enregistrez ce fichier manifeste sous le nom
nad.yaml. Ce fichier manifeste utilise les plug-ins IPVLAN et Whereabouts.apiVersion: "k8s.cni.cncf.io/v1" kind: NetworkAttachmentDefinition metadata: name: NAD_NAME spec: config: '{ "cniVersion": "0.3.1", "plugins": [ { "type": "ipvlan", "master": "eth1", "mode": "l2", "ipam": { "type": "whereabouts", "range": SECONDARY_RANGE_NAME } } ] }'Le fichier manifeste comprend les champs suivants :
NAD_NAME: nom de votreNetworkAttachmentDefinition.master: nom de l'interface réseau secondaire du nœud, qui sert d'interfacemasterpour IPVLAN. Sur GKE, les interfaces réseau secondaires commencent généralement pareth1et sont nommées de manière séquentielle. Pour confirmer le nom de l'interface, connectez-vous à un nœud à l'aide de SSH et exécutez la commandeip addr.range: plage d'adresses IP pour les interfaces de pod, qui est identique à la plage IPv4 secondaire que vous avez créée pour les pods (SECONDARY_RANGE_NAME). Par exemple,172.16.1.0/24.
Appliquez le fichier manifeste à votre cluster :
kubectl apply -f nad.yaml
Associer des pods à d'autres réseaux
Pour associer un pod à un réseau supplémentaire, ajoutez l'annotation k8s.v1.cni.cncf.io/networks au fichier manifeste du pod. Pour plusieurs réseaux, fournissez une liste de noms NetworkAttachmentDefinition séparés par une virgule au format suivant :
<namespace>/<nad-name>.
L'exemple suivant montre un fichier manifeste de pod qui se rattache à NAD_NAME nommé NAD_NAME dans l'espace de noms default :NetworkAttachmentDefinition
apiVersion: v1
kind: Pod
metadata:
name: samplepod
annotations:
k8s.v1.cni.cncf.io/networks: default/NAD_NAME
spec:
containers:
- name: sample-container
image: nginx
Remplacez NAD_NAME par le nom de la NetworkAttachmentDefinition que vous avez créée.
Lorsque vous appliquez ce fichier manifeste, Kubernetes crée le pod avec une interface réseau supplémentaire (net1) connectée au réseau spécifié par NetworkAttachmentDefinition.
Vérifier l'adresse IP supplémentaire du pod
Pour vérifier que le pod reçoit une adresse IP supplémentaire après l'avoir associé à un réseau supplémentaire, inspectez les interfaces réseau du pod :
Pour inspecter
samplepodet vérifier l'adresse IP supplémentaire, utilisez la commande suivante :$kubectl describe pod PODNAMERemplacez
PODNAMEpar le nom de votre pod, par exemplesamplepod.Examinez le résultat. L'interface
eth0possède l'adresse IP principale du pod. Le plug-in Whereabouts attribue l'adresse IP supplémentaire à une autre interface, telle quenet1.Le résultat ressemble à ce qui suit :
k8s.v1.cni.cncf.io/network-status: [{ "name": "gke-pod-network", "interface": "eth0", "ips": [ "10.104.3.4" ], "mac": "ea:e2:f6:ce:18:b5", "default": true, "dns": {}, "gateway": [ "\u003cnil\u003e" ] },{ "name": "default/my-nad", "interface": "net1", "ips": [ "10.200.1.1" ], "mac": "42:01:64:c8:c8:07", "dns": {} }] k8s.v1.cni.cncf.io/networks: default/my-nadDans cet exemple,
10.104.5.19est l'adresse IP principale sureth0, et10.200.1.1est l'adresse IP supplémentaire surnet1.
Étapes suivantes
- En savoir plus sur Multus CNI
- En savoir plus sur le CNI IPVLAN
- En savoir plus sur Whereabouts IPAM