Reseau

Cet article est une présentation des différentes solutions réseaux compatibles avec Kubernetes, incluant une comparaison de ces solutions.

Public visé : Administrateurs systèmes ayant des connaissances sur Kubernetes et le réseau.

Par Maud Laurent, Administratrice Système @Objectif Libre

Comparatif des solutions réseaux pour Kubernetes

Introduction : fonctionnement de Kubernetes

Kubernetes impose aux réseaux de suivre les règles suivantes :

  • Tous les pods peuvent communiquer entre eux sans NAT
  • Les nœuds peuvent communiquer avec les pods (et inversement) sans NAT
  • L’IP vue par le conteneur est la même que l’IP vue par les composants externes
Il existe deux types de mise en place réseaux :
  1. soit l’utilisation du réseau k8s proposé par défaut
  2. soit l’utilisation de CNI et de ses plugins – la solution la plus fréquente et sur laquelle porte notre comparatif.

Réseau k8s par défaut

La première solution pour configurer le réseau consiste à créer sur chaque hôte un bridge virtuel avec une plage d’IP, puis à ajouter sur chaque hôte les routes vers les autres hôtes à la main. En utilisant une solution Google ou Amazon, la configuration manuelle est possible, mais lorsqu’on s’en éloigne, il devient plus difficile de gérer ces configurations.

Ci-dessous un exemple de configuration pour la création d’un bridge sur un seul nœud avec une seule interface :

brctl addbr kubbr1
ip link add veth1kubbr1 type veth peer name kubbr
ip addr add 10.10.1.1/24 dev veth1kubbr1
ip link set veth1kubbr1 up
brctl addif kubbr1 veth1kubbr1
ip link set up kubbr1
Résultat des commandes ci-dessus

Solution utilisant CNI et un plugin réseau

La seconde option pour mettre en place le réseau dans Kubernetes est de passer par le Container Network Interface (CNI) et un plugin réseau. Les configurations de base sont faites automatiquement. La création et la gestion du réseau sont grandement facilitées.

Le réseau sous Linux peut être défini de deux façons différentes : l’underlay et l’overlay. Il est possible avec Kubernetes d’utiliser les deux.

  • L’underlay est le réseau physique, matériel composé des switchs, routeurs…
  • L’overlay est le réseau virtuel composé de vlan, veth (interface virtuelle) et VxLAN, il encapsule l’architecture réseau matériel. Le fonctionnement avec l’overlay est un peu plus lent qu’en underlay, il crée des tunnels entre les hôtes ce qui réduit les MTU disponibles.

A propos de Container Network Interface

CNI est un ensemble de spécifications et librairies (en Go) ayant pour but de faciliter l’intégration de plugins réseau. Un plugin CNI doit être exécutable par le système de management de conteneur utilisé. Il gère la mise en place de l’interface (ainsi que son IP) dans un namespace, et sa configuration avec l’hôte (connexion avec un bridge, gestion des routes). La configuration du type de réseau utilisé se fait dans un fichier /etc/cni/net.d/xx-mynet.conf. On y spécifie généralement le nom du réseau, son type (bridge, vlan, ipvlan, loopback, macvlan, ptp) ainsi que son IPam (IP address management : dhcp, host-local) avec un type, le sous-réseau et les routes rattachées. Les plugins réseaux créent des types qui leur sont propres en se basant sur ces informations.

 


K8s comparaison de différentes solutions CNI + plugin

Les solutions de réseaux compatibles avec Kubernetes sont nombreuses, et toutes utilisent ou créent un plugin CNI.

Les trois solutions les plus utilisées sont Calico, Flannel et WeaveNet. Deux autres, Cilium et Contiv, proposent aussi des fonctionnalités intéressantes. Dans cet article, nous allons détailler les différentes solutions existantes et leur fonctionnement avec Kubernetes.

Accès rapide : CalicoCiliumContivFlannelWeaveNet

Note

Les différents tests de déploiement ont été réalisés avec Kubespray.

Calico

Présentation

Logo CalicoCalico est une solution réseau pour Kubernetes qui se veut simple, scalable et sécurisée. Côté réseau, elle supporte l’adressage ipv4 et ipv6. Elle utilise le composant de Kubernetes kube-proxy pour gérer les règles de filtrage. Kube-proxy utilise les iptables Linux pour créer des règles de filtrage sur les réseaux et ainsi isoler les conteneurs.

Pour rentrer dans le détail : Calico fonctionne par défaut en Ethernet (L2). Il peut se configurer pour utiliser IPinIP (L3). IPinIP est un tunnel IP, un paquet IP encapsule un autre paquet IP en ajoutant en header un champ « SourceIP » qui sert d’entrée pour le tunnel et le champ « Destination » qui sert de point de sortie. Calico offre deux configurations pour IPinIP :

  • l’option always avec laquelle tout le trafic est encapsulé
  • ou crossSubnet avec laquelle seul le trafic entre les sous-réseaux est encapsulé.

Fonctionnement

Calico utilise différents composants :

  • Felix : agent Calico, disposé sur chaque hôte fournissant des points de sortie (interface vers l’extérieur), il partage les tables d’adressage ip et les routes entre les nœuds.
  • BIRD (bgp) : client (et route reflector) utilisé avec confd pour BGP. Border Gateway Protocol (BGP) est un protocole de routage qui partage ses informations de routage (tables) avec des systèmes autonomes (routeurs). BIRD est un daemon qui agit comme un routeur dynamique utilisé par Calico avec BGP. Il est utilisé pour centraliser la distribution des routes.
  • confd : monitore etcd pour les configurations et changements de configuration BGP. Il génère automatiquement les configurations BIRD.
  • etcd ou API Kubernetes : etcd est un outil de sauvegarde de type clef-valeur utilisé pour stocker les données.

Utilisation

Calico supporte les networkPolicies de Kubernetes, sa configuration se fait en yaml (dans un fichier de configuration /etc/calico/calicoctl.cfg). La configuration est possible avec la commande calicoctl.

Les différentes ressources utilisables pour la configuration sont : BGPPeer, BGPConfiguration, HostEndpoint, NetworkPolicy, GlobalNetworkPolicy, IPPool : réseaux utilisés pour les réseaux Kubernetes, Profile, FelixConfiguration et WorkloadEndpoint. Il s’agit des différentes ressources de Calico, elles servent pour la configuration (et se place dans le champs kind, voir l’exemple ci-dessous). Chacune à une fonction spécifique.

Réseau Calico

Il est possible de créer des sous-réseaux ou nouveaux réseaux Calico avec la ligne de commande calicoctl.

Voici un exemple de création d’un réseau avec Calico :

calicoctl create -f -<<EOF
- apiVersion: v1 # ou projectcalico/v3
  kind: ipPool
  metadata:
    cidr: 10.12.13.0/24
  spec:
    ipip:
      enabled: true
      mode: always
    nat-outgoing: true
EOF

Le réseau et les sous-réseaux Calico peuvent se représenter comme dans l’image ci-dessous. Dans cet exemple, il y a deux sous-réseaux, et chaque sous-réseau est défini par rapport au cluster entier et non par machine composant le cluster. Deux conteneurs peuvent faire partie d’un même réseau et être hébergés sur deux machines différentes.

Le choix du réseau est possible et se fait avec l’annotation suivante dans la partie metadata du template du pod lors du déploiement d’un yaml avec Kubernetes :

metadata:
   annotations:
     "cni.projectcalico.org/ipv4pools": "[\"10.112.12.0/24\"]" # ou ipv6pools si ipv6 est utilisé

Déploiement

Calico est installé en DaemonSet avec un conteneur sur chaque nœud et un « calico-controller » sur le master. Chaque nœud du cluster a 3 composants de Calico installés : Felix, BIRD et confd ; le master a en plus un contrôleur. Chaque envoi de données entre les nœuds se fait avec les tunnels IPinIP vus précédemment.

Réseau Calico dans le cas d’un cluster 3 noeuds sur le même réseau

Retrouvez la documentation : https://docs.projectcalico.org/v3.1/usage/

Cilium

Note

Kernel ≥ 4.8

Présentation

Cilium est une solution réseau pour Kubernetes fonctionnant sur les couches L3/L4 pour la partie réseaux et L7 pour la partie application. Le fonctionnement sur cette dernière couche permet d’ajouter des règles de filtrage haut niveau pour les applications web par exemple. Elle supporte IPv4 et IPv6. Cilium est actuellement la seule solution réseau à effectuer un filtrage avec BPF.

BPF – Berkeley Packet Filter

BPF est une solution de filtrage de paquets qui remplace la solution iptables. Le filtrage ne s’effectue plus au niveau applicatif, mais au niveau du kernel, ce qui le rend plus rapide, plus fonctionnel et plus sécurisé.

Cilium utilise BPF pour créer et appliquer les règles de filtrage sur les paquets, aucune règle iptable n’est créée. Les filtres sont plus efficaces et plus flexibles.

Fonctionnement

Cilium fonctionne avec cilium-agent lancé sur chaque nœud. Cilium-agent gère les opérations et les filtres pour les partager avec l’hôte. Il compile les règles BPF pour ensuite les passer au kernel de l’hôte.

Utilisation

Cilium peut fonctionner avec un réseau overlay (figure1) ou avec le routage natif (figure2). L’ipv4 et l’ipv6 sont supportés dans les deux cas. Le mode overlay est le mode par défaut. Comme on peut le voir sur l’image ci-dessous, un sous-réseau est attribué à chaque nœud. Le routage natif est plus complexe d’utilisation. Chaque paquet sortant du réseau local est envoyé sur le système de routage du kernel qui s’occupe de rediriger les paquets. Les règles de sécurité sont gérées pour ipv6 ; en ce qui concerne ipv4, il faut utiliser les règles CIDR. L’ip forwarding est activé par Cilium, mais les règles de redirection doivent être gérées manuellement ou via un protocole de routage comme BGP.

Réseau Cilium
Réseau Cilium

Cilium ajoute ses propres network policies utilisables avec kubectl get ciliumnetworkpolicy (ou cnp) pour filtrer les paquets de couche L7 comme http et kafka. Il applique automatiquement les networks policies de Kubernetes. Toutes ces configurations peuvent se faire en yaml. L’exemple ci-dessous est une règle de filtrage L7 faite avec les CiliumNetworkPolicy pour filtrer du http qui autorise l’accès à « / » aux pods ayant le label ‘access’ à true.

 apiVersion: "cilium.io/v2"
 kind: CiliumNetworkPolicy
 description: "Allow HTTP GET / from app=web to access=true"
 metadata:
   name: "rule1"
 spec:
   endpointSelector:
     matchLabels:
       app: web
   ingress:
   - fromEndpoints:
     - matchLabels: # vérification des labels
         access: "true"
     toPorts:
     - ports:
       - port: "80"
         protocol: TCP
       rules:
         http:
         - method: "GET"
           path: "/"

Une network policy créée par Kubernetes est visible avec la commande cilium policy get. Le fichier est au format json. Ci-dessous un exemple d’une networkPolicy créée en yaml et appliquée avec Kubernetes et son enregistrement au format json retourné par la commande cilium policy get.

Cilium network policy yaml et json (format de sauvegarde)

Plusieurs commandes permettent de voir l’état des données de Cilium. La liste est disponible ici http://cilium.readthedocs.io/en/latest/cheatsheet/, quelques exemples ci-dessous :

  kubectl exec -n kube-system cilium-qpxvw
   -- ls -al /sys/fs/bpf/tc/globals/ # liste les entrées bpf
   -- cilium bpf policy list -n 19898 # affiche la policy ayant ce numéro (version type iptables)
   -- cilium status # donne le status du noeud (ou --all-containers pour tous)
   -- cilium policy get # liste toutes les policies reçue par cilium (format json)

Cilium propose un système d’identité permettant de mettre un niveau de priorité et des tags utilisés sur des pods.

Cilium fonctionne avec kube-proxy. Mais lorsque ClusterIP (load balancing pour le trafic entre pods) est implémenté, Cilium fonctionne comme proxy en ajoutant et supprimant des règles BPF (sur chaque nœud) en fonction de l’évolution des machines sur le cluster. Lorsqu’il est utilisé avec Istio, il utilise Envoy comme proxy.

Déploiement

Cilium se déploie en tant que pod dans Kubernetes avec un DaemonSet. Il crée un bridge sur chaque nœud. Ces bridges communiquent avec des veth pour chaque pod.

Retrouvez la documentation : http://cilium.readthedocs.io/en/latest/

Contiv

Présentation

Contiv est une solution réseau pour Kubernetes proposée par Cisco et fonctionnant en VxLAN ou sur la couche L3 avec BGP. Contiv supporte IPv4 et IPv6. Il propose aussi une intégration des ACI (Application Centric Infrastructure) Cisco, mais Cisco propose une solution réseau ACI pour Kubernetes spécialement conçue pour ce dernier. Il se base sur OpenVSwitch pour les pipelines et utilise etcd pour la sauvegarde clef-valeur.

Fonctionnement

Contiv se lance avec deux composants :

  1. netplugin est installé sur chaque nœud. Il implémente les CNI utilisées, il gère aussi les créations d’interfaces pour les conteneurs, les allocations d’IP…
  2. netmaster n’est installé que sur le(s) master(s) du cluster en DaemonSet. Il s’occupe de gérer les requêtes en simultané, et des routes envoyées aux composants netplugin.

Les deux composants précédents utilisent les IP de leurs hôtes pour communiquer. Un vlan contiv est crée par défaut, regroupant tous les nœuds du cluster.

Utilisation

Plusieurs réseaux peuvent être créés avec la commande netctl. Tous sont utilisables par n’importe quel nœud. Les réseaux utilisables sont visibles avec la commande netctl net ls. Les ips sont récupérées dans les pools ayant le Nw Type à data.

La spécification du réseau se fait dans les labels lors de la création de yaml Kubernetes.

  labels:
    io.contiv.tenant: default
    io.contiv.network: contiv-net

Contiv fonctionne avec de l’overlay pour définir les sous-réseaux, un sous-réseau n’est donc pas uniquement sur un nœud, il est partagé dans tout le cluster ; ainsi, comme on peut le voir sur la figure ci-dessous, plusieurs machines peuvent faire partie d’un même réseau en étant sur différents hôtes.

Réseau Contiv (d’après la documentation)

Contiv ne supporte pas les network policies de Kubernetes, mais possède ses propres network policies avec sa propre API pour les règles de filtrage.

Il propose deux types de règles :

  1. Les règles réseaux de type Bandwith permettent de limiter la bande passante pour un groupe.
  2. Les règles réseaux de type Isolation permettent de créer une white-list ou black-list pour une application, ainsi que les actions pouvant être effectuées par le groupe (création, suppression, modification, vue).

La commande netctl permet de faire ces configurations, mais la création de ces règles est aussi faisable avec l’API web proposée par Contiv.

Cette interface permet aussi la gestion des tenants / des utilisateurs (authentification ldap possible) et des réseaux.

Note

Contiv est certifié plugin openshift.

Déploiement

Contiv se déploie en suivant le lien suivant : https://github.com/contiv/install#kubernetes-installation. Au final, ce sont des DaemonSet Kubernetes qui tournent sur le cluster.

Retrouvez la documentation : http://contiv.github.io/documents/gettingStarted/.

Flannel

 

Présentation

Flannel est une solution réseau pour Kubernetes fonctionnant avec plusieurs backends, VxLAN étant le backend recommandé (les autres sont plus expérimentaux) pour encapsuler les paquets. Seul l’IPv4 est supporté.

Fonctionnement

Flannel fonctionne avec etcd, notamment pour lire ses configurations et stocker les configurations réseaux. Il met en place des sous-réseaux sur chaque hôte grâce à un agent nommé flanneld.

Flannel crée un seul réseau VxLAN. Chaque nouveau pod est rattaché à ce VxLAN avec une veth. Flannel ne supporte pas le lancement de plusieurs réseaux sur un seul daemon, mais il est possible de lancer plusieurs daemon sur un seul hôte avec des configurations différentes.

Utilisation

Flannel créé un bridge cni0 sur chaque nœud et y attache des interfaces veth. Les pods ne sont créés que sur les minions, le master ne contient aucune instance (sauf les instances pour son fonctionnement qui utilisent l’ip rattaché au réseau externe). Chaque nœud a donc son sous-réseau du pool flannel. La communication est possible grâce aux VxLAN flannel créés sur tous les hôtes.

Réseau Flannel
Réseau Flannel

Il est possible d’activer avec VxLAN-GBP, le routage direct des paquets lorsque plusieurs hôtes sont sur le même réseau. Les réseaux VxLAN sont alors utilisés uniquement si les réseaux sont différents.

Flannel gère le trafic ipv4 uniquement entre les nœuds d’un cluster. Il se concentre sur le réseau et ne supporte pas les network policies de Kubernetes.

Déploiement

Flannel construit un DaemonSet par hôte. Avant de le déployer, il faut rajouter --allocate-node-cidrs=true --cluster-cidr=10.32.0.0/16 dans le fichier /etc/kubernetes/manifests/kube-controller-manager.manifest puis redémarrer kubelet. L’installation est décrite ici

Retrouvez la documentation : https://github.com/coreos/flannel#flannel

WeaveNet

 

Note

kernel ≥ 3.8, docker ≥1.10.0, Kubernetes ≥ 1.4, un master avec au moins 2 CPU.

Présentation

WeaveNet est une solution réseau proposant un plugin réseau (Weave CNI Plugin) pour Kubernetes fonctionnant avec des VxLAN en L2. Il utilise kube-proxy et kube-dns (son composant weave-DNS est désactivé dans le cas d’une intégration avec Kubernetes). Il supporte IPv4 et IPv6.

Fonctionnement

Contrairement à la plupart des solutions réseaux qui utilisent etcd pour stocker les données, WeaveNet les enregistre dans un fichier /weavedb/weave-netdata.db sur chaque pod créé par le DaemonSet. Chaque pod du DaemonSet possède l’adresse ip de l’interface physique du nœud sur lequel il est placé. Chaque pod contient 2 conteneurs weave et weave-npc (Network Policy Controller).

Le conteneur weave gère tout le fonctionnement de Weave sur le nœud. Le conteneur weave-npc s’occupe uniquement de la partie filtrage mis en place avec les NetworkPolicies de Kubernetes.

Utilisation

Les pods ne sont créés que sur les minions, le master ne contient aucune instance (sauf les instances pour son fonctionnement). WeaveNet supporte les NetworkPolicies de Kubernetes pour les règles de filtrage de type Ingress. Il propose une API web pour gérer le réseau (weave scope).

Réseau Weave

Comme on peut le voir sur l’image ci-dessous, sur chaque nœud est crée un bridge « weave ». Les conteneurs créés sont connectés grâce à une interface virtuelle sur le bridge de l’hôte. Tous ces bridges sont ensuite encapsulés en VxLAN pour communiquer avec le reste du cluster.

Réseau weaveNet
Réseau weaveNet

Il est possible de définir un mot de passe weave pour chiffrer la communication réseau directement lors de la création du DaemonSet avec des surcharges sur l’url (documentation : configuration options). Plus d’informations sur le chiffrement mis en place : https://github.com/weaveworks/weave/issues/3086

Il est possible de définir plusieurs sous-réseaux. L’allocation de sous-réseau se fait avec IPAM et peut se faire en mode :
  • seed : il faut disposer d’un premier cluster avec un nombre fixe de machines. Chaque machine va avoir un sous-réseau. Il est possible d’ajouter au cluster des machines, qui peuvent soit faire partie intégrante du cluster (nouvelle machine fixe), soit être intégrées dynamiquement selon les besoins (la machine peut donc être supprimée).
  • consensus : détermine les réseaux avec un algorithme de consensus (par défaut). Utilisé pour mettre en place weave en mode interactif ou pour un cluster fixe où l’ajout et la suppression de machines est rare. Ce mode utilise la commande weave prime qui met en place automatiquement l’allocation IP des nœuds.
  • observer : permet d’ajouter un nœud en tant qu’observateur. Ce dernier demandera un pool d’IP si besoin (en cas de surcharge d’un nœud) en demandant à un nœud de diviser son pool d’IP. Il permet d’ajouter dynamiquement des nœuds au cluster selon les besoins (auto-scaling).

Déploiement

Plusieurs installations sont possibles :

  • Chaque nœud lance WeaveNet directement sur la machine hôte.
  • WeaveNet peut être déployé directement en DaemonSet sur chaque nœud Kubernetes depuis ce lien. Tout est créé avec un fichier yaml récupérable et personnalisable.

Retrouvez la documentation : https://www.weave.works/docs/net/latest/kubernetes/kube-addon/

Conclusion

Les plugins réseaux sont un vrai atout et facilitent la gestion de celui-ci. Chacun correspond à des besoins différents.

Pour la mise en place d’un POC, ou si on souhaite mettre en place le réseau d’un cluster rapidement, il est préférable d’utiliser Flannel ou WeaveNet.

Calico, Contiv et Cilium proposent de faire directement de l’underlay (avec BGP notamment), évitant une encapsulation VxLAN.

Plusieurs solutions (Calico, Contiv) proposent l’ajout de plusieurs réseaux virtuels communs à tout le cluster, les pods créés peuvent ainsi être connectés à un même réseau et hébergés sur différent nœuds.

Cilium est plus axé sécurité et offre un filtrage niveau applicatif. Il utilise BPF pour filtrer niveau kernel. Le filtrage BPF offre de meilleures performances qu’un filtre avec iptables.

Récapitulatif

Solution Kubernetes networkPolicies IPv6 Couches utilisées Réseaux Déploiement Ligne de commandes Note
Calico Oui Oui L3 (IPinIP, BGP) Plusieurs réseaux sur le cluster DaemonSet calicoctl
Cilium Oui + ciliumNetworkPolicies Oui L3/L4 + L7 (filtrage) Sous-réseaux par nœud DaemonSet cilium (sur les pods DaemonSet) peu remplacer kube-proxy (filtrage avec BPF)
Contiv Non Oui L2 (VxLAN) / L3 (BGP) Plusieurs réseaux sur le cluster DaemonSet netctl
Flannel Non Non L2 (VxLAN) Plusieurs réseaux sur le cluster avec plusieurs daemon DaemonSet Non
Weave net Oui Oui L2 (VxLAN) Sous-réseaux par nœud DaemonSet Non chiffrement possible, n’utilise pas etcd