Pour déployer une application au sein d’un cluster Kubernetes, on peut le
faire de manière classique avec des fichiers de configuration YAML ou un
gestionnaire de packages comme Helm. Il existe un troisième moyen qui est de
créer un opérateur Kubernetes. Voyons dans un premier temps ce qu’est un
opérateur Kubernetes.
Les opérateurs Kubernetes
Qu’est-ce qu’un opérateur Kubernetes
Un opérateur Kubernetes est un contrôleur personnalisé qui étend les
fonctionnalités de l’API Kubernetes pour gérer des applications complexes. Il
permet de déployer et de gérer une application Kubernetes de manière
automatisée. L’opérateur peut automatiser des tâches telles que la
sauvegarde des données, la récupération après défaillance et
l’installation de nouvelles versions de l’application. L’utilisation d’un
opérateur Kubernetes permet donc de réduire les interventions et donc les
erreurs humaines.
Comment écrire un opérateur Kubernetes ?
Il existe de nombreuses méthodes pour écrire et déployer son propre un opérateur
Kubernetes :
avec l’Opérator Framework que nous allons utiliser ici.
Qu’est l’Operator Framework
L’Operator Framework est un outil créé par Red Hat dans le cadre de
l’Operator Framework. Avec ce Framework, on peut développer des opérateurs
kubernetes, soit avec le langage Go, soit le gestionnaire de configuration
Ansible ou encore le gestionnaire de packages Helm.
Ici, je ne vais utiliser Ansible pour créer notre premier opérateur.
Pourquoi utiliser Ansible pour écrire un opérateur Kubernetes ?
Au début, les opérateurs étaient écrits en Go, ce qui obligeait à connaître ce
langage. L’opérateur Ansible a été créé pour en faciliter l’écriture. Autre
point positif, cela permet aux utilisateurs d’intégrer des tâches de gestion
hors cluster liées à votre application via la large collections de modules
Ansible.
La documentation de l’installation se trouve
ici ↗. Je vais tout de même
détailler en français l’installation depuis les artefacts disponibles sur le
projet.
Vous devriez obtenir ce message :
On vérifie que les checksums correspondent :
On peut copier le binaire :
On peut lancer la commande suivante que tout est bien installé :
Installation d’une registry Docker
Nous avons besoin d’une registry docker pour stocker les images.
Installation des librairies python pour molecule
Si vous souhaitez utiliser molecule pour mettre en
place des tests, il est nécessaire d’installer dans votre environnement virtuel
python les librairies suivantes :
Installation des outils
Installation de kustomize et kubectl
Nous aurons aussi besoin de certains outils que je vais installer avec asdf :
Création de l’opérateur
Maintenant que le SDK est installé passons à la création de notre opérateur.
Il faut ensuite créer l’API :
Normalement, vous devriez obtenir toute une arborescence contenant ces répertoires et fichiers :
Les fichiers et dossiers importants :
[1] Makefile : contient toutes les commandes pour gérer l’opérateur
[2] playbooks : un dossier vide par défaut dans lequel vous pouvez ajouter vos actions
[3] requirements.yml : les dépendances rôles et collections ansible-galaxy
[4] watches.yaml : Permet de définir les ressources que l’opérateur surveille.
[5] roles : C’est dans ce dossier que nous définir les ressources kubernetes qui doivent être créé par l’opérateur
[84] Dockerfile : Permet d’ajouter des dépendances python à l’image qui lance la création des ressources.
Ajout des ressources pilotées par l’opérateur
Pour cela, nous allons éditer le rôle Ansible. Nous allons déployer une simple déploiement avec une image nginx.
Ouvrez le fichier roles/firstoperator/tasks/main.yml :
ATTENTION : c’est bien un fichier de rôle Ansible utilisant le module
kubernetes.core.k8s ↗
D’ailleurs, vous remarquez que nous faisons appel à des variables Jinja.
{{ size }} que nous allons définir dans le fichier roles/firstoperator/defaults/main.yml
qui pilote le nombre de pod(s) de notre déploiement.
{{ ansible_operator_meta.name }}
Création de l’image docker
Pour éviter de devoir renseigner le nom de l’image chaque invocation de la commande make, éditons le fichier Makefile :
À la ligne 50 remplacez la ligne commençant par IMG par :
Nous allons construire l’image qui va servir à lancer les actions Ansible par
l’opérateur. Nous allons l’installer dans la registry local :
Ce qui donne :
Déploiement de l’opérateur Ansible
Nous avons deux moyens de déployer notre opérateur dans notre instance kubernetes :
ou manuellement avec les commandes make deploy et make undeploy.
Nous utiliserons ici la seconde méthode pour le moment.
Ici, nous déployons que l’opérateur qui ajoute juste la définition de notre
ressource à l’API. Pour contrôler si l’opérateur est bien déployé, nous
utiliserons les commandes kubectl habituelles :
Nous avons déployé notre opérateur dans le namespace
first-ansible-operator-system. Verifions ce qui a été
créé dans ce namespace :
Pour vérifier les logs de l’opérateur (changez le nom de la ressource avec la vôtre) :
Notre Opérateur est correctement déployé. Passons à la création de notre
première ressource.
Création de notre première ressource
Pour créer notre première ressource, c’est assez simple, car lors de la création
de l’opérateur le SDK a créé un fichier de déclaration prêt à l’emploi. Ce
fichier se trouve dans le dossier config/samples/ et se nomme
cache_v1alpha1_firstoperator.yaml. Nous allons l’éditer pour spécifier le
nombre de pod de notre ressource :
On ajoute simplement size avec la valeur de 3 à notre ressource.
Nous pouvons créer notre première ressource, mais avant cela créons un namespace
dédié et changeons le context :
Dans une autre terminal lancez cette commande pour surveiller les logs de l’opérateur :
Créons notre ressource :
Dans l’autre terminal, vous devriez voir les logs de la création de la ressource :
Il y a une erreur dans notre déploiement ? Retirons notre ressource :
Que se passe-t-il ? Tout est indiqué dans les logs. Le service n’a pas été créé,
car nous n’avons pas les droits ! Il faut ajouter les droits sur les services
pour l’API Group "". Un petit tour dans le répertoire config/rbcpour éditer le
fichier role.yaml pour y ajouter services à ce groupe :
Redéployons notre Opérateur avec ces nouveaux droits !
Vous remarquez que la ligne suivante indique bien un changement !
On vérifie que notre service est correctement créé :
On vérifie que nous accédons bien à un des pods du déploiement :
Tout décommissionner
Nous avons fini de jouer avec notre Opérateur Ansible. Faisons le ménage !
Dans un premier détruisons notre application :
Puis notre Opérateur :
Plus loin
Après ces quelques jours où j’ai commencé à jouer avec l’Operator Framework
version Ansible, je peux conclure que c’est au final plutôt simple. Le plus
compliqué étant de lire et d’interpréter les logs retournées par Ansible. Je
vais continuer à explorer cette techno pour essayer de provisionner des
ressources externes et de gérer des backups. D’ailleurs maintenant que je
comprends comment cela fonctionne, je suis allé faire un tour dans le code de
l’opérateur AWX ↗.
On peut y voir 3 watches :
Il existe 2 rôles gérant les sauvegardes ! Par contre, cela fera l’objet d’un
nouveau billet sur les watches, finalizers, …