Два пода оказались в Evicted статусе — начинаем разбираться.
Содержание
Kubernetes requests и limits
В Kubernetes мы имеем возможность ограничить используемые контейнерами ресурсы двумя способами — requests и limits:
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 100m
memory: 100Mi
Тут:
requests: используется Kubernetes Scheduler при выборе рабочей ноды, на которой будет запущен под — тут задаётся минимальное значение памяти и/или ЦПУ, которые должны быть доступны на ноде для запуска пода
limits: такой себе «hard-limit» — максимальное значение ресурсов, которые доступны контейнеру для использования
Поды в Kubernetes могут попадать под один из трёх классов Quality of Service (QoS):
Guaranteed: поды, для которых указаны реквесты и лимиты для всех контейнеров, и для всех они одинаковы
Burstable: не гарантированные поды, для которых задан реквест как минимум на CPU или память для одного из контейнеров
Best effort: поды без реквестов и лимитов вообще
Проверить QoS класс пода можно через describe pod -o yaml:
kubectl get pod appname-54545944b4-h8gmv -o yaml
...
resources:
requests:
cpu: 100m
...
qosClass: Burstable
...
Тут задан requests только на CPU, и под попадает под QoS class Burstable.
А теперь посмотрим — как QoS класс влияет на жизнь подов.
Node tolerations
Когда WorkerNode в кластере исчерпытывает доступные ей ресурсы — память, ЦПУ, диск и т.д. — scheduler кластера во-первых перестаёт добавлять новые поды на эту ноду.
Кроме того, Kubernetes к такой ноде добавляет аннотации, указывающие на проблему с нодой, например — node.kubernetes.io/memory-pressure.
В таком случае, kubelet на этой ноде начинает убивать запущенные контейнеры, а их поды отмечает как Failed.
Например, при заполнении диска — kubelet будет удалять в первую очередь неиспользуемые поды и их контейнеры, затем — удалять образы с дисков.
Если этого недостаточно — начинает «выселять» (собственно — Evict) пользовательские поды в следующем порядке:
Best Effort — поды без реквестов и лимитов вообще
Burstable — поды, использующие больше ресурсов, чем задано в их реквестах
Burstable — поды, использующие меньше ресурсов, чем задано в их реквестах
Guaranteed поды в целом не должны затрагиваться, но в случае, если системе на ноде потребуется больше ресурсов, чем доступно — то kubelet начнёт вытеснять с этой ноды даже те поды, которые попадают под Guaranteed QoS класс.
Увидеть, почему именно под был вынеснен с ноды можно в событиях этого пода.
Например, последние поды у нас сейчас:
kk -n eks-prod-1-web-projectname-admin-backend-ns get pod
kk -n eks-prod-1-web-projectname-admin-backend-ns get pod bttrm-web-projectname-admin-backend-7f4b5bdb4c-wlbjf -o yaml
...
status:
message: 'The node was low on resource: memory. Container bttrm-web-projectname-admin-backend
was using 1014836Ki, which exceeds its request of 300Mi. '
phase: Failed
reason: Evicted
Тут Kubernetes нам явно сообщает, что «Container was using 1014836Ki, which exceeds its request of 300Mi«.
Тут Ki == kibibyte (1024 байта, 8192 бита), а Mi — mebibyte, т.е. 1024 kibibytes, или 1048576 байт.
Проверяем — переведём 1014836Ki в мегабайты:
echo 1014836/1024 | bc
991
Почти гиг памяти.
И ещё раз посмотрим на ресурсы, заданные в Deployment этого пода:
kk -n eks-prod-1-web-projectname-admin-backend-ns get deploy bttrm-web-projectname-admin-backend -o yaml
...
resources:
limits:
memory: 3Gi
requests:
cpu: 100m
memory: 300Mi
...
Т.к. в лимитах во-первых не задан лимит на ЦПУ, во-вторых — лимиты и реквесты не одинаковы — то он попадает под Burstable QoS класс, плюс на этой ноде кроме подов этого деплоймента других подов не было — и Kubernetes его прибил.
Жил-был под на рабочей ноде 10.4.44.215 в статусе Running, а потом бац — и в 19:40 убился.
Посмотрим на состояние ноды 10.4.44.215 в это время:
Нода исчерпала доступную память (AWS EC2 t3.medium, 4GB RAM), и kubelet начал вытеснять поды.
И глянем ресурсы, которые под потреблял в этом время:
Собственно, видим, что на под прилетело немного входящего трафика — и он активно начал отжирать память.
Память на ноде закончилась — и kubelet этот под прибил.
Дальше уже вопрос к разработчикам — то ли это expected, и надо переселять этот проект на рабочие ноды, у которых больше доступной памяти, и увеличивать подам реквесты и лимиты — либо у них где-то memory leak, и тогда они уже сами будут это фиксить.