[k8s] Réseautage et traffic réseau

<<< Chap 8 | Sommaire | Chap 10>>>

Chap. 9 Réseautage et traffic réseau

I. Information réseau

Pour rappel, kubernetes ne s’occupe pas de relier en réseau les différents Pods entre eux. C’est le rôle du CNI (Container Network Interface).

Revoyez les informations du chapitre 2 de cette série d’articles, pour les détails de mon choix de « Cannal » comme plugin CNI.

1. Informations utiles

Il se peut qu’à un moment ou un autre, vous aurez besoin de demander de l’aide sur un forum dédié en cas de problème de réseau.

Je vous recommende de vous préparer à fournir au moins les informations ci-dessous,

  • Version de kubernetes
  • Version de calico*
  • Version de flannel*
  • Système d’exploitation et sa version
  • Adresse du réseau
  • CIDR

Remplacer Calico et Flannel par votre CNI. L’adresse du réseau et le CIDR, peuvent aider à mieux comprendre votre configuration réseau.

Ces informations peuvent être récupérées avec les commandes,

  • Version de kubernetes
$ apt show kubectl | grep -i version
Version: 1.19.3-00
  • Version de calico et flannel
$ kubectl get ds -A -o wide | grep flannel
kube-system canal 3 3 3 3 3 kubernetes.io/os=linux 3h32m calico-node,kube-flannel calico/node:v3.16.4,quay.io/coreos/flannel:v0.12.0 k8s-app=canal
  • Version du système d’exploitation
$ cat /etc/lsb-release | grep -i description
DISTRIB_DESCRIPTION="Ubuntu 20.04.1 LTS"
  • CIDR du Cluster
$ ps -ef | grep cluster-cidr
xxxx  --client-ca-file=/etc/kubernetes/pki/ca.crt --cluster-cidr=172.16.0.0/16 --cluster-name=kubernetes xxxx
  • CIDR par node
$ kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}'
172.16.0.0/24 172.16.1.0/24 172.16.2.0/24

Voici les informations de mon réseau.

  • Kubernetes version: 1.19.3
  • Calico version: 3.16.4
  • Flannel version: 0.12.0
  • Operating System and version: Ubuntu 20.04.1 LTS
  • Mon réseau local: 192.168.0.0/24
  • CIDR du cluster kubernetes: 172.16.0.0/16

2. Topologie

Les communications dans un réseau Kubernetes se font de façon centralisées.

Les traffics partant des nodes (Workers), passent  par un plans de contrôle (Master) qui fait office de hub/commutateur, avant d’être redirigés vers leurs destinations. L’architecture réseau de kubernetes utilise une topologie réseau en étoile.

3. Network Namespace (netns)

Un espace de nom réseau Linux[1][2] (« network namespace ») est l’une fonctionnalité du noyau linux pour virtualiser la pile réseau dans chacun des namespaces.

De plus, un ensemble d’objets dans un même espace de nom (namespace), partage les mêmes resources. Par défaut, dans chaque Pod est créé une interface de loopback, pour que les conteneurs du même Pod puissent communiquer entre eux sans avoir à quitter le réseau namespace qui leurs sont associés.

Chaque espace de nom, peut fournir à chacun des Pods toutes les resources liées au réseau.
Entre autre, chaque pod peut avoir,

  • Une adresse IP privée
  • Sa propre table de routage, avec ses règles de parefeux, etc.

Les deux type de namespace sont,

  • « Root netns », pemet la communication entre un Pod et l’extérieur
  • « Pod netns », regroupe tous les conteneurs d’un même Pod, dans le même réseau « local »

4. Connectivités réseaux

Le CNI s’occupe du réseautage dans un cluster kubernetes. Entre autre, le CNI s’assure de la connectivité entre:

  • Conteneurs (voir chap 7 et chap 8)
    Deux conteurs au sein d’un même Pod communiquent entre eux via l’interface de loopback
  • Pods (voir chap 5)
    Deux conteneurs placés dans deux Pods différents, communiquent via l’interface réseau du Pod (eth0) si les deux Pods se trouvent sur deux Nodes différents.
    Sinon, les communications au sein d’un même Pod passe par l’interface bridge cbr0 du CNI
  • Pod et Service du réseau
  • Traffic Extérieur vers Service réseau

Schématisation des deux premiers points.

Les deux derniers points utilisent les services du proxy pour rediriger les traffics de l’extérieur vers l’un des Pods proposant le même service. On parle de répartition de charges, ou load balancing.

II. Services et Routage du traffic réseau

2.1 Introduction sur les Services

Sur la page de kubernetes[1], est donné la définition de « Service ».

Un service dans Kubernetes est un objet REST, semblable à un pod.

Lorsqu’un groupe de Pods est géré par le même service,

  • Ces Pods seront joignable via l’interface de l’objet Service, dont l’adresse IP est « immuable« , par opposition à l’adresse des Pods qui est éphémère (voir chap 5)
  • Chacun des ces Pods aura un nom DNS unique (voir chap 6)
  • Equilibrage des charges ou Load-balancer, entre les différents Pods

Un service kubernetes peut être créé de deux façon différentes,

  • Automatiquement, via la commande « expose »
  • Manuellement, à partir d’un fichier YAML

2.2 Création manuel d’un service

Les étapes du chap 5 peuvent se résumer par:

  • Création de 2 Pods à partir du Service de Réplication
  • Création d’un Service kubernetes avec la commande « expose »
$ kubectl create -f nginx-dpl.yaml

$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 1/1 1 1 47m

$ kubectl expose deploy nginx-deployment
service/nginx-deployment exposed

2.3 Création d’un service via un fichier YAML

Les étapes du chap 6 peuvent se résumer par:

  • Création de deux Pods différents ayant le même label/étiquette
  • Création d’un Service kubernetes à partir d’un fichier YAML, qui cible l’étiquette commun des deux Pods au niveau port TCP 9376
$ kubectl create -f ubuntu1.yml

$ kubectl create -f ubuntu2.yml

$ kubectl create -f ubuntu-svc.yml

2.3 Types de Service

Au moment où j’écris cet article, il y a quatre types de services reconnus par kubernetes.

  • ClusterIP
    Expose le service avec une adresse IP interne au cluster (choix par défaut)
  • NodePort
    Expose le service directement sur le node via un port défini au préalable
  • LoadBalancer
    Expose le service à l’extérieur du réseau, vers un répartisseur de charge de votre fournisseur de service Cloud Computing
  • ExternalName
    Mappe le service au contenu du champ externalName

Pour plus d’information sur l’utilisation de chacun de ces services, revoyer les informations de la page de kubernetes sur les services.

Si vous avez fait attention au fichier YAML du chap 5, j’ai commenté le type de service en ajoutant un # au niveau de la ligne « type ».

apiVersion: v1
kind: Service
metadata:
  name: my-subdomain
spec:
  selector:
    name: ubuntu
  ports:
  - name: default
    protocol: TCP
    port: 80
    targetPort: 9376
  #type: ClusterIP

Comme précisé plus haut, ClusterIP est l’option par défaut si le type n’est pas précisé. C’est cette option que vous risquez de rencontrer régulièrement dans mon blog.

2.4 Serveur Proxy

Voyons comment le service kubernetes fonctionne.

Dans le schéma ci-dessous, un client lance deux requêtes différentes, dont l’un est adressé au serveur Nginx, et l’autre à un autre type de serveur.

Dans le cas de la requêtre vers un serveur Nginx de notre exemple, l’objet Service sélectionne au hasard l’un des trois pods (endpoints) pour transférer cette requête via le port 9376, d’où les 33% de chance de tomber sur l’un des trois Pods ciblés par cette requête.

Pour avoir la liste des endpoints disponible dans l’iptable, ce dernier génère une liste de règles qui capturent les informations sur le trafic vers le «clusterIP» et le «port» du service,

$ kubectl get endpoints nginx-deployment

$ kubectl get ep nginx-deployment

Sinon, vous pouvez avoir cette information complète sur le service avec la commande describe.

$ kubectl describe svc nginx-deployment

Nous avons vu comment créer des probes de préparation (Readiness Probe) dans le chap 7. C’est le bon moment pour la mettre en pratique, pour vérifier l’état de santé des pods de destinations (endpoints), afin de s’assurer qu’ils fonctionnent correctement et d’éviter ainsi, d’avoir des traffics inutiles vers des pods non fonctionnels.

2.5 Kubernetes Ingress

Citation de la page officielle de kubernetes[1],

Vous pouvez également utiliser Ingress pour exposer votre service. Ingress n’est pas un type de service, mais il sert de point d’entrée pour votre cluster. Il vous permet de consolider vos règles de routage en une seule ressource car il peut exposer plusieurs services sous la même adresse IP.

    internet
        |
   [ Ingress ]
   --|-----|--
   [ Services ]

Source

A Guide to the Kubernetes Networking Model
Kubernetes: Service