Configurer plusieurs interfaces réseau pour des pods

Ce document explique comment configurer Google Distributed Cloud pour fournir plusieurs interfaces réseau à plusieurs cartes d'interface réseau pour vos pods. La fonctionnalité de cartes d'interface réseau multiples pour les pods peut aider à distinguer le trafic du plan de contrôle de celui du plan de données, créant ainsi une isolation entre les plans. Des interfaces réseau supplémentaires permettent également d'utiliser la fonctionnalité de multidiffusion pour vos pods. L'utilisation de plusieurs cartes d'interface réseau pour les pods est compatible avec les clusters d'utilisateur, mais n'est pas autorisée pour les clusters d'administrateur.

L'isolation du plan réseau est importante pour les systèmes qui utilisent la virtualisation des fonctions réseau (NFV), telles les réseaux définis par logiciel dans un réseau étendu (SD-WAN), un agent de sécurité des accès au cloud (CASB) ou les pare-feu nouvelle génération (NG-FW). Ces types de NFV reposent sur l'accès à plusieurs interfaces pour séparer les plans de contrôle et de données.

La configuration de plusieurs interfaces réseau permet d'associer des interfaces réseau à des pools de nœuds, ce qui peut offrir des performances accrues. Par exemple, un cluster peut contenir une combinaison de types de nœuds. Lorsque vous regroupez des machines hautes performances dans un pool de nœuds, vous pouvez ajouter des interfaces supplémentaires au pool de nœuds pour améliorer le flux de trafic.

Configurer plusieurs interfaces réseau

En règle générale, la configuration de plusieurs interfaces réseau dans vos pods comporte trois étapes :

  1. Activez la carte d'interface réseau multiples pour votre cluster d'utilisateur en utilisant les champs multipleNetworkInterfaces et enableDataplaneV2 dans le fichier de configuration du cluster.

  2. Spécifiez des interfaces réseau dans la section additionalNodeInterfaces du fichier de configuration du cluster et créez une ou plusieurs ressources personnalisées NetworkAttachmentDefinition.

  3. Attribuez des interfaces réseau aux pods avec l'annotation k8s.v1.cni.cncf.io/networks.

Activer plusieurs cartes d'interface réseau

Activez plusieurs cartes d'interface réseau pour vos pods en définissant les champs multipleNetworkInterfaces et enableDataplaneV2 dans le fichier de configuration du cluster d'utilisateur sur true.

apiVersion: v1
multipleNetworkInterfaces: true
enableDataplaneV2: true
  ...

Spécifier des interfaces réseau

Dans le fichier de configuration du cluster, spécifiez des interfaces réseau supplémentaires pour les nœuds dans la section additionalNodeInterfaces.

Par exemple, voici une partie d'un fichier de configuration de cluster d'utilisateur affichant une interface réseau de nœud supplémentaire :

apiVersion: v1
multipleNetworkInterfaces: true
enableDataplaneV2: true
network:
  serviceCIDR: "10.96.0.0/20"
  podCIDR: "192.168.0.0/16"
  vCenter:
    networkName: network-private310
  ...
  # New multiple network configs
  additionalNodeInterfaces:
  - networkName: "gke-network-1"
    ipBlockFilePath: "my-block-yaml"
    type: static

Après avoir créé un cluster avec la configuration précédente, vous devez créer une ou plusieurs ressources personnalisées NetworkAttachmentDefinition (NAD) dans votre cluster d'utilisateur où vous spécifiez des interfaces réseau supplémentaires. Les NetworkAttachmentDefinitions correspondent aux réseaux disponibles pour vos pods. L'exemple suivant illustre un fichier manifeste pour un objet NetworkAttachmentDefinition :

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: gke-network-1
  namespace: default
spec:
  config: '{
  "cniVersion":"0.3.0",
  "type": "ipvlan",
  "master": "ens224", # defines the node interface that this Pod interface would map to
  "mode": "l2",
  "ipam": {
    "type": "whereabouts",
    "range": "172.16.0.0/24"
   }
}'

Enregistrez le fichier manifeste en tant que fichier YAML, par exemple my-nad.yaml, puis créez l'objet NetworkAttachmentDefinition :

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] apply -f my-nad.yaml

Attribuer des interfaces réseau à un pod

Utilisez l'annotation k8s.v1.cni.cncf.io/networks pour attribuer une ou plusieurs interfaces réseau à un pod. Chaque interface réseau est spécifiée avec un espace de noms et le nom d'une NetworkAttachmentDefinition, séparés par une barre oblique (/). Utilisez une liste séparée par des virgules pour spécifier plusieurs interfaces réseau.

Dans l'exemple suivant, deux interfaces réseau sont attribuées au pod samplepod. Les interfaces réseau sont spécifiées par les noms de deux éléments NetworkAttachmentDefinitions, gke-network-1 et gke-network-2, créés dans l'espace de noms default.

---
apiVersion: v1
kind: Pod
metadata:
  name: samplepod
  annotations:
    k8s.v1.cni.cncf.io/networks: default/gke-network-1,default/gke-network-2
spec:
  containers:
  ...

Restreindre les interfaces réseau à un ensemble de nœuds

Si vous ne souhaitez pas qu'un objet NetworkAttachmentDefinition soit applicable à l'ensemble d'un cluster, vous pouvez limiter ses fonctionnalités à un ensemble de nœuds.

Vous pouvez regrouper les nœuds de cluster en utilisant le libellé standard attribué au nœud ou votre propre libellé personnalisé. Vous pouvez ensuite spécifier le libellé de nœud dans le fichier manifeste NetworkAttachmentDefinition à l'aide de l'annotation k8s.v1.cni.cncf.io/nodeSelector. GKE sur VMware force le déploiement de tous les pods faisant référence à cette ressource personnalisée sur les nœuds portant cette étiquette.

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  annotations:
    k8s.v1.cni.cncf.io/nodeSelector: LABEL_KEY=LABEL_VALUE
  name: gke-network-1
spec:
...

L'exemple suivant montre le libellé my-label=multinicNP indiqué sur le NetworkAttachmentDefinition et force le déploiement de tous les pods auxquels le réseau gke-network-1 est attribué sur les nœuds portant ce libellé.

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  annotations:
    k8s.v1.cni.cncf.io/nodeSelector: my-label=multinicNP
  name: gke-network-1
spec:
...

Pour appliquer un libellé personnalisé à un nœud, utilisez la commande kubectl label nodes :

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] label nodes NODE_NAME LABEL_KEY=LABEL_VALUE 

Remplacez les éléments suivants :

  • NODE_NAME : nom du nœud auquel vous ajoutez un libellé.
  • LABEL_KEY : clé à utiliser pour le libellé.
  • LABEL_VALUE : valeur du libellé.

Dans cet exemple, le libellé environment=production est attribué au nœud my-node :

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] label nodes my-node environment=production

Enjeux de sécurité

Une NetworkAttachmentDefinition fournit un accès complet à un réseau. Par conséquent, les administrateurs de cluster doivent faire preuve de prudence lorsqu'ils fournissent un accès de création, de mise à jour ou de suppression à d'autres utilisateurs. Si un NetworkAttachmentDefinition donné doit être isolé, vous pouvez spécifier lors de sa création un espace de noms autre que celui par défaut où seuls les pods de cet espace de noms peuvent accéder.

Dans le schéma suivant, les pods de l'espace de noms default ne peuvent pas accéder à l'interface réseau de l'espace de noms privileged.

Utiliser des espaces de noms pour isoler le trafic réseau

Plug-ins CNI acceptés

Cette section répertorie les plug-ins CNI compatibles avec la fonctionnalité à plusieurs cartes d'interface réseau pour Google Distributed Cloud. Utilisez uniquement les plug-ins suivants lorsque vous spécifiez une NetworkAttachmentDefinition.

Création d'interfaces :

  • ipvlan
  • macvlan
  • bridge

Plug-ins meta :

  • portmap
  • sbr
  • tuning

Plug-ins IPAM :

  • host-local
  • static
  • whereabouts

Configuration de la route

Un pod auquel est associé une ou plusieurs NetworkAttachmentDefinitions possède plusieurs interfaces réseau. Par défaut, la table de routage de cette situation est étendue avec les interfaces supplémentaires disponibles localement, uniquement à partir des NetworkAttachmentDefinitions attribuées. Les paquets liés à la passerelle par défaut sont toujours configurés pour utiliser l'interface par défaut du pod, eth0. Vous pouvez modifier ce comportement à l'aide des plug-ins CNI suivants :

  • sbr
  • static
  • whereabouts

Par exemple, vous souhaiterez peut-être que la majeure partie du trafic passe par la passerelle par défaut, ce qui signifie qu'il passe par l'interface réseau par défaut. Cependant, vous souhaiterez peut-être qu'un trafic spécifique passe par l'une des interfaces autres que celles par défaut. Le trafic peut être difficile à distinguer en fonction de l'adresse IP de destination (routage normal), car le même point de terminaison est disponible sur les deux types d'interfaces. Dans ce cas, le routage basé sur la source (SBR, source based routing) peut s'avérer utile.

Plug-in SBR

Le plug-in sbr permet à l'application de contrôler les décisions de routage. L'application contrôle l'élément utilisé en tant qu'adresse IP source de la connexion qu'elle établit. Lorsque l'application choisit d'utiliser l'adresse IP de la NetworkAttachmentDefinition comme adresse IP source, les paquets parviennent à l'autre table de routage sbr configurée. La table de routage sbr envoie le trafic via sa propre passerelle par défaut, qui passe par l'interface de NetworkAttachmentDefinition. L'adresse IP de la passerelle par défaut dans cette table est contrôlée avec le champ gateway dans les plug-ins whereabouts ou static. Le plug-in sbr s'exécute en tant que plug-in en chaîne. Pour en savoir plus sur le plug-in sbr, y compris sur son utilisation, consultez la page Plug-in de routage basé sur la source.

L'exemple suivant montre "gateway":"21.0.111.254" défini dans whereabouts et sbr défini en tant que plug-in en chaîne après ipvlan :

# ip route
default via 192.168.0.64 dev eth0  mtu 1500
192.168.0.64 dev eth0 scope link
# ip route list table 100
default via 21.0.111.254 dev net1
21.0.104.0/21 dev net1 proto kernel scope link src 21.0.111.1

Plug-ins de gestion des adresses IP statiques et relatifs à l'emplacement

Le plug-in whereabouts est en fait une extension du plug-in static. Tous deux partagent la même configuration de routage. Pour obtenir un exemple de configuration, consultez la page Plug-in de gestion des adresses IP statiques. Vous pouvez définir une passerelle et une route à ajouter à la table de routage du pod. Vous ne pouvez pas modifier la passerelle par défaut du pod de cette manière.

L'exemple suivant montre l'ajout de "routes": [{ "dst": "172.31.0.0/16" }] dans la ressource personnalisée NetworkAttachmentDefinition :

# ip route
default via 192.168.0.64 dev eth0  mtu 1500
172.31.0.0/16 via 21.0.111.254 dev net1
21.0.104.0/21 dev net1 proto kernel scope link src 21.0.111.1
192.168.0.64 dev eth0 scope link

Exemples de configuration

Cette section présente quelques configurations réseau courantes compatibles avec la fonctionnalité de cartes d'interface réseau multiples.

Un seul rattachement de réseau utilisé par plusieurs pods :

Rattachement de réseau unique utilisé par plusieurs pods.

Plusieurs rattachements de réseau utilisés par un même pod :

Plusieurs rattachements de réseau utilisés par un seul pod.

Plusieurs rattachements de réseau pointant vers la même interface utilisée par un seul pod :

Plusieurs rattachements de réseau pointant vers la même interface utilisée par un seul pod.

Même rattachement de réseau utilisé plusieurs fois par un seul pod :

Un même rattachement de réseau est utilisé plusieurs fois par un seul pod.

Résoudre les problèmes

Si des interfaces réseau supplémentaires sont mal configurées, les pods auxquels elles sont attribuées ne démarrent pas. Cette section explique comment trouver des informations pour résoudre les problèmes liés à la fonctionnalité de cartes d'interface réseau multiples.

Vérifier les événements du pod

Multus signale les échecs via des événements de pod Kubernetes. Exécutez la commande kubectl describe suivante pour afficher les événements d'un pod donné :

kubectl describe pod POD_NAME

Vérifier les journaux

Vous pouvez accéder aux journaux Whereabouts et Multus de chaque nœud aux emplacements suivants :

  • /var/log/whereabouts.log
  • /var/log/multus.log

Examiner les interfaces du pod

Exécutez la commande kubectl exec pour vérifier les interfaces de votre pod. Une fois les NetworkAttachmentDefinitions appliquées, les interfaces du pod se présentent comme suit :

user@node1:~$ kubectl exec samplepod-5c6df74f66-5jgxs -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: net1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether 00:50:56:82:3e:f0 brd ff:ff:ff:ff:ff:ff
    inet 21.0.103.112/21 scope global net1
       valid_lft forever preferred_lft forever
38: eth0@if39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 36:23:79:a9:26:b3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.2.191/32 scope global eth0
       valid_lft forever preferred_lft forever

Obtenir l'état du pod

Exécutez la commande kubectl get pour récupérer l'état du réseau d'un pod donné :

kubectl get pods POD_NAME -oyaml

Voici un exemple de résultat indiquant l'état d'un pod comportant plusieurs réseaux :

apiVersion: v1
kind: Pod
metadata:
  annotations:
    k8s.v1.cni.cncf.io/network-status: |-
      [{
          "name": "",
          "interface": "eth0",
          "ips": [
              "192.168.1.88"
          ],
          "mac": "36:0e:29:e7:42:ad",
          "default": true,
          "dns": {}
      },{
          "name": "default/gke-network-1",
          "interface": "net1",
          "ips": [
              "21.0.111.1"
          ],
          "mac": "00:50:56:82:a7:ab",
          "dns": {}
      }]
    k8s.v1.cni.cncf.io/networks: gke-network-1