Гид по технологиям

Finalizers в Kubernetes: удаление и устранение блокировок

8 min read Kubernetes Обновлено 12 Dec 2025
Finalizers в Kubernetes: удаление и устранение блокировок
Finalizers в Kubernetes: удаление и устранение блокировок

Иллюстрация: логотип Kubernetes

Finalizers — это механизм Kubernetes, который откладывает окончательное удаление объекта до выполнения заранее определённых действий (например, очистки зависимостей или освобождения ресурсов). Они полезны для защиты от случайного удаления и для реализации корректной процедуры garbage collection, но могут приводить к «зависшим» объектам в состоянии Terminating. В статье описаны назначение Finalizers, типичные причины зависания, пошаговые методики диагностики, шаблоны решения инцидентов и рекомендации по безопасному принудительному удалению.

Быстрые ссылки

  • Что такое Finalizers?

  • Проблемы с Finalizers

  • Владелец и политики распространения удаления

  • Реализация Finalizers в контроллере

  • План действий при инциденте и чек-листы

Что такое Finalizers?

Finalizers — это список идентификаторов, сохранённых в поле metadata.finalizers объекта Kubernetes, которые дают контроллерам или другим компонентам шанс выполнить завершающие операции перед окончательным удалением объекта. Когда вы запускаете команду, например:

kubectl delete namespace/example

Kubernetes отмечает объект как ожидающий удаления и помещает его в состояние Terminating. Объект не будет удалён окончательно, пока его metadata.finalizers не станет пустым — каждый финализатор должен завершить свою работу и удалить свой идентификатор из списка.

Короткая последовательность удаления:

  1. Выпущена команда удаления — объект помечается как ожидающий удаления (DeletionTimestamp) и переходит в состояние Terminating.
  2. Для каждого идентификатора из metadata.finalizers выполняются соответствующие действия (освобождение ресурсов, уведомления, garbage collection и т. п.). После выполнения финализатор удаляет свою запись из metadata.finalizers.
  3. Когда metadata.finalizers пуст, Kubernetes физически удаляет объект.

Пример встроенного финализатора: PersistentVolume обычно имеет kubernetes.io/pv-protection — он препятствует удалению тома, пока на нём монтируются Pods. Если том всё ещё используется, объект будет помечен Terminating и останется таким, пока Pods не перестанут обращаться к PV.

Важно: Finalizers — это не код, а маркеры/флаги, которые указывают на необходимость выполнения кода в контроллере. Реализация действий финализатора выполняется в логике контроллера (operator / controller-runtime / custom controller).

Проблемы с Finalizers

Долгие или зависшие финализаторы — частая причина того, что объекты «зависают» в Terminating. Типичные сценарии проблем:

  • Финализатор ожидает удаления/изменения другого ресурса, который сам завис или удалён некорректно.
  • Контроллер, ответственный за выполнение финализатора, отсутствует, упал или неправильно настроен.
  • Ошибки сетевого взаимодействия или перебои в доступе к внешним системам (облачным API, СХД, DNS) мешают завершению операций.
  • Неправильно реализован контроллер: не обрабатывает DeletionTimestamp, не удаляет свой идентификатор или имеет гонки при обновлении объекта.

Симптомы:

  • Объект долго находится в состоянии Terminating.
  • В metadata.finalizers видны один или несколько идентификаторов.
  • В событиях (kubectl describe) видим повторяющиеся ошибки выполнения контроллера или тайм-ауты.

Диагностика: сначала посмотрите текущее состояние и финализаторы объекта:

kubectl get pod example-pod --namespace example -o json | jq '.metadata.finalizers'

Или вывести весь YAML:

kubectl get pod example-pod --namespace example -o yaml

Скриншот поля finalizers в определении объекта Kubernetes

Просмотрите события и условия:

kubectl describe pod example-pod --namespace example

События и поля в spec.status.conditions показывают, какие операции происходили после запуска удаления — это помогает понять, какой компонент блокирует завершение.

В крайнем случае можно вручную убрать финализатор, но это опасно и должно применяться только после анализа всех зависимостей:

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

Примечание: в примере выше мы патчим metadata.finalizers — именно это поле контролирует поведение удаления. Принудительное удаление финализатора может оставить «осиротевшие» ресурсы.

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

Связанные с Finalizers концепции — ownerReferences и propagationPolicy (политики распространения удаления). Owner references устанавливают иерархию зависимостей между объектами: когда родитель удаляется, Kubernetes может по умолчанию удалить и дочерние объекты (каскадное удаление).

ownerReferences определяются в metadata.ownerReferences и содержат поля kind, name, uid и другие метаданные.

Политики распространения удаления:

  • Foreground — дети удаляются первыми; родитель остаётся в Terminating, пока все дети (и их финализаторы) не будут удалены.
  • Background — родитель удаляется первым, а удаление детей выполняется асинхронно.
  • Orphan — игнорирует ownerReferences: дети остаются в кластере.

Некоторые клиенты/утилиты выставляют поведение каскада через флаги (kubectl поддерживает –cascade), но для явного указания propagationPolicy через API иногда используют прямой запрос к API-серверу. Например, через curl можно отправить DeleteOptions с propagationPolicy:

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

Реализация финализаторов учитывается при каскадном удалении: при Foreground-политике финализаторы всех дочерних объектов должны завершиться прежде, чем удалится родитель.

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

Finalizers реализуются в коде контроллера: при пересмотре объекта (Reconcile) контроллер должен проверять наличие DeletionTimestamp — это сигнал, что объект помечен на удаление. Стандартная последовательность действий контроллера:

  1. Если object.DeletionTimestamp == nil и финализатор отсутствует, добавить финализатор (если требуется защитить ресурс).
  2. Если object.DeletionTimestamp != nil и финализатор присутствует, выполнить завершающие операции:
    • Освободить внешние ресурсы (например, облачные тома, записи DNS, webhook-уведомления).
    • Убедиться, что зависимости удалены или корректно обработаны.
    • Обновить статус и удалить идентификатор финализатора из metadata.finalizers.

В Kubebuilder и controller-runtime есть шаблоны и гайдлайны, которые показывают, как правильно добавлять и удалять финализаторы и как безопасно обновлять объект с учётом конфликтов при обновлении (retry on conflict).

Пример логики в псевдокоде:

if object.DeletionTimestamp != nil {
  if containsFinalizer(object, myFinalizer) {
    // выполнить действия очистки
    if cleanupSuccessful {
      removeFinalizer(object, myFinalizer)
      update(object)
    } else {
      // requeue и повторить позже
    }
  }
} else {
  if !containsFinalizer(object, myFinalizer) {
    addFinalizer(object, myFinalizer)
    update(object)
  }
}

Важно: операции очистки должны быть идемпотентны и устойчивы к сбоям — контроллер может быть перезапущен и пересмотр объекта должен корректно возобновить работу.

План действий при инциденте: пошаговый playbook

Ниже — набор шагов для инженера, столкнувшегося с объектом в состоянии Terminating.

  1. Инвентаризация
    • Получить YAML объекта: kubectl get -o yaml.
    • Просмотреть metadata.finalizers и metadata.ownerReferences.
    • Просмотреть события: kubectl describe .
  2. Диагностика контроллеров
    • Определить, какой контроллер отвечает за финализатор (идентификатор финализатора часто содержит имя контроллера).
    • Проверить Pods/Deployment контроллера: находятся ли они в Ready-состоянии?
    • Посмотреть логи контроллера: kubectl logs -n .
  3. Анализ зависимостей
    • Проверить связанные ресурсы (через ownerReferences и ссылки в annotations/labels).
    • Убедиться, что внешние API/интеграции доступны.
  4. Безопасные исправления
    • Если контроллер восстановим: устранить причину и дождаться, пока финализатор выполнит работу.
    • Если контроллер отсутствует навсегда (например, удалённый operator), изучить последствия удаления финализатора.
  5. Принудительный путь (последний шаг)
    • Сделать бэкап важной информации (export YAML, копии данных).
    • Удалить финализатор через kubectl patch: kubectl patch -p ‘{“metadata”: {“finalizers”: null}}’
    • Проверить, не появились ли осиротевшие ресурсы и удалить/реассоциировать их вручную.

Критерии приёмки для успешного инцидента:

  • Объект перестал быть в Terminating и корректно удалён.
  • Никакие критические ресурсы не оказались осиротевшими (неиспользуемые PV, облачные тома, записи DNS и т. п.).
  • Восстановлены контроллеры или внесены изменения в инфраструктуру, исключающие повторение проблемы.

Ролe-зависимые чек-листы (Developer, Operator, SRE)

Operator / SRE:

  • Проверить состояние контроллеров, управляющих финализаторами.
  • Просмотреть события и логи контроллера.
  • Проверить состояние кластера (NetworkPolicy, AdmissionControllers, API-server).
  • Выполнить принудительное удаление только после оценки рисков и создания миграционного плана.

Developer:

  • Убедиться, что ваш контроллер корректно реагирует на DeletionTimestamp.
  • Реализовать идемпотентные операции очистки.
  • Добавлять финализаторы только если это действительно необходимо.

Product Owner / Архитектор:

  • Решить политику существования ресурсов: кто и когда отвечает за удаление внешних артефактов.
  • Утвердить fallback-стратегию на случай удаления контроллера.

Инцидентный план отката и тестовый сценарий

Инцидентный план:

  1. Откат конфигураций контроллера (если недавно был деплой) на прошлую стабильную версию.
  2. Перезапустить контроллеры и дождаться выполнения финализаторов.
  3. Если контроллера нет — применить ручной процесс очистки и удалить финализаторы, затем пересмотреть архитектуру.

Тесты и критерии приёмки (примерные):

  • Unit-тесты: покрывают код удаления финализатора и обработку ошибок внешних вызовов.
  • Интеграционные тесты: симулируют DeletionTimestamp и проверяют, что контроллер корректно удаляет финализатор после успешной очистки.
  • Acceptance: при удалении родительского объекта все дочерние удаляются (или остаются как Orphan, если это ожидаемо) и никаких внешних ресурсов не остаётся в неконсистентном состоянии.

Decision tree для диагностики (Mermaid)

flowchart TD
  A[Объект в Terminating?] -->|Нет| B[Конец]
  A -->|Да| C[Проверить metadata.finalizers]
  C --> D{finalizers пусты}
  D -->|Да| E[Проблема не в финализаторах]
  D -->|Нет| F[Определить контроллер финализатора]
  F --> G{Контроллер запущен и Ready?}
  G -->|Да| H[Проверить логи и события контроллера]
  G -->|Нет| I[Восстановить/деплоить контроллер]
  H --> J{Ошибки внешних интеграций?}
  J -->|Да| K[Исправить интеграцию]
  J -->|Нет| L[Выполнить ручную очистку или удалить финализатор]
  I --> M[После восстановления дождаться завершения]
  L --> N[Мониторинг и проверка осиротевших ресурсов]
  N --> B
  E --> B

Когда нельзя просто удалить финализатор — варианты отказа

  • Если удаление финализатора приведёт к утрате данных (например, тома) или рассинхронизации внешних систем.
  • Если финализатор гарантирует отправку уведомлений/событий для других приложений — удаление может нарушить бизнес-процессы.
  • Когда финализатор управляет критичными ресурсами облака (квоты, биллинг) — удаление без ручной проверки может привести к непредсказуемым расходам.

Всегда сначала проводите анализ последствий удаления: какие внешние артефакты связаны с объектом и кто за них отвечает.

Альтернативные подходы и архитектурные рекомендации

  • Минимизируйте число финализаторов и используйте их лишь для действительно критичных операций.
  • Проектируйте контроллеры так, чтобы они могли корректно завершать работу при повторных вызовах (идемпотентность).
  • Для внешних ресурсов используйте дополнительные механизмы защиты (например, locks, TTL, внешние очереди задач), чтобы финализатор не зависел напрямую от единственной точки отказа.
  • Документируйте контракт контроллера: какие финализаторы он использует и какие внешние операции выполняет.

Риски и смягчение

Риски:

  • Осиротевшие ресурсы и утечка затрат.
  • Отсутствие уведомления владельцев о том, что ресурсы не были корректно освобождены.
  • Нарушение целостности данных.

Меры смягчения:

  • Автоматизированный аудит объектов с финализаторами (крон-задание, которое уведомляет команду при длинном Terminating).
  • Политики резервного копирования и удержание метаданных для ручного восстановления.
  • Соглашения внутри команды о модели владения и ответственности (Owner shifts).

1‑строчный глоссарий

  • Finalizer: идентификатор в metadata.finalizers, указывающий на необходимость завершающей операции перед удалением объекта.
  • DeletionTimestamp: метка, сигнализирующая, что объект помечен на удаление.
  • OwnerReference: ссылка на родительский объект, используемая при каскадном удалении.
  • PropagationPolicy: политика определения порядка удаления родителя и детей (Foreground/Background/Orphan).

Краткое резюме

Finalizers — мощный инструмент управления жизненным циклом ресурсов в Kubernetes, который обеспечивает корректную очистку и предотвращает случайное удаление зависимых ресурсов. Однако они требуют правильной реализации контроллеров и процедуры реагирования при инцидентах — в противном случае объекты могут «зависать» в Terminating. Всегда сначала проводите диагностику и оценивайте риски перед принудительным удалением финализаторов.

Важно

  • Принудительное удаление финализатора — крайняя мера. Всегда делайте бэкап и оцените все зависимости.

Примечание

  • Документируйте поведение финализаторов и включайте проверку их состояния в процессы постдеплоя и мониторинга.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как отписаться от каналов YouTube — быстро и правильно
Руководство

Как отписаться от каналов YouTube — быстро и правильно

Удалить плейлист на YouTube — быстро
How-to

Удалить плейлист на YouTube — быстро

Как посмотреть текст песни в YouTube Music
Музыка

Как посмотреть текст песни в YouTube Music

Как смотреть падение шара Times Square 2023
Развлечения

Как смотреть падение шара Times Square 2023

Удалить Google Drive с Mac — полное руководство
Mac

Удалить Google Drive с Mac — полное руководство

Сохранить страницу офлайн в Brave
Браузеры

Сохранить страницу офлайн в Brave