Порядок, в котором Kubernetes будет убивать поды в зависимости от QoS (Quality of Service)

«Порядок, в котором Kubernetes будет убивать поды в зависимости от QoS (Quality of Service)» — вопрос из категории Kubernetes, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Kubernetes при нехватке ресурсов на узле (в первую очередь памяти) начинает эвакуировать поды, начиная с наименее приоритетных с точки зрения QoS (Quality of Service). Порядок следующий:

  1. BestEffort — поды, у которых для всех контейнеров не заданы ни requests, ни limits. У них самый низкий приоритет.
  2. Burstable — поды, у которых для хотя бы одного контейнера заданы requests, но limits либо не заданы, либо превышают requests.
  3. Guaranteed — поды с наивысшим приоритетом. Для всех контейнеров в поде должны быть заданы и requests, и limits, причем requests.memory == limits.memory и requests.cpu == limits.cpu.

Пример манифеста для Guaranteed QoS:

apiVersion: v1
kind: Pod
metadata:
  name: guaranteed-pod
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        memory: "100Mi"
        cpu: "500m"
      limits:
        memory: "100Mi"  # Должно равняться request
        cpu: "500m"      # Должно равняться request

Важные нюансы:

  • Механизм убийства (eviction) срабатывает при давлении на вытесняемые ресурсы: память (memory.available) и файловую систему узла (nodefs.available, imagefs.available).
  • Для CPU Kubernetes не убивает поды, а троттлит (ограничивает) процессы контейнеров, если они превышают свои лимиты.
  • Внутри одного класса QoS Kubernetes может использовать другие приоритеты, например, сравнивать usage контейнеров против их requests.
  • OOM Killer на уровне ядра Linux может убить любой процесс, включая контейнеры, но он также учитывает oom_score_adj, который Kubernetes выставляет в зависимости от QoS класса.