La solution que nous avons mis en place permet de tester K3S de façon très rapide mais ne garantit aucunement une haute-disponibilité des services.

Mais quelles possibilités m'offre K3S pour réaliser un mode HA ? Est-ce que je suis prêt à le faire ?

Dans un premier temps, revenons un peu sur le schéma technique de notre Lightweight Kubernetes.

K3S High-Availability

K3S offre plusieurs types de fonctionnement, tout d'abord le single-server :

K3S single server

Ce schéma nous permet de définir deux éléments importants d'une architecture K3S :

  • server : Pour ceux qui viennent du monde Docker Swarm comme moi, il s'agit de votre node manager. C'est lui qui va répartir les tâches aux workers qui sont ici des agents ...
  • agent : Les worker nodes, ils vont recevoir les tâches et les exécuter.

Par défaut, K3S installe aussi bien le serveur que l'agent si vous ne passez aucun argument lors de l'installation.

Tout comme pour Docker Swarm, un agent s'exécute sur chaque nœud worker et rend compte des tâches qui lui sont affectées. Le nœud worker informe ainsi le nœud gestionnaire de l'état actuel de ses tâches affectées afin que celui-ci puisse maintenir l'état souhaité de chaque worker.

Un server node où l'agent est également installé peut exécuter des tâches. Mais vous pouvez bien évidemment séparer complètement vos nodes servers des nodes agents.

Un single-server permet donc de maintenir une certaine disponibilité des services au sein des nodes agents. Mais cette architecture possède un point de défaillance, le server unique.

Afin de ne pas tomber dans ce cas de figure, il est bien évidement possible d'installer plusieurs servers dans un même cluster :

K3S HA

Comme nous avons pu le voir, les agents vont envoyés aux serveurs l'état des tâches en cours. Afin de stocker cette information, K3S va utiliser une base externe. Plusieurs types de datastore sont disponibles :

  • PostgreSQL,
  • MySQL,
  • etcd,
  • SQLite.

Dans ce cas, la perte d'un server n'est plus un problème puisque l'état est conservé sur une base externe et chaque server du cluster pourra récupérer l'information.

Depuis la fin 2019, il existe même une dernière solution :

  • High Availability with Embedded DB

La base de données n'est cette fois pas externe, mais directement intégrée sur les servers. Pour information la base de données embarquée est Dqlite :

According to https://dqlite.io, it is “a fast, embedded, persistent SQL database with Raft consensus that is perfect for fault-tolerant IoT and Edge devices.” This makes it a natural fit for K3s.

Habitué à Docker Swarm, j'avoue qu'installer une base externe ne me plaisait pas trop... J'ai donc décidé d'essayer la version embarquée de la solution 😂

Pré-requis

🚩 Attention ce tutoriel ne propose aucunement une solution à mettre en production. Il s'agit clairement d'une démonstration, des possibilités offertes par K3S et je vais prendre des raccourcis qu'il est inenvisageable de prendre dans le cadre d'une mise en production ! 🚩

Afin de réaliser la démo, je vais utiliser 3 VPS chez OVH. J'ai délibérément choisi de les lancer sur 3 datacenters différents :

  • Gravelines
  • Strasbourg
  • Beauharnois

Vous aurez compris, je prends le parti d'utiliser des machines géographiquement distantes afin de commencer les essais sur un éventuel "lag réseau" de la solution. Je ne rentrerai pas dans le détail aujourd'hui de ces essais mais ce sera le cas au cours d'un prochain article !

Pour information, je lance la démonstration sur 3 instances de types sandbox à 2.99€HT/mois :

  • S1-2
  • Mémoire vive :2 Go
  • Processeur :1 vCores (2.4 GHz)
  • Stockage :10 Go SSD

Ces 3 machines sont installées avec Debian 10 et ma clé SSH.

À la réception des accès, je vais créer trois entrées DNS de type A sur mon domaine avec les IP publiques :

IP DNS

Il s'agit de réaliser un DNS round-robin sur l'adresse afin de tester la haute-disponibilité de notre instance whoami.

J'ai également mis en place un Vrack pour faire communiquer les instances. Dans le cadre de cette démonstration, ce n'est clairement pas indispensable.

Une fois ces quelques préparatifs réalisés, nous pouvons lancer l'installation.

Démonstration

Je vais tout d'abord installer mon premier serveur. Pour installer K3S la seule dépendance est curl qui n'est pas installée par défaut :

sudo apt update && sudo apt install curl

Je n'ai plus qu'à installer K3S mais en lui précisant de ne pas déployer Traefik et d'initialiser le cluster avec la BDD embarquée.

curl -sfL https://get.k3s.io | sh -s - --no-deploy=traefik  --cluster-init

Quelques instants plus tard vous pourrez vérifier le bon démarrage de votre server avec la commande :

sudo kubectl get nodes

Pour installer K3S sur les deux autres instances, nous allons avoir besoin du Token de notre serveur qui se situe dans le fichier suivant :

sudo cat /var/lib/rancher/k3s/server/node-token

C'est fini pour le premier master. Les opérations suivantes sont à renouveller sur les deux instances restantes :

curl -sfL https://get.k3s.io | sh -s - --no-deploy=traefik --server https://IPDUPREMIERSERVEUR:6443 --token "XXXXX"

À la fin de l'installation, K3S m'a renvoyé une erreur car le daemon prenait un peu de temps à se connecter au serveur. Mais après quelques minutes :

sudo kubectl get nodes
NAME        STATUS   ROLES    AGE     VERSION
s1-2-sbg5   Ready    master   7h29m   v1.17.3+k3s1
s1-2-gra7   Ready    master   7h37m   v1.17.3+k3s1
s1-2-bhs5   Ready    master   7h30m   v1.17.3+k3s1

Nous venons déjà d'installer K3S en mode multi-master... Il faut être honnête, c'est vraiment simple.

Déployons maintenant Traefik. Pour cela je repars de la configuration que j'avais déjà mis en ligne sur github :

lfache/K3S_TRAEFIK2.1
Contribute to lfache/K3S_TRAEFIK2.1 development by creating an account on GitHub.
https://github.com/lfache/K3S_TRAEFIK2.1
sudo kubectl apply -f K3S_TRAEFIK2.1/

Enfin on vérifie que Traefik se lance correctement sur nos serveurs :

kubectl get po --all-namespaces

Vous pouvez modifier le fichier K3S_TRAEFIK2.1/Traefik.yml afin de créer 3 replicas, dans mon précédent fichier il ne lance qu'une seule instance :

apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: kube-system
  name: traefik-ingress-controller
---
kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: kube-system
  name: traefik
  labels:
    app: traefik

spec:
  replicas: 3

Appliquez les changements :

sudo kubectl apply -f K3S_TRAEFIK2.1/

Pour vérifier que tout fonctionne, accèdez au dashboard de Traefik sur chaque IP publique : http://X.X.X.X:8080

Enfin déployons notre instance whoami en créant un fichier whoami.yml :

mkdir whoami
cd whoami
vim whoami.yml

Voici le fichier :

kind: Namespace
apiVersion: v1
metadata:
  name: whoami
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: whoami
  namespace: whoami
  labels:
    app: whoami
spec:
  replicas: 3
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: containous/whoami
          ports:
            - name: http
              containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: whoami
spec:
  ports:
    - protocol: TCP
      name: http
      port: 80
  selector:
    app: whoami
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-http
  namespace: whoami
spec:
  entryPoints:
    - http
  routes:
  - match: Host(`dev.domain.com`)
    kind: Rule
    services:
    - name: whoami
      port: 80

Déployez l'instance :

 sudo kubectl apply -f whoami/

Depuis votre navigateur vérifiez que http://dev.domain.com renvoie les informations de whoami :

Il est possible de faire la vérification avec curl également, par exemple sous Windows et PowerShell :

curl 'http://X.X.X.X' -H @{"Host"="dev.domain.com"}

Réalisez cette opération en remplaçant http://X.X.X.X par vos IP publiques.

Si vous avez bien suivi ( ou si je n'ai pas fait d'erreurs en écrivant cet article, au choix 😇 ), il ne devrait y avoir aucun soucis !

Testons maintenant notre HA. Plusieurs solutions possibles, redémarrer un serveur, le passer en mode rescue si vous êtes chez OVH, couper le serveur K3S...

Bref j'ai choisi de mon côté de passer en mode maintenance un de mes noeuds afin de le couper le temps de mes essais.

Relancez les commandes curls et là ...

MAGIC

Vous pouvez effectuer le même test avec votre navigateur.

Voila votre instance whoami fonctionne sur notre cluster K3S en mode HA. Est-ce parfait ? Non clairement pas, si votre navigateur décide d'aller sur le serveur qui est en maintenance... Timeout... Nous n'avons utilisé ici aucun système de loadbalancer afin de contrer cette problématique.


Dans ce tutoriel, nous avons pu installer K3S en mode HA avec, en prime, Traefik en version  2.1 😍.  Nous avons également pu tester notre installation avec le  déploiement d'une instance whoami.

Bien évidemment et comme je l'avais évoqué dans l'article, ce déploiement n'est clairement pas sans défaut. Aucun filtrage, aucune gestion du SSL, un DNS round-robin qui peut poser des soucis... Mais nous avons pu voir ensemble qu'installer un cluster K3S en HA était clairement possible. Il est maintenant nécessaire d'aller plus loin dans les recherches afin de rendre ce cluster viable pour des tests plus poussés !

J'espère en tout cas que cet article vous aura apporté une aide, dans la compréhension d'un cluster K3S, mais également dans l'installation de K3S en mode HA avec Traefik en version 2.1 !

En tout cas  n'hésitez pas à m'apporter des remarques ou des commentaires sur Twitter