Génerer des operateurs Kubernetes avec 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 :
- avec le Charmed Operartor Framework ↗
- avec le Java Operator SDK ↗
- avec Kopf ↗
- avec le framework KubeBuilder ↗.
- avec le framework KUDO ↗ : Kubernetes Universal Declarative Operator
- avec Mast ↗
- avec MetaController ↗
- avec le shellOperator ↗
- 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.
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
:
curl -sfL https://get.k3s.io | sh -sudo chmod 0644 /etc/rancher/k3s/k3s.yamlk3s kubectl get nodeNAME STATUS ROLES AGE VERSIONinternal 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.
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.0curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH}gpg --keyserver keyserver.ubuntu.com --recv-keys 052996E2A20B5C7Ecurl -LO ${OPERATOR_SDK_DL_URL}/checksums.txtcurl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt.ascgpg -u "Operator SDK (release) <cncf-operator-sdk@cncf.io>" --verify checksums.txt.asc
Vous devriez obtenir ce message :
gpg: les données signées sont supposées être dans « checksums.txt »gpg: Signature faite le mer. 15 mars 2023 01:46:07 CETgpg: avec la clef RSA 8613DB87A5BA825EF3FD0EBE2A859D08BF9886DBgpg: 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 :
grep operator-sdk_${OS}_${ARCH} checksums.txt | sha256sum -c -
operator-sdk_linux_amd64: Réussi
On peut copier le binaire :
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é :
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.
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 :
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 :
asdf plugin add kustomizeasdf install kustomize latestasdf set --home kustomize latest
asdf plugin add kubectlasdf install kubectl latestasdf set --home kubectl latest
Création de l’opérateur
Maintenant que le SDK est installé passons à la création de notre opérateur.
mkdir first-ansible-operatorcd first-ansible-operatoroperator-sdk init --domain example.me --plugins ansible
Il faut ensuite créer l’API :
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 :
[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 :
vi Makefile
À la ligne 50 remplacez la ligne commençant par IMG par :
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 :
make docker-build docker-push VERSION=0.0.1
Ce qui donne :
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.0sdocker push localhost:5000/first-operator:v0.0.1The push refers to repository [localhost:5000/first-operator]4c98d0d9ecab: Pushedec115a086a7b: Pushed57b360c22e69: Pushedb3caa9094c7b: Layer already exists2e2156d26b91: Layer already exists89b874d633f9: Layer already exists5f70bf18a086: Layer already exists5188f96e027c: Layer already exists89cc1fe33e9a: Layer already existse28c0943f833: Layer already exists6ce5a98a4fc8: Layer already exists3570c420cda4: Layer already existsbccb88911f57: Layer already existsv0.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 :
- avec OLM, pour Operator Lifecycle Manager ↗ qui gère l’ensemble du cylce de vie d’un Opérateur.
- ou manuellement avec les commandes
make deploy
etmake undeploy
.
Nous utiliserons ici la seconde méthode pour le moment.
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 :
kubectl get namespaces
NAME STATUS AGEdefault Active 11dkube-system Active 11dkube-public Active 11dkube-node-lease Active 11dfirstoperator Active 7dfirst-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 :
kubectl -n first-ansible-operator-system get podNAME READY STATUS RESTARTS AGEfirst-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) :
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/v1alpha1kind: Firstoperatormetadata: 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: firstoperatorspec: 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
:
kubectl create namespace firstoperatorkubectl config set-context --current --namespace=firstoperatorkubectl get podNo resources found in firstoperator namespace.
Dans une autre terminal
lancez cette commande pour surveiller les logs de l’opérateur :
kubectl -n first-ansible-operator-system logs -f first-ansible-operator-controller-manager-56bb9d55d6-vd6hs manager
Créons notre ressource :
kubectl apply -f config/samples/cache_v1alpha1_firstoperator.yamlfirstoperator.cache.example.me/firstoperator-sample created
Dans l’autre terminal, vous devriez voir les logs de la création de la ressource :
{"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/rbc
pour éditer le
fichier role.yaml
pour y ajouter services
à ce groupe :
---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: manager-rolerules: ## ## 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 !
make deploy VERSION=0.0.1cd 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 unchangedcustomresourcedefinition.apiextensions.k8s.io/firstoperators.cache.example.me unchangedserviceaccount/first-ansible-operator-controller-manager unchangedrole.rbac.authorization.k8s.io/first-ansible-operator-leader-election-role unchangedclusterrole.rbac.authorization.k8s.io/first-ansible-operator-manager-role configuredclusterrole.rbac.authorization.k8s.io/first-ansible-operator-metrics-reader unchangedclusterrole.rbac.authorization.k8s.io/first-ansible-operator-proxy-role unchangedrolebinding.rbac.authorization.k8s.io/first-ansible-operator-leader-election-rolebinding unchangedclusterrolebinding.rbac.authorization.k8s.io/first-ansible-operator-manager-rolebinding unchangedclusterrolebinding.rbac.authorization.k8s.io/first-ansible-operator-proxy-rolebinding unchangedservice/first-ansible-operator-controller-manager-metrics-service unchanged
Vous remarquez que la ligne suivante indique bien un changement !
clusterrole.rbac.authorization.k8s.io/first-ansible-operator-manager-role configured
On vérifie que notre service est correctement créé :
kubectl get servicesNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEfrontend-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 :
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 andworking. 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 :
kubectl delete -f config/samples/cache_v1alpha1_firstoperator.yaml
firstoperator.cache.example.me "firstoperator-sample" deleted
Puis notre Opérateur :
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" deletedcustomresourcedefinition.apiextensions.k8s.io "firstoperators.cache.example.me" deletedserviceaccount "first-ansible-operator-controller-manager" deletedrole.rbac.authorization.k8s.io "first-ansible-operator-leader-election-role" deletedclusterrole.rbac.authorization.k8s.io "first-ansible-operator-manager-role" deletedclusterrole.rbac.authorization.k8s.io "first-ansible-operator-metrics-reader" deletedclusterrole.rbac.authorization.k8s.io "first-ansible-operator-proxy-role" deletedrolebinding.rbac.authorization.k8s.io "first-ansible-operator-leader-election-rolebinding" deletedclusterrolebinding.rbac.authorization.k8s.io "first-ansible-operator-manager-rolebinding" deletedclusterrolebinding.rbac.authorization.k8s.io "first-ansible-operator-proxy-rolebinding" deletedservice "first-ansible-operator-controller-manager-metrics-service" deleteddeployment.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, …