Proxmox v6 : Cluster K8S kubeadm via Terraform & Cloud-Init

Proxmox v6 : Cluster K8S kubeadm via Terraform & Cloud-Init

22 mai 2020 4 Par Mairien Anthony

Aujourd’hui, un peu de tout ! Terraform, Cloud-Init, Proxmox, Kubernetes, et un lab bien sympa !

Étant toujours dans mon apprentissage de Docker/K8s/Devops en général, je me suis dit que monter un petit cluster Kubernetes sur un bon vieux Proxmox serait sympathique, d’autant plus que j’avais déjà créé un article traitant de k8s mais c’était via Minikube, autant dire que c’était très sommaire. Ici, malgré que je ne sois pas encore un pro, on va essayer d’avancer un peu plus loin et de se monter un « vrai » cluster 😉

Commençons donc directement !

I) Le lab en détails

Ici nous allons donc partir sur un cluster comprenant 3 hôtes, un master et deux workers. Plutôt que de créer à la main et configurer nos 3 vms, je me suis dit que j’allais un peu automatiser ça.

On va donc, dans l’ordre :

  • Créer une template de machine virtuelle basée sur une image
    Cloud-Init de Debian 10 sur notre Proxmox ;
  • Créer un script Terraform pour déployer X fois notre template, en configurant une IP et tout ce qui va bien à chaque fois (installation des utilitaires de base, de docker, kubectl…) ;
  • Ensuite seulement nous mettrons en place notre cluster Kubernetes ;

II) Création du template via Cloud-Init

Ici pour la première étape nous allons télécharger un disque Cloud-Init d’une Debian 10 pré-configurée :

Ah oui, juste ! Qu’est-ce que Cloud-Init avant toute chose… et bien je vais essayer de décrire cet outil assez grossièrement, car je ferai sûrement d’autres articles qui en parleront plus en détails, mais retenez ceci :

Cloud Init est un package (un binaire) permettant de réaliser la configuration initiale d’un template de machine virtuelle ou de conteneur. Par exemple, une fois exécuté il pourra changer le nom d’hôte, l’adresse IP, installer tel ou tel paquet, importer telle clé SSH, etc. Plus besoin donc de se connecter manuellement sur 100 VMs pour exécuter son script Bash fait maison…

Ensuite, il ne nous reste plus qu’à créer notre VM qui servira de template en CLI, en lui greffant le disque virtuel Cloud-Init précédemment téléchargé :

N’étant pas un pro des commandes qm, j’avoue que certaines me sont encore un peu obscures, désolé 😅

A partir de là, on est bon !

Concernant la configuration IP, le user/password etc ce sera fait via notre script Terraform.

III) Installation et création du script Terraform

Ici je ne vais pas trop m’étendre sur ce qu’est Terraform et sur son installation complète et détaillée, sachez simplement que ce produit vient aussi d’Hashicorp, la même société qui propose Vagrant, et grosso modo :

  • Vagrant, permet de déployer une infra mais orientée pour le développement et non la production ;
  • Terraform, permet de déployer une infra mais orientée vers le Cloud et la production ;

Ici c’est du on-premise mais étant donné que je n’avais jamais testé Terraform auparavant, je me suis dit go for it 😛

Donc, pour l’installer :

Vérifiez bien entendu la version à télécharger pour votre wget, et le tour est joué !

Ensuite, comme pour Vagrant, Terraform utilise des Providers pour déployer ses vm/conteneurs. Ici, on va installer manuellement le provider Proxmox car par défaut il n’est pas inclus.

La première étape est donc d’installer le langage Go (ici je suis sur une Ubuntu 20.04, à vous d’adapter selon votre OS) :

Et là on peut installer notre provider Proxmox (l’installation peut prendre plusieurs minutes) :

Il faudra simplement réaliser un terraform init pour « reload » le tout, et prendre en charge nos deux nouveaux plugins.

Bien, une fois fait on peut se placer dans un dossier prévu à cet effet et créer notre fichier main.tf qui contiendra donc toutes les instructions pour déployer nos VMs. Ici aussi, je ne vais pas détailler l’entiéreté du script car ce serait trop long, le but de l’article est d’avant tout déployer un cluster k8s je vous rappelle 😅

Soit, voici notre script :

Je pense que le tout est assez bien commenté, et au passage, car je ne pense pas l’avoir dit en introduction, tous les scripts présentés ici sont d’ores et déjà disponibles sur mon Github, histoire de vous faciliter la vie :

https://github.com/IT-Anthony/terraform-deploy-vms

Bien, avant de déployer notre infrastructure il convient de créer un petit script bash permettant de faire les traditonnels apt-get update/apt-get update ainsi que l’installation de Docker :

Je sais je sais, on se passera de commentaires sur ce script basique en bash… l’important est que ça fonctionne haha.

Ensuite pour déployer notre infrastructure, il ne nous reste plus qu’à exécuter un terraform apply avec comme argument la variable nombre ainsi que le nombre de VMs à créer :

On patiente un peu, et le tour est joué !

Tadaaaa ! Nous avons donc déployé 3 machines virtuelles basées sur Debian 10 avec une installation automatique des mises à jour ainsi que de Docker ! Pas mal non ?

Mais bref, passons enfin à ce cluster Kubernetes…

IV) Création du cluster Kubernetes

Ici nous allons donc utiliser kubeadm, qui est un utilitaire permettant de déployer rapidement et facilement son cluster. La première étape est donc d’installer Docker sur chaque noeud et désactiver la mémoire Swap (étant donné que nous avons utilisé une image OpenStack ainsi qu’un script shell plus haut, tout ça est déjà fait).

Il faut simplement éditer manuellement le fichier /etc/cloud/cloud.cfg de nos 3 VMs pour passer en commentaire le paramètre update_etc_hosts, et ensuite changer le hostname via un rapide hostnamectl set-hostname (on aurait pu l’automatiser ça aussi, mais bon…).

Une fois fait, nous obtenons la chose suivante :

  • master-01, en 192.168.1.101/24 ;
  • worker-01, en 192.168.1.102/24 :
  • worker-02, en 192.168.1.103/24 ;

On se connecte donc sur le master pour commencer et démarrer notre installation :

Cette commande va donc permettre de renseigner l’adresse IP de notre master, puis de lui comme nom « master-01 » via la variable $HOSTNAME et enfin la partie pod-network permet de spécifier à K8S le réseau à utiliser pour la gestion des pods. Ici nous allons utiliser Flannel pour la gestion du réseau, il convient donc d’utiliser le range 10.244.0.0/16 spécifiquement.

On patiente un peu, puis nous allons ensuite créer un fichier de configuration que nous utiliserons via l’utilitaire kubectl, et qui permet de gérer le cluster (on notera d’ailleurs que les commandes sont données par l’installateur lui-même).

On se doit ensuite de modifier les paramètres bridge pour permettre à K8S de correctement utiliser le réseau de la machine (à réaliser sur nos trois VMs) :

Et enfin on déploie notre fameux pod Flannel qui servira à la gestion du réseau, comme dit précédemment :

Promis, la partie « config bien longue » est presque terminée ! Il faut simplement exécuter une dernière petite commande pour modifier l’adressage réseau de Flannel et éviter des petits soucis par la suite :

Cette commande nous ouvre l’éditeur Vim et nous permet de modifier précisément ce paramètre, changez-le en 10.10.0.0/16 :

Une fois fait, on peut d’ores et déjà se connecter sur notre worker-01 et worker-02 et les faire rejoindre le cluster :

Bien entendu cette commande sera différente de votre côté, déjà au niveau du token mais même au niveau de l’IP du master.

Si vous désirez rajouter un node après que le token ait expiré, car il n’a une durée de validité que de quelques minutes, vous pouvez exécuter cette commande :

Ensuite on peut réaliser le classique kubectl get nodes pour voir les membres du cluster, et même rajouter un label « worker » à nos deux workers justement via la commande kubectl lable node worker-01 node-role.kubernetes.io/worker=worker :

Bien, nos membres sont donc tous ready ! On va pouvoir déployer un rapide conteneur Nginx puis nous l’exposerons en dehors du cluster pour vérifier que tout soit ok.

V) Conteneur Nginx pour tests et vérificaton

Pour créer notre conteneur Nginx et l’exposer en dehors du cluster, rien de plus simple !

Ici on créer donc un deployment nommé web-01 et basé sur l’image Nginx.

On peut vérifier qu’il est bien en status Running via la commande kubectl get pods :

Niquel, on poursuit !

Ensuite on va créer un service de type NodePort et qui nous permettra donc de toucher le Nginx depuis l’extérieur du cluster :

Ici le port 80 pointe sur le port 80 du conteneur, mais on aurait très bien pu prendre un port aléatoire de l’hôte, le principe est le même.

Un petit kubectl get svc et on peut voir que notre service a bien un port-forwarding d’actif :

Et ensuite, si l’on se rend sur l’adresse IP du node sur lequel tourne notre conteneur, en rajoutant le port 32629 on devrait arriver sur notre serveur web Nginx :

It works ! D’ailleurs si vous aviez par exemple 200 nodes, il est bon de savoir sur quelle node notre pod a été déployé… pour cela on peut utiliser la commande kubectl describe pods web-01 :

On cherche ensuite la ligne Node: xxx et c’est tout bon.

VI) Conclusion

Et bien c’est déjà la fin de cet article, qui aura été bien plus long à rédiger que ce que je ne pensais… de base je pensais simplement à déployer un petit cluster sur mon Proxmox comme dit en début d’article, puis j’ai eut l’idée de vouloir « un peu automatiser » le tout, mais découvrant tout juste Terraform/CloudInit et même Kubernetes en général, j’ai dû faire face à plusieurs galères… bon le résultat est bien là, les scripts sont fonctionnels et le cluster aussi, mais il est clair que tout ceci peut être largement amélioré, c’est avant tout un lab donc le but est bel et bien d’expérimenter, alors ne me jugez pas trop sévèrement haha 😅

J’espère tout de même vous avoir appris quelques bricoles, et je vous souhaite une bonne journée/soirée !