Que sont les finaliseurs dans Kubernetes ? Comment gérer les suppressions d'objets

0
174

Les suppressions d'objets Kubernetes ne sont pas aussi simples qu'il n'y paraît à première vue. La suppression d'un objet est un processus complexe qui inclut des vérifications conditionnelles pour déterminer si une suppression sûre est possible. Ceci est réalisé par des objets API appelés Finalizers.

Dans cet article, nous verrons ce que sont les Finalizers, comment ils sont gérés et les défis qu'ils peuvent poser lorsque vous souhaitez supprimer un objet. Avoir une meilleure compréhension du processus de suppression peut vous aider à déboguer les problèmes où les ressources ne semblent pas se terminer en temps opportun.

Que sont les finaliseurs ?

Les finaliseurs sont un mécanisme permettant de faire respecter certaines conditions avant qu'un objet puisse être supprimé. Lorsque vous exécutez une commande telle que kubectl delete namespace/example, Kubernetes vérifie les finaliseurs définis sur l'objet référencé. Ceux-ci sont répertoriés dans son champ metadata.finalizers. Chaque finaliseur a la possibilité de reporter la suppression jusqu'à ce qu'il ait terminé ses actions.

Le processus de suppression réel ressemble à ceci :

  1. Émettez une commande de suppression. – Kubernetes marque l'objet comme étant en attente de suppression. Cela laisse la ressource dans le fichier “Terminaison” en lecture seule. état.
  2. Exécutez chacune des actions associées aux finaliseurs de l'objet. – Chaque fois qu'une action Finalizer se termine, ce Finalizer est détaché de l'objet, de sorte qu'il n'apparaîtra plus dans le champ metadata.finalizers.
  3. Kubernetes continue de surveiller les Finalizers attachés à l'objet . – L'objet sera supprimé une fois que le champ metadata.finalizers sera vide, car tous les Finalizers ont été supprimés à la fin de leurs actions.

Les finaliseurs sont couramment utilisés pour exécuter des procédures de nettoyage et de récupération de place avant qu'un objet ne soit supprimé du cluster. Vous pouvez ajouter vos propres finaliseurs à l'aide de l'API Kubernetes ; Les finaliseurs intégrés sont également appliqués automatiquement à certains types d'objets.

Par exemple, les ressources PersistentVolume sont fournies avec un finaliseur kubernetes.io/pv-protection qui empêche la suppression accidentelle des volumes en cours d'utilisation par les pods. Le finaliseur s'assure que le PersistentVolume ne peut pas être supprimé du cluster tant qu'aucun pod ne l'utilise. L'émission d'une commande de suppression alors qu'il y a encore un pod actif entraînera le marquage du volume comme étant en cours d'arrêt ; il restera dans cet état aussi longtemps que le Pod aura besoin du volume, puis sera supprimé automatiquement dès que possible par la suite.

Finalizer Challenges

Les finaliseurs de longue durée qui attendent une condition impliquant d'autres ressources peuvent provoquer l'apparition de suppressions bloquées dans l'état de terminaison. Vous pouvez également rencontrer des problèmes où un finaliseur bloque la suppression d'objets dépendants, ce qui empêche le parent de se terminer avec succès.

Publicité

Ces problèmes causent régulièrement de la confusion – les développeurs et les opérateurs ont tendance à considérer les suppressions comme des procédures simples alors que le processus est en fait nuancé et variable. Les conditions préalables à une suppression réussie dépendent des relations de la ressource et de leurs finaliseurs, ainsi que de l'objet cible lui-même.

Lorsqu'un objet se termine depuis trop longtemps, vérifiez ses finaliseurs en inspectant le champ metadata.finalizers dans son YAML :

kubectl get pod example-pod –namespace example -o json | jq

Une fois que vous savez quels finaliseurs sont définis, vous pouvez commencer à identifier ceux susceptibles de bloquer une suppression. L'affichage des événements et des changements de condition de l'objet peut faciliter le débogage en affichant les actions qui se sont produites depuis l'émission de la commande de suppression. Les conditions sont affichées dans le champ spec.status.conditions de YAML ; les événements sont visibles lors de l'exécution de kubectl describe pod example-pod.

Vous pouvez supprimer manuellement les finaliseurs d'un objet en corrigeant le champ spec.finalizers sur null. Cette technique ne doit être utilisée que si cela est absolument nécessaire. Les finaliseurs sont des sauvegardes destinées à protéger votre cluster ; les remplacer pourrait conduire à des objets orphelins et à des chaînes de dépendance brisées.

kubectl patch pod example-pod -p '{“metadata: {“finalizers”: null}}'

Propriétaires et politiques de propagation

Un sujet connexe sont les propriétaires d'objets et les politiques de propagation de la suppression. Les références de propriétaire définissent les relations entre les objets. Elles sont utilisées pour supprimer des arborescences d'objets entières lorsqu'un parent est supprimé. Par exemple, si vous supprimez un déploiement, Kubernetes doit également détruire les pods dans ce déploiement.

Les références de propriétaire sont définies via le champ metadata.ownerReferences sur les objets. Chaque référence inclut le genre et le nom de l'objet auquel la ressource actuelle doit être parent.

Publicité

Lorsque des références de propriétaire sont utilisées, la suppression d'un parent supprime automatiquement tous ses enfants. C'est ce qu'on appelle la suppression en cascade. Il est possible de désactiver la cascade en ajoutant le drapeau –cascade=orphan à kubectl delete. Kubernetes permettra aux enfants de l'objet de rester dans le cluster, les laissant disponibles mais orphelins.

Kubernetes prend également en charge différentes politiques de suppression “propagation.” Ceux-ci définissent si le parent ou ses enfants sont supprimés en premier. La stratégie de premier plan par défaut supprime les enfants, puis le parent, garantissant qu'aucun orphelin ne se produise. L'arrière-plan inverse l'ordre de sorte que le parent est supprimé en premier. La troisième règle, Orphan, demande à Kubernetes d'ignorer complètement les références de propriétaire.

La commande kubectl delete ne prend pas en charge les stratégies de propagation. Vous devez faire une requête API directe si vous souhaitez modifier la politique pour une opération de suppression :

curl -X DELETE localhost/api/v1/namespaces/default/deployments/example -d '{“apiVersion”: “v1”, “kind”: “DeleteOptions”, “propagationPolicy”: “Background”}' -H “Content-Type: application/json”

Les finaliseurs sont respectés lorsqu'une suppression est propagée ou mise en cascade vers des objets associés. Dans le cas de la politique de premier plan, cela signifie que tous les finaliseurs de tous les enfants devront être terminés avant que le parent puisse résilier. Pour la politique d'arrière-plan, les enfants resteront en ligne jusqu'à ce que les finaliseurs de leurs parents aient terminé.

Implémentation des finaliseurs

Vous pouvez implémenter vos propres finaliseurs en utilisant l'API Kubernetes et le SDK Go. Les finaliseurs sont créés en enregistrant des hooks dans la méthode Reconcile d'un contrôleur.

La méthode doit vérifier si l'objet à réconcilier a une valeur dans son champ DeletionTimestamp. Cela signifie qu'il est en attente de suppression et qu'il est à l'état Terminer. Choisissez un identifiant pour votre finaliseur et vérifiez si l'objet inclut la valeur dans son champ metadata.finalizers. Si c'est le cas, vous devez exécuter toutes les actions nécessaires, puis détacher le Finalizer de l'objet. Un exemple d'implémentation est inclus dans le guide Kubebuilder pour écrire vos propres types d'objets Kubernetes à l'aide de CRD (définitions de ressources personnalisées).

Les finaliseurs sont toujours implémentés sous forme de code dans une méthode de contrôleur. Le champ metadata.finalizers agit de la même manière que les annotations et les étiquettes, répertoriant les finaliseurs à appliquer à cet objet sans définir directement le code à exécuter.

Conclusion

Les finaliseurs contrôlent le cycle de vie d'un objet Kubernetes après le lancement de la suppression. Ils sont utilisés pour implémenter le ramasse-miettes, informer les contrôleurs des suppressions imminentes et empêcher la suppression accidentelle d'objets qui sont encore référencés par d'autres ressources.

Publicité

Parce que les finaliseurs peuvent bloquer les suppressions d'objets pour des périodes de temps arbitrairement longues, elles sont une source courante de frustration lorsque les équipes opérationnelles ne comprennent pas pourquoi un objet est bloqué. se terminant. Dans cette situation, il est préférable d'inspecter les ressources affectées, de voir quels finaliseurs sont actifs et d'enquêter sur les relations inter-objets qui pourraient agir comme des dépendances bloquantes. Forcer la suppression d'un finaliseur devrait être votre dernier recours si vous devez immédiatement supprimer un objet de terminaison ou si vous avez épuisé toutes vos autres options.