Команда Kubernetes as a Service в Mail.ru Cloud Solutions перевела статью, в которой автор помогает найти причины ошибок в Kubernetes, если вы совсем не понимаете, куда нужно смотреть. Далее текст от лица автора.
Kubernetes — непростая платформа, особенно когда что-то пошло не так и нужно срочно найти и устранить возникшую проблему. В основном трудности объясняются сложностью самой системы и отсутствием подробных сообщений об ошибках. Ситуация усугубляется еще и огромным количеством «шестеренок» в потоке оркестрации контейнеров — при том что для представления этого потока используется всего лишь несколько состояний. Например, есть как минимум шесть возможных причин, по которым под может зависнуть в состоянии ContainerCreating
или CrashLoppBackOff
.
Мы активно работаем с Kubernetes уже более трех лет и за это время составили длинный список сложных и в то же время трудно диагностируемых проблем. Большинство из них можно отнести к одной из трех категорий:
- Зависание пода в состоянии
ContainerCreating
. - Ошибка
CrashLoopBackOff
и периодический перезапуск контейнера. - Проблемы с сетью.
Причины этих сбоев могут быть совершенно разными, и в этой статье мы поможем вам понять, что происходит и почему. Мы не ставим перед собой цель выдать вам список команд и узкоспециализированных инструментов на все случаи жизни. Скорее, мы хотели бы расширить ваше понимание и помочь развить интуицию, на которую вы в дальнейшем сможете опираться, если Kubernetes будет работать не так, как надо.
Когда что-то идет не так, в первую очередь нужно заглянуть в лог Kubernetes (kubectl get events -n <NAMESPACE>
). В нем подробно записаны все шаги оркестрации, а это самое главное в любой диагностике.
1. Поды зависают в состоянии ContainerCreating
Ключ к пониманию ContainerCreating
(как, впрочем, и любого другого состояния пода) — это четкое представление, где именно он находится в оркестрации Kubernetes. Эта информация поможет нам определить и исключить другие компоненты стека.
Например, ContainerCreating
подразумевает, что kube-scheduler
назначил контейнеру рабочий узел и дал демону Docker
инструкцию запустить рабочую нагрузку, но на этом этапе еще не выделены сетевые ресурсы — то есть у рабочей нагрузки нет IP-адреса.
Давайте рассмотрим некоторые типовые причины, вызывающие зависание пода на этапе ContainerCreating
:
1.1 Сбой при выделении IP-адреса
KubeControlPlane
запрашивает IP-адрес у CNI (например, Calico), а если выделить IP-адрес не удается, ControlPlane
просто ждет до бесконечности. При этом «на поверхности» в журнале нет ни ошибок, ни трассировки, и команда kubectl
тоже не выдает никакой информации. Эта проблема фиксируется только в логах kubelet/system
.
Причины:
- Нехватка IP-адресов в
IPPool
, настроенном в вашемCNI
. - Ошибки связи между
kubelet
иCNI
. - Ошибки конфигурации в
CNI
.
1.2 Ошибка монтирования Configmap
Configmaps
содержат файлы, которые монтируются в (виртуализированную) файловую систему контейнера в среде исполнения. Этот этап оркестрации фиксируется в логах.
Причины:
-
/var/lib/docker
на узле переполнен: из-за этого демон Docker на узле не может работать нормально. - Ошибки или опечатки в имени
Configmap
, на который ссылается деплоймент пода.
1.3 Сбой при запросе Persistent Volumes
Контейнеры, хранящие данные о состоянии, например, базы данных или платформы обмена сообщениями, тоже могут застрять на этапе ContainerCreating
, если им не удается смонтировать PersistentVolume
через PersistentVolumeClaim
. Эта ситуация регистрируется в журналах событий; более подробную информацию можно найти в системных логах.
Причины:
- Ошибка связи между плагином Kubernetes CSI и облачным провайдером.
-
ControlPlane
выполняет процедурыattach
иdetach
для перемещения дисков, когда рабочие нагрузки проходят через узлы в кластере. И иногда этот процесс занимает больше времени, чем обычно, из-за тайм-аутов при выполнении операций mount и umount.
2. CrashLoopBackOff и периодические перезапуски
Ошибка CrashLoopBackOff
часто объясняется сбоями в коде контейнера или в самой программе. Это происходит, когда после запуска в контейнере команда entrypoint
завершается с ошибкой. Причин у такой ошибки может быть множество, но прежде всего следует обратить внимание на следующие:
2.1 Ошибки в скрипте Startup или InitContainers
Помимо программных ошибок в самом контейнере, к сбою запуска могут привести и внешние сбои при вводе переменных среды, параметры монтирования, секреты или обращение к другим объектам Kubernetes.
2.2 Превышение лимитов памяти
Если контейнер превышает лимиты памяти, установленные для пода, Kubernetes подает сигнал о прерывании выполняющегося процесса. Если такое случается часто, скорее всего, количество перезапусков пода будет возрастать.
2.3 Нехватка места на диске или в хранилище
К сбою контейнера на узле может привести нехватка места для хранения в двух местах:
-
PersistentVolume
самого пода, который влияет на процессы контейнера. -
/var/lib/docker
(OverlayFS Docker) на рабочем узле, на котором запланирован под.
2.4 Проверка работоспособности
Механизм проверки работоспособности (liveness probe) в Kubernetes позволяет ControlPlane
автоматически перезапускать вышедшие из строя контейнеры и таким образом восстанавливать работу. В то же время, если такие проверки проводятся слишком часто или просто настроены неправильно, без учета отложенных запусков восстановления, это может сказаться на стабильности работы:
-
При высокой частоте liveness probe Kubernetes часто выполняет проверки. Но, например, если контейнер находится в середине критического события GC (в случае Java), скорее всего, проверка работоспособности покажет отрицательный результат — и все закончится перезагрузкой контейнера.
-
Измененный/отсроченный запуск при восстановлении: иногда время запуска контейнера увеличивается из-за попыток исправить сбои, возникшие в результате аварийного завершения. Это часто видно по stateful-приложениям, которые запускают процедуры восстановления, чтобы справиться с разными неисправностями вроде поврежденной файловой системы. Так что если в настройках проверки работоспособности для этого недостаточно люфта, контейнер может застрять в цикле бесконечных перезапусков.
3. Проблемы с сетью
Программно-определяемая сеть Kubernetes — сама по себе вещь достаточно сложная, а поиск и устранение проблем в ее сетевых настройках и вовсе отдельный квест. Например, проблемы с подключением в кластере может создать сбой одного компонента, особенно в сетевом стеке. В конечном счете вам придется искать проблему в разных местах. Так что в этой ситуации имеет смысл начать со стратегических точек и постепенно сужать круг поиска.
Если перед вами встает задача отладить работу внутренней сети Kubernetes, разумно сосредоточиться прежде всего на следующих областях.
3.1 Kube-proxy и таблицы IP-адресов
Основное назначение kube-proxy
— установить связь между Service IP и конечными точками его бэкэнда (Pod IP
). Так что если ваш под находится на узле, который не может подключиться к service IP
и при этом система выводит сообщения об ошибках «тайм-аут подключения» или «в подключении отказано», то в большинстве случаев проблему можно решить, просто перезапустив kube-proxy
. Ведь, как и с любой другой рабочей нагрузкой, ваш контейнер kube-proxy
мог просто выйти из строя на этом узле.
Таблица IP-адресов
— это ключевой компонент маршрутизации трафика между сервисами (service) и подами, включая связь через NodePorts
. Kube-proxy
использует таблицу IP-адресов для настройки правил, которые помогают балансировать и маскировать нагрузку. Так что если поды могут связываться с IP-адресами других подов, но не с Service IP
, то ответ на вопрос можно найти именно в таблице IP-адресов.
3.2 Kube-DNS
Первое, на что нужно смотреть в случае проблем с разрешением имен, это внутренние настройки DNS в кластере Kubernetes (служба DNS по умолчанию — kubedns
). Убедитесь, что служба доступна через IP-адрес кластера или пода.
Во-вторых, проверьте, содержит ли resolv.conf
в ваших подах и рабочих узлах необходимые домены DNS и сервер доменных имен для поиска.
3.3 Conntrack
Проблемы в Conntrack
могут привести к обрыву связи или несоответствиям в сетевом трафике. Вкратце: с помощью conntrack ядро Linux поддерживает состояния связи и логические потоки в системе. То есть, скажем, если ваше приложение использует внешний IP, к которому выполняются миллионы подключений, то состояние этих подключений и логические потоки отслеживаются в таблице ядра conntrack
. Само собой, для таких таблиц conntrack
установлены жесткие лимиты, и в случае превышения в сети начинаются неполадки.
В RHEL лимиты подключения conntrack
можно проверить следующим образом:
$ sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_maxnet.netfilter.nf_conntrack_count = 167012
net.netfilter.nf_conntrack_max = 262144
3.5 CNI и таблица маршрутизации
Когда ваш daemonset CNI
(например, Calico
) выходит из строя на любом узле, это приводит к сбою маршрутизации и сетевого подключения в кластере Kubernetes, часто только на узлах, в которых случился сбой.
По аналогии с kube-proxy
проблему может решить перезапуск контейнера Calico на этом узле или контроллера Calico
. Поды CNI подвержены сбоям так же, как и любые другие рабочие нагрузки в кластере.
Заключение
Kubernetes — это сложная платформа, и устранение ее неисправностей — задача нетривиальная. Например, к одному зависшему состоянию ContainerCreating
могут привести совершенно разные причины, от сбоя при распределении IP-адресов до проблем с монтированием диска. Прежде всего, эти сложности объясняются большим количеством динамических компонентов платформы и разнообразием взаимосвязей между ними.
Мы рассмотрели три категории неисправностей и несколько проблем, которые стоят за ними:
- Зависание подов в состоянии
ContainerCreating
. - Ошибка
CrashLoopBackOff
и периодический перезапуск контейнера. - Проблемы с сетью.
Мы ненадолго заглянули на внутреннюю кухню Kubernetes и сделали первые шаги на пути к развитию интуиции, которая подскажет вам, где искать причину неисправностей, которые случаются здесь не так уж редко.
На платформе Mail.ru Cloud Solutions вы можете подключить Kubernetes as a Service. Новые пользователи при регистрации получают 3000 бонусных рублей, которые можно потратить на тестирование и ознакомление с платформой.
А в этой статье мы рассказываем, как устроен наш Kubernetes aaS, что у него под капотом и какие есть дополнительные функции.
Что еще почитать: