[Системное администрирование, Серверное администрирование, DevOps, Kubernetes] Контролируем удаление с финализаторами (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В Kubernetes не так-то просто что-то удалить — вы уверены, что удалили объект, но оказывается, что он все еще присутствует в кластере. Вы, конечно, можете выполнять команду kubectl delete в повседневных операциях и надеяться на лучшее, но знание принципов работы delete команд в Kubernetes поможет вам понять, почему некоторые объекты остаются после удаления.
В этой статье мы рассмотрим:
- Какие свойства ресурса влияют на удаление.
- Как финализаторы и ссылки на родителя-владельца управляют удалением объектов.
- Как можно использовать propagationPolicy, чтобы изменить порядок удаления.
- Как работает удаление, с примерами.
Для простоты во всех примерах мы используем ConfigMaps и базовые команды kubectl. Мы увидим, как работают эти команды, и обсудим результаты их использования на практике.
Базовая команда delete
В Kubernetes есть несколько команд для создания, чтения, обновления и удаления объектов. Здесь мы поговорим о четырех командах kubectl: create, get, patch и delete.
Примеры базовой команды kubectl delete:
kubectl create configmap mymap
configmap/mymap created
kubectl get configmap/mymap
NAME DATA AGE
mymap 0 12s
kubectl delete configmap/mymap
configmap "mymap" deleted
kubectl get configmap/mymap
Error from server (NotFound): configmaps "mymap" not found
Перед командой стоит знак $, далее следует ее результат. Как видите, мы начали с kubectl create configmap mymap, чтобы создать пустой configmap mymap. Теперь нужно выполнить get и убедиться, что он существует. Затем мы удалили configmap. Если снова сделать get, получим ошибку HTTP 404, потому что configmap не найден.
У команды deleteочень простая диаграмма состояний:
Диаграмма состояний для delete
Операция незамысловатая, но ей могут помешать некоторые факторы, включая финализаторы и ссылки на родителя-владельца.
Как работают финализаторы
Чтобы понять, как удаляются ресурсы в Kubernetes и почему они иногда все-таки не удаляются, полезно разобраться с финализаторами.
Финализаторы — это ключи в манифесте ресурса, отвечающие за операции, которые надо выполнить до удаления объекта. Они контролируют сборку мусора для ресурсов и сообщают контроллерам, какие операции очистки нужно выполнить до удаления ресурса. Они не обязательно обозначают код, который нужно выполнить. По сути, это просто списки ключей, вроде аннотаций. Как и аннотациями, ими также можно управлять.
Скорее всего, вы встречали следующие финализаторы:
- kubernetes.io/pv-protection
- kubernetes.io/pvc-protection
Они используются для постоянных томов и не дают случайно удалить их. Точно так же некоторые финализаторы могут использоваться для предотвращения удаления любого ресурса.
Ниже приводится configmap без свойств, но с финализатором:
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: mymap
finalizers:
- kubernetes
EOF
Контроллер ресурса configmap не понимает, что делать с ключом финализатора kubernetes. Такие финализаторы для configmap я называю «мертвыми», и обычно они используются с неймспейсами. Вот что происходит при попытке удалить configmap:
kubectl delete configmap/mymap &
configmap "mymap" deleted
jobs
[1]+ Running kubectl delete configmap/mymap
Kubernetes сообщает, что объект удален, но на самом деле, в традиционном понимании, никуда он не удален. Скорее он находится в процессе удаления. Если мы снова выполним get, то узнаем, что объект изменен и теперь содержит временную метку удаления deletionTimestamp.
kubectl get configmap/mymap -o yaml
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: "2020-10-22T21:30:18Z"
deletionGracePeriodSeconds: 0
deletionTimestamp: "2020-10-22T21:30:34Z"
finalizers:
- kubernetes
name: mymap
namespace: default
resourceVersion: "311456"
selfLink: /api/v1/namespaces/default/configmaps/mymap
uid: 93a37fed-23e3-45e8-b6ee-b2521db81638
Если в двух словах, объект был изменен, но не удален. Все потому, что Kubernetes увидел, что у объекта есть финализаторы, и поместил его в состояние read-only. Временная метка удаления показывает, что объект можно только читать — а еще из него можно удалить апдейты ключа финализатора. Другими словами, удаление будет завершено, только когда мы удалим из объекта финализатор.
Удалить финализаторы можно с помощью команды patch. Фоновое удаление завершится, и объект будет удален. Если мы опять выполним get configmap, то ничего не увидим.
kubectl patch configmap/mymap \
--type json \
--patch='[ { "op": "remove", "path": "/metadata/finalizers" } ]'
configmap/mymap patched
[1]+ Done kubectl delete configmap/mymap
kubectl get configmap/mymap -o yaml
Error from server (NotFound): configmaps "mymap" not found
Диаграмма состояния для финализации выглядит так:
Диаграмма состояний для финализации
Если мы попытаемся удалить объект с финализатором, он останется на этапе финализации, пока контроллер не удалит ключи финализаторов или финализаторы не будут удалены через Kubectl. Когда список финализаторов будет пуст, Kubernetes поместит его в очередь на удаление из реестра.
Ссылки на владельца
Ссылки на владельца (owner references) описывают отношения между группами объектов. Это свойства ресурсов, которые указывают, как они связаны друг с другом, чтобы можно было удалять целые деревья ресурсов.
Правила финализатора обрабатываются, если есть ссылки на владельца. Ссылки на владельца состоят из имени и UID. Они связывают ресурсы в одном неймспейсе и им нужен UID. Ссылки на владельца для подов обычно указывают на replica set, которому они принадлежат. Если удалить deploy или stateful set, дочерние replica set и pod тоже удалятся.
Посмотрим на примере, как работают ссылки на владельца. В первом примере мы сначала создаем родительский объект, а потом дочерний. В результате получаем простейший configmap со ссылками на владельца, то есть родителя:
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: mymap-parent
EOF
CM_UID=$(kubectl get configmap mymap-parent -o jsonpath="{.metadata.uid}")
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: mymap-child
ownerReferences:
- apiVersion: v1
kind: ConfigMap
name: mymap-parent
uid: $CM_UID
EOF
Если мы удалим дочерний объект, в котором есть ссылка на владельца, родитель никуда не денется:
kubectl get configmap
NAME DATA AGE
mymap-child 0 12m4s
mymap-parent 0 12m4s
kubectl delete configmap/mymap-child
configmap "mymap-child" deleted
kubectl get configmap
NAME DATA AGE
mymap-parent 0 12m10s
В следующем случае мы воссоздали configmap из примера выше. Если мы удалим родителя, а не дочерний объект, в котором есть ссылка на него, а потом сделаем get для configmap, то увидим, что все configmap пропали:
kubectl get configmap
NAME DATA AGE
mymap-child 0 10m2s
mymap-parent 0 10m2s
kubectl delete configmap/mymap-parent
configmap "mymap-parent" deleted
kubectl get configmap
No resources found in default namespace.
Получается, что если в дочернем объекте есть ссылка на родителя, он автоматически удаляется при удалении родителя. Это называется cascade. По умолчанию cascade имеет значение true, но можно указать --cascade=false в kubectl delete, чтобы удалить родительский объект, не трогая дочерние.
В следующем примере у нас есть родительский и дочерний объекты, а еще ссылки на владельца. Если мы удалим родителя, указав --cascade=false, дочерние объекты сохранятся:
kubectl get configmap
NAME DATA AGE
mymap-child 0 13m8s
mymap-parent 0 13m8s
kubectl delete --cascade=false configmap/mymap-parent
configmap "mymap-parent" deleted
kubectl get configmap
NAME DATA AGE
mymap-child 0 13m21s
Параметр --cascade указывает на политику распространения в API, которая позволяет менять порядок объектов удаления в дереве. В следующем примере используется отправка запроса к API через curl для удаления с фоновой политикой распространения (propagation policy):
kubectl proxy --port=8080 &
Starting to serve on 127.0.0.1:8080
curl -X DELETE \
localhost:8080/api/v1/namespaces/default/configmaps/mymap-parent \
-d '{ "kind":"DeleteOptions", "apiVersion":"v1", "propagationPolicy":"Background" }' \
-H "Content-Type: application/json"
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Success",
"details": { ... }
}
Политику распространения нельзя указать в командной строке с помощью kubectl — только при прямом вызове API. Просто создайте прокси, чтобы иметь доступ к серверу API со своего компьютера, и выполните команду curl с одним URL, чтобы послать команду delete.
Есть три варианта политики распространения:
- Foreground: дочерние объекты удаляются до родительского (обратный порядок).
- Background: родительский объект удаляется до дочерних (прямой порядок).
- Orphan: ссылки на владельца игнорируются.
Если вы удаляете объект, в котором есть ссылки на владельца, то финализаторы также будут учитываться. В результаты деревья объектов могут сохраняться, и удаление будет частичным. В этом случае изучите имеющиеся ссылки на владельца и финализаторы, чтобы понять, что происходит.
Принудительное удаление неймспейса
В некоторых случаях для удаления неймспейсов может потребоваться принудительная финализация: если вы удалили неймспейс и очистили все объекты в нем, но неймспейс по-прежнему существует, его можно удалить принудительно, обновив его подресурс, finalize. Так контроллер неймспейса поймет, что нужно удалить финализатор и выполнить очистку:
cat <<EOF | curl -X PUT \
localhost:8080/api/v1/namespaces/test/finalize \
-H "Content-Type: application/json" \
--data-binary @-
{
"kind": "Namespace",
"apiVersion": "v1",
"metadata": {
"name": "test"
},
"spec": {
"finalizers": null
}
}
EOF
Действовать нужно осторожно, иначе неймспейс будет удален, а осиротевшие объекты останутся, и Kubernetes запутается. В таком случае нужно заново создать неймспейс вручную, и тогда оставшиеся объекты снова в нем появятся, чтобы их можно было очистить и восстановить.
Итоги
Как показывают примеры, финализаторы могут помешать удалению ресурсов в Kubernetes, особенно если речь о родительских и дочерних объектах. Обычно финализаторы добавляются в код не просто так, поэтому нужно все проверить, прежде чем удалять их вручную. С помощью ссылок на владельца можно указывать и удалять деревья ресурсов, хотя и в этом случае будут учитываться финализаторы. Наконец, можно использовать политику распространения, чтобы указывать порядок удаления в прямых вызовах API и контролировать процесс удаления объектов. Теперь вы чуть больше знаете о том, как работает удаление в Kubernetes, и можете поэкспериментировать самостоятельно в продакшен-кластере.
Видео от автора:
Извините, данный ресурс не поддреживается. :(
===========
Источник:
habr.com
===========
===========
Автор оригинала: Aaron Alpar (Kasten)
===========Похожие новости:
- [Программирование, IT-инфраструктура, Управление проектами, Kubernetes] Интервью с Марселем Ибраевым о распиле монолита или «Успех распила монолита – грамотный менеджмент»
- [Программирование, DevOps, Kubernetes] Kubernetes Headless Service: А если Pod исчез?
- [Системное администрирование, IT-инфраструктура, DevOps] Как работает single sign-on (технология единого входа)? (перевод)
- [Настройка Linux, Open source, Виртуализация, Kubernetes] Изучение экоcистемы Kubernetes в 2021 году, global modal в React и 7 сетевых команд Linux для каждого сисадмина
- [Информационная безопасность, Системное администрирование, Сетевые технологии] Интеграция SAML в Zimbra OSE
- [Информационная безопасность, IT-инфраструктура, Микросервисы] Защита приложений в эпоху микросервисов (перевод)
- [Системное администрирование, IT-инфраструктура, DevOps, Kubernetes] Как мы собираем общие сведения о парке из Kubernetes-кластеров
- [Системное администрирование, Анализ и проектирование систем, Data Mining, DevOps, Data Engineering] Проблемы мониторинга дата-пайплайнов и как я их решал
- [Тестирование IT-систем, Тестирование веб-сервисов, DevOps] Тренды тестирования 2020-2021: правда и мифы
- [Программирование, Серверное администрирование, Управление проектами, DevOps] Постмортем инцидентов для начинающих (перевод)
Теги для поиска: #_sistemnoe_administrirovanie (Системное администрирование), #_servernoe_administrirovanie (Серверное администрирование), #_devops, #_kubernetes, #_finalizers, #_kubernetes, #_k8s, #_kubectl, #_blog_kompanii_southbridge (
Блог компании Southbridge
), #_sistemnoe_administrirovanie (
Системное администрирование
), #_servernoe_administrirovanie (
Серверное администрирование
), #_devops, #_kubernetes
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 24-Ноя 20:02
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В Kubernetes не так-то просто что-то удалить — вы уверены, что удалили объект, но оказывается, что он все еще присутствует в кластере. Вы, конечно, можете выполнять команду kubectl delete в повседневных операциях и надеяться на лучшее, но знание принципов работы delete команд в Kubernetes поможет вам понять, почему некоторые объекты остаются после удаления. В этой статье мы рассмотрим:
Для простоты во всех примерах мы используем ConfigMaps и базовые команды kubectl. Мы увидим, как работают эти команды, и обсудим результаты их использования на практике. Базовая команда delete В Kubernetes есть несколько команд для создания, чтения, обновления и удаления объектов. Здесь мы поговорим о четырех командах kubectl: create, get, patch и delete. Примеры базовой команды kubectl delete: kubectl create configmap mymap
configmap/mymap created kubectl get configmap/mymap
NAME DATA AGE mymap 0 12s kubectl delete configmap/mymap
configmap "mymap" deleted kubectl get configmap/mymap
Error from server (NotFound): configmaps "mymap" not found Перед командой стоит знак $, далее следует ее результат. Как видите, мы начали с kubectl create configmap mymap, чтобы создать пустой configmap mymap. Теперь нужно выполнить get и убедиться, что он существует. Затем мы удалили configmap. Если снова сделать get, получим ошибку HTTP 404, потому что configmap не найден. У команды deleteочень простая диаграмма состояний: Диаграмма состояний для delete Операция незамысловатая, но ей могут помешать некоторые факторы, включая финализаторы и ссылки на родителя-владельца. Как работают финализаторы Чтобы понять, как удаляются ресурсы в Kubernetes и почему они иногда все-таки не удаляются, полезно разобраться с финализаторами. Финализаторы — это ключи в манифесте ресурса, отвечающие за операции, которые надо выполнить до удаления объекта. Они контролируют сборку мусора для ресурсов и сообщают контроллерам, какие операции очистки нужно выполнить до удаления ресурса. Они не обязательно обозначают код, который нужно выполнить. По сути, это просто списки ключей, вроде аннотаций. Как и аннотациями, ими также можно управлять. Скорее всего, вы встречали следующие финализаторы:
Они используются для постоянных томов и не дают случайно удалить их. Точно так же некоторые финализаторы могут использоваться для предотвращения удаления любого ресурса. Ниже приводится configmap без свойств, но с финализатором: cat <<EOF | kubectl create -f -
apiVersion: v1 kind: ConfigMap metadata: name: mymap finalizers: - kubernetes EOF Контроллер ресурса configmap не понимает, что делать с ключом финализатора kubernetes. Такие финализаторы для configmap я называю «мертвыми», и обычно они используются с неймспейсами. Вот что происходит при попытке удалить configmap: kubectl delete configmap/mymap &
configmap "mymap" deleted jobs [1]+ Running kubectl delete configmap/mymap Kubernetes сообщает, что объект удален, но на самом деле, в традиционном понимании, никуда он не удален. Скорее он находится в процессе удаления. Если мы снова выполним get, то узнаем, что объект изменен и теперь содержит временную метку удаления deletionTimestamp. kubectl get configmap/mymap -o yaml
apiVersion: v1 kind: ConfigMap metadata: creationTimestamp: "2020-10-22T21:30:18Z" deletionGracePeriodSeconds: 0 deletionTimestamp: "2020-10-22T21:30:34Z" finalizers: - kubernetes name: mymap namespace: default resourceVersion: "311456" selfLink: /api/v1/namespaces/default/configmaps/mymap uid: 93a37fed-23e3-45e8-b6ee-b2521db81638 Если в двух словах, объект был изменен, но не удален. Все потому, что Kubernetes увидел, что у объекта есть финализаторы, и поместил его в состояние read-only. Временная метка удаления показывает, что объект можно только читать — а еще из него можно удалить апдейты ключа финализатора. Другими словами, удаление будет завершено, только когда мы удалим из объекта финализатор. Удалить финализаторы можно с помощью команды patch. Фоновое удаление завершится, и объект будет удален. Если мы опять выполним get configmap, то ничего не увидим. kubectl patch configmap/mymap \
--type json \ --patch='[ { "op": "remove", "path": "/metadata/finalizers" } ]' configmap/mymap patched [1]+ Done kubectl delete configmap/mymap kubectl get configmap/mymap -o yaml Error from server (NotFound): configmaps "mymap" not found Диаграмма состояния для финализации выглядит так: Диаграмма состояний для финализации Если мы попытаемся удалить объект с финализатором, он останется на этапе финализации, пока контроллер не удалит ключи финализаторов или финализаторы не будут удалены через Kubectl. Когда список финализаторов будет пуст, Kubernetes поместит его в очередь на удаление из реестра. Ссылки на владельца Ссылки на владельца (owner references) описывают отношения между группами объектов. Это свойства ресурсов, которые указывают, как они связаны друг с другом, чтобы можно было удалять целые деревья ресурсов. Правила финализатора обрабатываются, если есть ссылки на владельца. Ссылки на владельца состоят из имени и UID. Они связывают ресурсы в одном неймспейсе и им нужен UID. Ссылки на владельца для подов обычно указывают на replica set, которому они принадлежат. Если удалить deploy или stateful set, дочерние replica set и pod тоже удалятся. Посмотрим на примере, как работают ссылки на владельца. В первом примере мы сначала создаем родительский объект, а потом дочерний. В результате получаем простейший configmap со ссылками на владельца, то есть родителя: cat <<EOF | kubectl create -f -
apiVersion: v1 kind: ConfigMap metadata: name: mymap-parent EOF CM_UID=$(kubectl get configmap mymap-parent -o jsonpath="{.metadata.uid}") cat <<EOF | kubectl create -f - apiVersion: v1 kind: ConfigMap metadata: name: mymap-child ownerReferences: - apiVersion: v1 kind: ConfigMap name: mymap-parent uid: $CM_UID EOF Если мы удалим дочерний объект, в котором есть ссылка на владельца, родитель никуда не денется: kubectl get configmap
NAME DATA AGE mymap-child 0 12m4s mymap-parent 0 12m4s kubectl delete configmap/mymap-child configmap "mymap-child" deleted kubectl get configmap NAME DATA AGE mymap-parent 0 12m10s В следующем случае мы воссоздали configmap из примера выше. Если мы удалим родителя, а не дочерний объект, в котором есть ссылка на него, а потом сделаем get для configmap, то увидим, что все configmap пропали: kubectl get configmap
NAME DATA AGE mymap-child 0 10m2s mymap-parent 0 10m2s kubectl delete configmap/mymap-parent configmap "mymap-parent" deleted kubectl get configmap No resources found in default namespace. Получается, что если в дочернем объекте есть ссылка на родителя, он автоматически удаляется при удалении родителя. Это называется cascade. По умолчанию cascade имеет значение true, но можно указать --cascade=false в kubectl delete, чтобы удалить родительский объект, не трогая дочерние. В следующем примере у нас есть родительский и дочерний объекты, а еще ссылки на владельца. Если мы удалим родителя, указав --cascade=false, дочерние объекты сохранятся: kubectl get configmap
NAME DATA AGE mymap-child 0 13m8s mymap-parent 0 13m8s kubectl delete --cascade=false configmap/mymap-parent configmap "mymap-parent" deleted kubectl get configmap NAME DATA AGE mymap-child 0 13m21s Параметр --cascade указывает на политику распространения в API, которая позволяет менять порядок объектов удаления в дереве. В следующем примере используется отправка запроса к API через curl для удаления с фоновой политикой распространения (propagation policy): kubectl proxy --port=8080 &
Starting to serve on 127.0.0.1:8080 curl -X DELETE \ localhost:8080/api/v1/namespaces/default/configmaps/mymap-parent \ -d '{ "kind":"DeleteOptions", "apiVersion":"v1", "propagationPolicy":"Background" }' \ -H "Content-Type: application/json" { "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Success", "details": { ... } } Политику распространения нельзя указать в командной строке с помощью kubectl — только при прямом вызове API. Просто создайте прокси, чтобы иметь доступ к серверу API со своего компьютера, и выполните команду curl с одним URL, чтобы послать команду delete. Есть три варианта политики распространения:
Если вы удаляете объект, в котором есть ссылки на владельца, то финализаторы также будут учитываться. В результаты деревья объектов могут сохраняться, и удаление будет частичным. В этом случае изучите имеющиеся ссылки на владельца и финализаторы, чтобы понять, что происходит. Принудительное удаление неймспейса В некоторых случаях для удаления неймспейсов может потребоваться принудительная финализация: если вы удалили неймспейс и очистили все объекты в нем, но неймспейс по-прежнему существует, его можно удалить принудительно, обновив его подресурс, finalize. Так контроллер неймспейса поймет, что нужно удалить финализатор и выполнить очистку: cat <<EOF | curl -X PUT \
localhost:8080/api/v1/namespaces/test/finalize \ -H "Content-Type: application/json" \ --data-binary @- { "kind": "Namespace", "apiVersion": "v1", "metadata": { "name": "test" }, "spec": { "finalizers": null } } EOF Действовать нужно осторожно, иначе неймспейс будет удален, а осиротевшие объекты останутся, и Kubernetes запутается. В таком случае нужно заново создать неймспейс вручную, и тогда оставшиеся объекты снова в нем появятся, чтобы их можно было очистить и восстановить. Итоги Как показывают примеры, финализаторы могут помешать удалению ресурсов в Kubernetes, особенно если речь о родительских и дочерних объектах. Обычно финализаторы добавляются в код не просто так, поэтому нужно все проверить, прежде чем удалять их вручную. С помощью ссылок на владельца можно указывать и удалять деревья ресурсов, хотя и в этом случае будут учитываться финализаторы. Наконец, можно использовать политику распространения, чтобы указывать порядок удаления в прямых вызовах API и контролировать процесс удаления объектов. Теперь вы чуть больше знаете о том, как работает удаление в Kubernetes, и можете поэкспериментировать самостоятельно в продакшен-кластере. Видео от автора: Извините, данный ресурс не поддреживается. :( =========== Источник: habr.com =========== =========== Автор оригинала: Aaron Alpar (Kasten) ===========Похожие новости:
Блог компании Southbridge ), #_sistemnoe_administrirovanie ( Системное администрирование ), #_servernoe_administrirovanie ( Серверное администрирование ), #_devops, #_kubernetes |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 24-Ноя 20:02
Часовой пояс: UTC + 5