Поиск по сайту:

Что такое финализаторы в Kubernetes? Как справиться с удалением объектов


Удаление объектов Kubernetes не так просто, как кажется на первый взгляд. Удаление объекта — сложный процесс, который включает условные проверки, чтобы определить, возможно ли безопасное удаление. Это достигается с помощью объектов API, называемых Finalizers.

В этой статье мы рассмотрим, что такое финализаторы, как ими управлять и какие проблемы они могут вызывать, когда вы хотите удалить объект. Лучшее понимание процесса удаления может помочь вам отладить проблемы, связанные с несвоевременным прекращением ресурсов.

Что такое финализаторы?

Финализаторы — это механизм принудительного выполнения определенных условий перед удалением объекта. Когда вы запускаете такую команду, как kubectl delete namespace/example, Kubernetes проверяет финализаторы, определенные для объекта, на который указывает ссылка. Они перечислены в его поле metadata.finalizers. У каждого финализатора есть шанс отложить удаление до тех пор, пока он не завершит свои действия.

Фактический процесс удаления выглядит следующим образом:

  1. Отправьте команду на удаление. — Kubernetes помечает объект как ожидающий удаления. В результате ресурс остается в состоянии Завершение только для чтения.
  2. Выполнять каждое из действий, связанных с финализаторами объекта. — Каждый раз, когда завершается действие финализатора, этот финализатор отсоединяется от объекта, поэтому он больше не будет отображаться в метаданных поле .finalizers.
  3. Kubernetes отслеживает финализаторы, прикрепленные к объекту. — Объект будет удален, как только поле metadata.finalizers станет пустым, поскольку все финализаторы были удалены завершением. своих действий.

Финализаторы обычно используются для запуска процедур очистки и сборки мусора перед удалением объекта из кластера. Вы можете добавить свои собственные финализаторы с помощью Kubernetes API; встроенные финализаторы также автоматически применяются к некоторым типам объектов.

Например, ресурсы PersistentVolume поставляются с финализатором kubernetes.io/pv-protection, который предотвращает случайное удаление томов, активно используемых модулями. Финализатор обеспечивает невозможность удаления PersistentVolume из кластера до тех пор, пока его не используют поды. Выдача команды удаления при наличии активного модуля приведет к тому, что том будет помечен как Завершение; он будет оставаться в этом состоянии до тех пор, пока Pod нуждается в томе, а затем автоматически удаляется как можно скорее после этого.

Вызовы Финализатора

Длительно работающие финализаторы, ожидающие условия, затрагивающего другие ресурсы, могут привести к тому, что удаления застрянут в состоянии Завершение. Вы также можете столкнуться с проблемами, когда Finalizer блокирует удаление зависимых объектов, что препятствует успешному завершению работы родителя.

Эти проблемы регулярно вызывают путаницу — разработчики и операторы склонны рассматривать удаление как простую процедуру, тогда как на самом деле процесс многообразен и разнообразен. Предпосылки для успешного удаления зависят от отношений ресурса и их Финализаторов, а также от самого целевого объекта.

Когда объект находится в состоянии Завершение слишком долго, проверьте его финализаторы, проверив поле metadata.finalizers в его YAML:

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

Как только вы узнаете, какие финализаторы определены, вы можете начать идентифицировать те из них, которые могут заблокировать удаление. Просмотр событий объекта и изменений условий может помочь в отладке, показывая действия, которые произошли с момента подачи команды удаления. Условия отображаются в поле spec.status.conditions YAML; события видны при запуске kubectl description pod example-pod.

Вы можете вручную удалить финализаторы объекта, изменив поле spec.finalizers на null. Этот метод не следует использовать без крайней необходимости. Финализаторы — это меры безопасности, предназначенные для защиты вашего кластера; их переопределение может привести к потерянным объектам и нарушенным цепочкам зависимостей.

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

Владельцы и политика распространения

Смежной темой являются владельцы объектов и политики распространения удаления. Ссылки на владельцев определяют отношения между объектами. Они используются для удаления целых деревьев объектов при удалении родителя. Например, если вы удаляете развертывание, Kubernetes также должен уничтожить поды в этом развертывании.

Ссылки на владельца определяются через поле metadata.ownerReferences на объектах. Каждая ссылка включает вид и имя объекта, который является родительским для текущего ресурса.

Когда используются ссылки на владельца, удаление родителя автоматически удаляет все его дочерние элементы. Это называется каскадным удалением. Каскад можно отключить, добавив флаг --cascade=orphan в kubectl delete. Kubernetes позволит дочерним элементам объекта оставаться в кластере, оставляя их доступными, но осиротевшими.

Kubernetes также поддерживает различные «политики распространения» удаления. Они определяют, будут ли сначала удаляться родитель или его дочерние элементы. Политика Foreground по умолчанию удаляет дочерние элементы, а затем родитель, гарантируя отсутствие сиротства. Background инвертирует порядок, поэтому родитель удаляется первым. Третья политика, Orphan, предписывает Kubernetes полностью игнорировать ссылки на владельца.

Команда kubectl delete не поддерживает политики распространения. Вы должны сделать прямой запрос API, если хотите изменить политику для операции удаления:

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

Финализаторы учитываются, когда удаление распространяется или каскадируется на связанные объекты. В случае политики Foreground это означает, что все финализаторы на всех дочерних элементах должны быть завершены, прежде чем родитель сможет завершить работу. Для политики Background дочерние элементы будут оставаться активными до тех пор, пока их родительские финализаторы не закончат работу.

Реализация финализаторов

Вы можете реализовать свои собственные финализаторы с помощью Kubernetes API и Go SDK. Финализаторы создаются путем регистрации хуков в методе Reconcile контроллера.

Метод должен проверять, имеет ли объект для согласования значение в поле DeletionTimestamp. Это означает, что он ожидает удаления и находится в состоянии Завершение. Выберите идентификатор для финализатора и проверьте, включает ли объект значение в поле metadata.finalizers. Если это так, вы должны выполнить все необходимые действия, а затем отсоединить Финализатор от объекта. Пример реализации включен в руководство Kubebuilder по написанию собственных типов объектов Kubernetes с использованием CRD (настраиваемых определений ресурсов).

Финализаторы всегда реализуются как код в методе контроллера. Поле metadata.finalizers действует аналогично аннотациям и меткам, перечисляя финализаторы, которые нужно применить к этому объекту, без прямого определения кода для выполнения.

Заключение

Финализаторы управляют жизненным циклом объекта Kubernetes после инициации удаления. Они используются для реализации сборки мусора, уведомления контроллеров о предстоящем удалении и предотвращения случайного удаления объектов, на которые все еще ссылаются другие ресурсы.

Поскольку финализаторы могут блокировать удаление объектов на сколь угодно длительные периоды времени, они являются частым источником разочарования, когда команды операторов не понимают, почему объект «застревает» при завершении. В этой ситуации лучше проверить затронутые ресурсы, посмотреть, какие финализаторы активны, и исследовать отношения между объектами, которые могут действовать как блокирующие зависимости. Принудительное удаление Finalizer должно быть вашим последним средством, если вы должны немедленно удалить завершающий объект или исчерпали все другие варианты.