Aller au contenu

Génerer des operateurs Kubernetes avec Ansible

logo ansible

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 :

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 ?

ansible kubernetes operator

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.

Création de notre premier Operateur Ansible

Installation des prérequis

Installation d’un cluster Kubernetes

Vous pouvez utiliser kind, k3s, minikube,… pour monter votre cluster mono-noeud. Personnellement j’utilise k3s:

Terminal window
curl -sfL https://get.k3s.io | sh -
sudo chmod 0644 /etc/rancher/k3s/k3s.yaml
k3s kubectl get node
NAME STATUS ROLES AGE VERSION
internal Ready control-plane,master 9h v1.26.3+k3s1

Installation de l’Operator Framework

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.

Terminal window
export ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac)
export OS=$(uname | awk '{print tolower($0)}')
export OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/download/v1.28.0
curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH}
gpg --keyserver keyserver.ubuntu.com --recv-keys 052996E2A20B5C7E
curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt
curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt.asc
gpg -u "Operator SDK (release) <cncf-operator-sdk@cncf.io>" --verify checksums.txt.asc

Vous devriez obtenir ce message :

Terminal window
gpg: les données signées sont supposées être dans « checksums.txt »
gpg: Signature faite le mer. 15 mars 2023 01:46:07 CET
gpg: avec la clef RSA 8613DB87A5BA825EF3FD0EBE2A859D08BF9886DB
gpg: Bonne signature de « Operator SDK (release) <cncf-operator-sdk@cncf.io> » [inconnu]
gpg: Attention : cette clef n'est pas certifiée avec une signature de confiance.
gpg: Rien n'indique que la signature appartient à son propriétaire.
Empreinte de clef principale : 3B2F 1481 D146 2380 80B3 46BB 0529 96E2 A20B 5C7E
Empreinte de la sous-clef : 8613 DB87 A5BA 825E F3FD 0EBE 2A85 9D08 BF98 86DB

On vérifie que les checksums correspondent :

Terminal window
grep operator-sdk_${OS}_${ARCH} checksums.txt | sha256sum -c -
operator-sdk_linux_amd64: Réussi

On peut copier le binaire :

Terminal window
chmod +x operator-sdk_${OS}_${ARCH} && sudo mv operator-sdk_${OS}_${ARCH} /usr/local/bin/operator-sdk

On peut lancer la commande suivante que tout est bien installé :

Terminal window
operator-sdk version
operator-sdk version: "v1.28.0", commit: "484013d1865c35df2bc5dfea0ab6ea6b434adefa", kubernetes version: "1.26.0", go version: "go1.19.6", GOOS: "linux", GOARCH: "amd64"

Installation d’une registry Docker

Nous avons besoin d’une registry docker pour stocker les images.

Terminal window
docker run -d -p 5000:5000 --restart=always --name registry registry:2

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 :

Terminal window
pip install molecule kubernetes

Installation des outils

Installation de kustomize et kubectl

Nous aurons aussi besoin de certains outils que je vais installer avec asdf :

Terminal window
asdf plugin add kustomize
asdf install kustomize latest
asdf global kustomize latest
asdf plugin add kubectl
asdf install kubectl latest
asdf global kubectl latest

Création de l’opérateur

Maintenant que le SDK est installé passons à la création de notre opérateur.

Terminal window
mkdir first-ansible-operator
cd first-ansible-operator
operator-sdk init --domain example.me --plugins ansible

Il faut ensuite créer l’API :

Terminal window
operator-sdk create api --group cache --version v1alpha1 --kind FirstOperator --generate-role

Normalement, vous devriez obtenir toute une arborescence contenant ces répertoires et fichiers :

Terminal window
[0] .
├── [1] Makefile
├── [2] playbooks
├── [3] requirements.yml
├── [4] watches.yaml
├── [5] roles
└── [6] firstoperator
├── [7] vars
└── [8] main.yml
├── [9] meta
└── [10] main.yml
├── [11] handlers
└── [12] main.yml
├── [13] templates
├── [14] tasks
└── [15] main.yml
├── [16] README.md
├── [17] defaults
└── [18] main.yml
└── [19] files
├── [20] molecule
├── [21] kind
├── [22] converge.yml
├── [23] molecule.yml
├── [24] create.yml
└── [25] destroy.yml
└── [26] default
├── [27] kustomize.yml
├── [28] prepare.yml
├── [29] tasks
└── [30] firstoperator_test.yml
├── [31] converge.yml
├── [32] create.yml
├── [33] verify.yml
├── [34] destroy.yml
└── [35] molecule.yml
├── [36] config
├── [37] rbac
├── [38] firstoperator_viewer_role.yaml
├── [39] role.yaml
├── [40] auth_proxy_client_clusterrole.yaml
├── [41] leader_election_role.yaml
├── [42] auth_proxy_role_binding.yaml
├── [43] auth_proxy_role.yaml
├── [44] firstoperator_editor_role.yaml
├── [45] leader_election_role_binding.yaml
├── [46] service_account.yaml
├── [47] role_binding.yaml
├── [48] kustomization.yaml
└── [49] auth_proxy_service.yaml
├── [50] scorecard
├── [51] patches
├── [52] basic.config.yaml
└── [53] olm.config.yaml
├── [54] bases
└── [55] config.yaml
└── [56] kustomization.yaml
├── [57] prometheus
├── [58] monitor.yaml
└── [59] kustomization.yaml
├── [60] crd
├── [61] kustomization.yaml
└── [62] bases
└── [63] cache.example.me_firstoperators.yaml
├── [64] samples
├── [65] kustomization.yaml
└── [66] cache_v1alpha1_firstoperator.yaml
├── [67] testing
├── [68] kustomization.yaml
├── [69] manager_image.yaml
├── [70] pull_policy
├── [71] Always.yaml
├── [72] Never.yaml
└── [73] IfNotPresent.yaml
└── [74] debug_logs_patch.yaml
├── [75] manager
├── [76] kustomization.yaml
└── [77] manager.yaml
├── [78] manifests
└── [79] kustomization.yaml
└── [80] default
├── [81] kustomization.yaml
├── [82] manager_auth_proxy_patch.yaml
└── [83] manager_config_patch.yaml
├── [84] Dockerfile
└── [85] PROJECT

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 :

---
- name: Create a Deployment with image hello-world
kubernetes.core.k8s:
definition:
kind: Deployment
apiVersion: apps/v1
metadata:
name: "{{ ansible_operator_meta.name }}-helloworld"
namespace: "{{ ansible_operator_meta.namespace }}"
spec:
replicas: "{{ size }}"
selector:
matchLabels:
app: helloworld
template:
metadata:
labels:
app: helloworld
spec:
containers:
- name: helloworld
image: "nginx"
- name: Create frontend service
kubernetes.core.k8s:
definition:
kind: Service
apiVersion: v1
metadata:
name: frontend-service
namespace: '{{ ansible_operator_meta.namespace }}'
labels:
app: frontend
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30686
protocol: TCP
selector:
app: frontend

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.

---
size: 1

{{ 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 :

Terminal window
vi Makefile

À la ligne 50 remplacez la ligne commençant par IMG par :

Terminal window
IMG ?= localhost:5000/first-operator:v$(VERSION)

Nous allons construire l’image qui va servir à lancer les actions Ansible par l’opérateur. Nous allons l’installer dans la registry local :

Terminal window
make docker-build docker-push VERSION=0.0.1

Ce qui donne :

Terminal window
docker build -t localhost:5000/first-operator:v0.0.1 .
[+] Building 0.6s (11/11) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 351B 0.0s
=> [internal] load metadata for quay.io/operator-framework/ansible-operator:v1.28.0 0.5s
=> [internal] load build context 0.0s
=> => transferring context: 5.04kB 0.0s
=> [1/6] FROM quay.io/operator-framework/ansible-operator:v1.28.0@sha256:e4356b6a35250901d436ad40f7defb3afb841d42cb1 0.0s
=> CACHED [2/6] COPY requirements.yml /opt/ansible/requirements.yml 0.0s
=> CACHED [3/6] RUN ansible-galaxy collection install -r /opt/ansible/requirements.yml && chmod -R ug+rwx /opt/ansi 0.0s
=> [4/6] COPY watches.yaml /opt/ansible/watches.yaml 0.0s
=> [5/6] COPY roles/ /opt/ansible/roles/ 0.0s
=> [6/6] COPY playbooks/ /opt/ansible/playbooks/ 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:1079f6875f53a7cb4c6dfa8a6e33913806f5fe53315c84c7e0e1fc36eae75cca 0.0s
=> => naming to localhost:5000/first-operator:v0.0.1 0.0s
docker push localhost:5000/first-operator:v0.0.1
The push refers to repository [localhost:5000/first-operator]
4c98d0d9ecab: Pushed
ec115a086a7b: Pushed
57b360c22e69: Pushed
b3caa9094c7b: Layer already exists
2e2156d26b91: Layer already exists
89b874d633f9: Layer already exists
5f70bf18a086: Layer already exists
5188f96e027c: Layer already exists
89cc1fe33e9a: Layer already exists
e28c0943f833: Layer already exists
6ce5a98a4fc8: Layer already exists
3570c420cda4: Layer already exists
bccb88911f57: Layer already exists
v0.0.1: digest: sha256:12c0db25a325bb5259feccc7553e79cadadd3a70da60ab4ffd188651fe04ce34 size: 3030

Déploiement de l’opérateur Ansible

Nous avons deux moyens de déployer notre opérateur dans notre instance kubernetes :

Nous utiliserons ici la seconde méthode pour le moment.

Terminal window
make deploy VERSION=0.0.1

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 :

Terminal window
kubectl get namespaces
NAME STATUS AGE
default Active 11d
kube-system Active 11d
kube-public Active 11d
kube-node-lease Active 11d
firstoperator Active 7d
first-ansible-operator-system Active 3d22h

Nous avons déployé notre opérateur dans le namespace first-ansible-operator-system. Verifions ce qui a été créé dans ce namespace :

Terminal window
kubectl -n first-ansible-operator-system get pod
NAME READY STATUS RESTARTS AGE
first-ansible-operator-controller-manager-56bb9d55d6-vd6hs 2/2 Running 3 (3m59s ago) 3d22h

Pour vérifier les logs de l’opérateur (changez le nom de la ressource avec la vôtre) :

Terminal window
kubectl -n first-ansible-operator-system logs first-ansible-operator-controller-manager-56bb9d55d6-vd6hs manager
{"level":"info","ts":"2023-05-02T08:00:25Z","logger":"cmd","msg":"Version","Go Version":"go1.18.10","GOOS":"linux","GOARCH":"amd64","ansible-operator":"v1.28.0","commit":"484013d1865c35df2bc5dfea0ab6ea6b434adefa"}
{"level":"info","ts":"2023-05-02T08:00:25Z","logger":"cmd","msg":"Watch namespaces not configured by environment variable WATCH_NAMESPACE or file. Watching all namespaces.","Namespace":""}
I0502 08:00:27.097654 7 request.go:690] Waited for 1.049099946s due to client-side throttling, not priority and fairness, request: GET:https://10.43.0.1:443/apis/apiextensions.k8s.io/v1?timeout=32s
{"level":"info","ts":"2023-05-02T08:00:27Z","logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":"127.0.0.1:8080"}
{"level":"info","ts":"2023-05-02T08:00:27Z","logger":"watches","msg":"Environment variable not set; using default value","envVar":"ANSIBLE_VERBOSITY_FIRSTOPERATOR_CACHE_EXAMPLE_ME","default":2}
{"level":"info","ts":"2023-05-02T08:00:27Z","logger":"cmd","msg":"Environment variable not set; using default value","Namespace":"","envVar":"ANSIBLE_DEBUG_LOGS","ANSIBLE_DEBUG_LOGS":false}
{"level":"info","ts":"2023-05-02T08:00:27Z","logger":"ansible-controller","msg":"Watching resource","Options.Group":"cache.example.me","Options.Version":"v1alpha1","Options.Kind":"Firstoperator"}
{"level":"info","ts":"2023-05-02T08:00:27Z","logger":"proxy","msg":"Starting to serve","Address":"127.0.0.1:8888"}
{"level":"info","ts":"2023-05-02T08:00:27Z","logger":"apiserver","msg":"Starting to serve metrics listener","Address":"localhost:5050"}
{"level":"info","ts":"2023-05-02T08:00:27Z","msg":"Starting server","path":"/metrics","kind":"metrics","addr":"127.0.0.1:8080"}
{"level":"info","ts":"2023-05-02T08:00:27Z","msg":"Starting server","kind":"health probe","addr":"[::]:6789"}
I0502 08:00:27.456406 7 leaderelection.go:248] attempting to acquire leader lease first-ansible-operator-system/first-ansible-operator...
I0502 08:00:44.125317 7 leaderelection.go:258] successfully acquired lease first-ansible-operator-system/first-ansible-operator
{"level":"info","ts":"2023-05-02T08:00:44Z","msg":"Starting EventSource","controller":"firstoperator-controller","source":"kind source: *unstructured.Unstructured"}
{"level":"info","ts":"2023-05-02T08:00:44Z","msg":"Starting Controller","controller":"firstoperator-controller"}
{"level":"info","ts":"2023-05-02T08:00:44Z","msg":"Starting workers","controller":"firstoperator-controller","worker count":9}

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 :

apiVersion: cache.example.me/v1alpha1
kind: Firstoperator
metadata:
labels:
app.kubernetes.io/name: firstoperator
app.kubernetes.io/instance: firstoperator-sample
app.kubernetes.io/part-of: first-ansible-operator
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/created-by: first-ansible-operator
name: firstoperator-sample
namespace: firstoperator
spec:
size: 3

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 :

Terminal window
kubectl create namespace firstoperator
kubectl config set-context --current --namespace=firstoperator
kubectl get pod
No resources found in firstoperator namespace.

Dans une autre terminal lancez cette commande pour surveiller les logs de l’opérateur :

Terminal window
kubectl -n first-ansible-operator-system logs -f first-ansible-operator-controller-manager-56bb9d55d6-vd6hs manager

Créons notre ressource :

Terminal window
kubectl apply -f config/samples/cache_v1alpha1_firstoperator.yaml
firstoperator.cache.example.me/firstoperator-sample created

Dans l’autre terminal, vous devriez voir les logs de la création de la ressource :

Terminal window
{"level":"error","ts":"2023-05-02T08:25:18Z","msg":"Reconciler error","controller":"firstoperator-controller","object":{"name":"firstoperator-sample","namespace":"firstoperator"},"namespace":"firstoperator","name":"firstoperator-sample","reconcileID":"4b593968-f602-4d16-add3-1eec3b278820","error":"event runner on failed","stacktrace":"sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler\n\t/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.14.5/pkg/internal/controller/controller.go:329\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.14.5/pkg/internal/controller/controller.go:274\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2\n\t/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.14.5/pkg/internal/controller/controller.go:235"}
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Failed to retrieve requested object: b'{\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"services \\\\\"frontend-service\\\\\" is forbidden: User \\\\\"system:serviceaccount:first-ansible-operator-system:first-ansible-operator-controller-manager\\\\\" cannot get resource \\\\\"services\\\\\" in API group \\\\\"\\\\\" in the namespace \\\\\"firstoperator\\\\\"\",\"reason\":\"Forbidden\",\"details\":{\"name\":\"frontend-service\",\"kind\":\"services\"},\"code\":403}\\n'", "reason": "Forbidden"}

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 :

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: manager-role
rules:
##
## Base operator rules
##
- apiGroups:
- ""
resources:
- secrets
- pods
- pods/exec
- pods/log
- services
verbs:
- create
- delete
- get
- list
- patch
- update
- watch

Redéployons notre Opérateur avec ces nouveaux droits !

Terminal window
make deploy VERSION=0.0.1
cd config/manager && /home/vagrant/.asdf/shims/kustomize edit set image controller=localhost:5000/first-operator:v0.0.1
/home/vagrant/.asdf/shims/kustomize build config/default | kubectl apply -f -
# Warning: 'patchesStrategicMerge' is deprecated. Please use 'patches' instead. Run 'kustomize edit fix' to update your Kustomization automatically.
namespace/first-ansible-operator-system unchanged
customresourcedefinition.apiextensions.k8s.io/firstoperators.cache.example.me unchanged
serviceaccount/first-ansible-operator-controller-manager unchanged
role.rbac.authorization.k8s.io/first-ansible-operator-leader-election-role unchanged
clusterrole.rbac.authorization.k8s.io/first-ansible-operator-manager-role configured
clusterrole.rbac.authorization.k8s.io/first-ansible-operator-metrics-reader unchanged
clusterrole.rbac.authorization.k8s.io/first-ansible-operator-proxy-role unchanged
rolebinding.rbac.authorization.k8s.io/first-ansible-operator-leader-election-rolebinding unchanged
clusterrolebinding.rbac.authorization.k8s.io/first-ansible-operator-manager-rolebinding unchanged
clusterrolebinding.rbac.authorization.k8s.io/first-ansible-operator-proxy-rolebinding unchanged
service/first-ansible-operator-controller-manager-metrics-service unchanged

Vous remarquez que la ligne suivante indique bien un changement !

Terminal window
clusterrole.rbac.authorization.k8s.io/first-ansible-operator-manager-role configured

On vérifie que notre service est correctement créé :

Terminal window
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend-service NodePort 10.43.77.106 <none> 80:30686/TCP 27s

On vérifie que nous accédons bien à un des pods du déploiement :

Terminal window
curl localhost:30686
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Tout décommissionner

Nous avons fini de jouer avec notre Opérateur Ansible. Faisons le ménage !

Dans un premier détruisons notre application :

Terminal window
kubectl delete -f config/samples/cache_v1alpha1_firstoperator.yaml
firstoperator.cache.example.me "firstoperator-sample" deleted

Puis notre Opérateur :

Terminal window
make undeploy
/home/vagrant/.asdf/shims/kustomize build config/default | kubectl delete -f -
# Warning: 'patchesStrategicMerge' is deprecated. Please use 'patches' instead. Run 'kustomize edit fix' to update your Kustomization automatically.
namespace "first-ansible-operator-system" deleted
customresourcedefinition.apiextensions.k8s.io "firstoperators.cache.example.me" deleted
serviceaccount "first-ansible-operator-controller-manager" deleted
role.rbac.authorization.k8s.io "first-ansible-operator-leader-election-role" deleted
clusterrole.rbac.authorization.k8s.io "first-ansible-operator-manager-role" deleted
clusterrole.rbac.authorization.k8s.io "first-ansible-operator-metrics-reader" deleted
clusterrole.rbac.authorization.k8s.io "first-ansible-operator-proxy-role" deleted
rolebinding.rbac.authorization.k8s.io "first-ansible-operator-leader-election-rolebinding" deleted
clusterrolebinding.rbac.authorization.k8s.io "first-ansible-operator-manager-rolebinding" deleted
clusterrolebinding.rbac.authorization.k8s.io "first-ansible-operator-proxy-rolebinding" deleted
service "first-ansible-operator-controller-manager-metrics-service" deleted
deployment.apps "first-ansible-operator-controller-manager" deleted

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 :

---
# Use the 'create api' subcommand to add watches to this file.
- version: v1beta1
group: awx.ansible.com
kind: AWX
playbook: playbooks/awx.yml
snakeCaseParameters: False
- version: v1beta1
group: awx.ansible.com
kind: AWXBackup
role: backup
snakeCaseParameters: False
finalizer:
name: awx.ansible.com/finalizer
role: backup
vars:
finalizer_run: true
- version: v1beta1
group: awx.ansible.com
kind: AWXRestore
role: restore
snakeCaseParameters: False

Il existe 2 rôles gérant les sauvegardes ! Par contre, cela fera l’objet d’un nouveau billet sur les watches, finalizers, …