На какой низкоуровневой технологии в Linux работает механизм Limits (ограничений ресурсов) в Kubernetes?

«На какой низкоуровневой технологии в Linux работает механизм Limits (ограничений ресурсов) в Kubernetes?» — вопрос из категории Kubernetes, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Kubernetes для реализации limits и requests на уровне узлов (нод) полагается на механизм ядра Linux — control groups (cgroups). Именно cgroups обеспечивают изоляцию, учет и ограничение ресурсов (CPU, память, disk I/O) для группы процессов (в данном случае — для контейнера).

Как это работает:

  1. Когда kubelet создает контейнер через container runtime (например, containerd), он передает параметры лимитов.
  2. Runtime создает для контейнера cgroup в соответствующей подсистеме (например, cpu и memory).
  3. В эту cgroup помещаются все процессы контейнера, и к ней применяются заданные ограничения.

Конкретные реализации:

  • CPU limits: Используется подсистема cpu и механизм CFS (Completely Fair Scheduler) Bandwidth Control. Лимит (cpu.cfs_quota_us) определяет, сколько микросекунд CPU времени контейнер может использовать за период (cpu.cfs_period_us, обычно 100ms).
  • Memory limits: Используется подсистема memory. При достижении жесткого лимита (memory.limit_in_bytes) ядло Linux активирует OOM Killer, который завершает процесс в контейнере.

Пример манифеста и его низкоуровневое отображение:

# Pod spec в Kubernetes
spec:
  containers:
  - name: app
    resources:
      requests:
        memory: "256Mi"
        cpu: "500m"
      limits:
        memory: "512Mi"
        cpu: "1"

На узле это приведет к созданию cgroup, например, по пути /sys/fs/cgroup/memory/kubepods/pod-<uid>/container-<id>/, где в файл memory.limit_in_bytes будет записано значение 536870912 (512 MiB).

Для работы необходима поддержка cgroups в ядре и корректная настройка kubelet (флаги --cgroup-driver, --enforce-node-allocatable).