Sauvegarder et restaurer des manifestes Kubernetes avec leur statut

25 nov. 2024

Un peu de contexte

Dans ma mission actuelle, je travaille à l'automatisation du provisionnement de clusters Kubernetes. C'est un environnement hybride entre des ressources on premise et cloud. J'ai essayé la Kubernetes Cluster API mais elle ne fournissait pas la flexibilité ni le niveau d'intégration dont j'avais besoin pour travailler dans cette banque. Après des semaines de tests et de conception, l'équipe avec laquelle je travaille a décidé d'opter pour un opérateur de cluster interne.

Principe

Lorsqu'on utilise le pattern de réconciliation dans un opérateur, comme décrit dans Cloud Native Infrastructure il faut créer des Custom Resources pour gérer le cycle de vie des dépendances externes nécessaires aux clusters Kubernetes. Une fonctionnalité clé est d'utiliser la clé status des Custom Resources pour stocker leur état réel, par exemple :


apiVersion: xyz/v1alpha1
kind: KubernetesCluster
metadata:
  name: my-custom-cluster-for-backup
spec:
  type: iks
  env: test
  kubeVersion: "1.28"
  osVersion: UBUNTU_20_64
  product:
	name: this is my solo experiment
	shortName: experiment
  uuid:
	value: aaa692e5-e6ce-4f19-ad20-6491ca74067c
  addons:
	- name: cluster-autoscaler
	  version: "1.2.2"
	- name: vpc-block-csi-driver
	  version: "5.2"
status:
  apiServerURL: https://my-private-endpoint.tld
  masterVersion: 1.28.23
							

C'est une conception puissante, surtout lorsqu'on gère des centaines ou des milliers d'objets. C'est comme une base de données structurée mais accessible uniquement via le serveur d'API Kubernetes. Ce pattern fonctionne le mieux lorsque chaque état de chaque objet peut être atteint de manière idempotente.

Le problème

La clé status n'est évidemment pas dans le manifeste de la Custom Resource, elle n'est donc pas récupérable depuis git ; elle vit uniquement dans les manifestes des clusters Kubernetes. Dans l'exemple de la section précédente, apiServerURL et masterVersion sont récupérables via l'API, donc les états peuvent être réconciliés par l'opérateur.
Que se passe-t-il si certains états sont irrécupérables en cas de suppression de la Custom Resource ou si des états transitoires sont nécessaires pour atteindre l'état attendu ? Cela signifie clairement que les états des Custom Resources doivent être sauvegardés quelque part en sécurité.

Velero à la rescousse

L'implémentation de l'API Kubernetes ignore complètement la clé status lorsque vous créez ou mettez à jour un objet Kubernetes. Il faut donc un processus en deux étapes pour récupérer l'objet et son statut sauvegardé. J'ai expérimenté velero et j'ai découvert cette fonctionnalité très intéressante. Il est possible de restaurer le status d'un objet lors d'une restauration Velero.

Essayons de sauvegarder et restaurer le statut du load balancer d'un service Kubernetes.
D'abord, lancez la sauvegarde :
velero backup create argocd --include-namespaces argocd

Service du serveur ArgoCD :


apiVersion: v1
kind: Service
metadata:
  finalizers:
  - service.kubernetes.io/load-balancer-cleanup
  labels:
	app.kubernetes.io/component: server
	app.kubernetes.io/name: argocd-server
	app.kubernetes.io/part-of: argocd
  name: argocd-server
  namespace: argocd
spec:
...
  type: LoadBalancer
status:
  loadBalancer:
	ingress:
	- ip: 172.18.0.7
	  ipMode: Proxy
	  ports:
	  - port: 80
		protocol: TCP
	  - port: 443
		protocol: TCP
							

Supprimez maintenant le service :
kubectl -n argocd delete svc argocd-server

Enfin, restaurez le service en restaurant la sauvegarde Velero avec le paramètre magique :
velero restore create argocd --from-backup argocd --status-include-resources Service

Comme vous l'avez facilement remarqué, le simple ajout de --status-include-resources Service permet à Velero de restaurer le statut uniquement pour les ressources nommées en ligne de commande. Vous trouverez plus d'explications en lisant la documentation

Maintenant que mon équipe et moi sommes sereins, nous allons continuer à approfondir le pattern opérateur pour gérer encore plus de ressources en dehors de Kubernetes, avec Kubernetes !