Нове перетворення з cgroup v1 CPU Shares на v2 CPU Weight

Я радий повідомити про впровадження вдосконаленої формули перетворення з cgroup v1 CPU shares на cgroup v2 CPU weight. Це вдосконалення вирішує критичні проблеми з розподілом пріоритетів CPU для робочих навантажень Kubernetes під час роботи на системах з cgroup v2.

Історія

Kubernetes спочатку був розроблений з урахуванням cgroup v1, де CPU shares визначалися просто шляхом присвоєння контейнеру CPU-запитів у вигляді millicpu.

Наприклад, контейнер, що запитує 1 CPU (1024m) отримає (cpu.shares = 1024).

Через деякий час почалася заміна cgroup v1 на його наступника, cgroup v2. У cgroup v2 концепція частки процесора (яка коливається від 2 до 262144, або від 2¹ до 2¹⁸) була замінена CPU weight (яка коливається від [1, 10000], або від 10⁰ до 10⁴).

З переходом на cgroup v2, KEP-2254 впровадив формулу перетворення для зіставлення cgroup v1 CPU shares з cgroup v2 CPU weight. Формула перетворення була визначена як: cpu.weight = (1 + ((cpu.shares - 2) * 9999) / 262142)

Ця формула лінійно співвідносить значення від [2¹, 2¹⁸] до [10⁰, 10⁴].

Лінійна формула перетворення

Хоча цей підхід є простим, лінійне співвідношення створює кілька значних проблем і впливає як на продуктивність, так і на ступінь деталізації конфігурації.

Проблеми з попередньою формулою перетворення

Поточна формула перетворення створює дві основні проблеми:

1. Зниження пріоритету порівняно з робочими навантаженнями, що не належать до Kubernetes

У cgroup v1 стандартне значення для розподілу ресурсів процесора становить 1024, що означає, що контейнер, який запитує 1 процесор, має такий самий пріоритет, як і системні процеси, що знаходяться поза межами Kubernetes. Однак у cgroup v2 CPU weight у стандартних налаштуваннях становить 100, але поточна формула перетворює 1 CPU (1024m) лише на ≈39 weight — менше ніж 40 % від стандартного значення.

Приклад:

  • Контейнер, що запитує 1 CPU (1024m)
  • cgroup v1: cpu.shares = 1024 (дорівнює стандартному значенню)
  • cgroup v2 (поточний): cpu.weight = 39 (значно нижче за стандартне значення 100)

Це означає, що після переходу на cgroup v2 робочі навантаження Kubernetes (або OCI) фактично знизять пріоритет CPU порівняно з процесами, що не належать до Kubernetes. Проблема може бути серйозною для конфігурацій з великою кількістю системних демонів, які працюють поза межами Kubernetes і очікують, що робочі навантаження Kubernetes матимуть пріоритет, особливо в ситуаціях нестачі ресурсів.

2. Некерована деталізація

Поточна формула дає дуже низькі значення для невеликих запитів на використання CPU, обмежуючи можливість створювати підгрупи cgroup всередині контейнерів для детального розподілу ресурсів (що, ймовірно, стане набагато простішим у майбутньому, див. KEP #5474 для отримання додаткової інформації).

Приклад:

  • Контейнер, що запитує 100m CPU
  • cgroup v1: cpu.shares = 102
  • cgroup v2 (поточна): cpu.weight = 4 (занадто низьке значення для конфігурації підгруп cgroup)

З cgroup v1 запит на 100m CPU, що призвів до 102 CPU shares, був керованим у тому сенсі, що підгрупи cgroup могли бути створені всередині основного контейнера, призначаючи детальні пріоритети CPU для різних груп процесів. Однак з cgroup v2 дуже важко розподілити 4 shares між підгрупами cgroup, оскільки це недостатньо детально.

З планами дозволити записувані cgroups для контейнерів без привілеїв, це стає ще більш актуальним.

Нова формула перетворення

Опис

Нова формула є більш складною, але набагато краще відображає ‍ співвідношення між cgroup v1 CPU shares та cgroup v2 CPU weight:

cpu.weight=10(L2/612+125L/6127/34), де: L=log2(cpu.shares)cpu.weight = \lceil 10^{(L^{2}/612 + 125L/612 - 7/34)} \rceil, \text{ де: } L = \log_2(cpu.shares)

Ідея полягає в тому, що це квадратична функція, яка перетинає наступні значення:

  • (2, 1): мінімальні значення для обох діапазонів.
  • (1024, 100): стандартні значення для обох діапазонів.
  • (262144, 10000): максимальні значення для обох діапазонів.

Візуально нова функція виглядає наступним чином:

2025-10-25-new-cgroup-v1-to-v2-conversion-formula-new-conversion.png

А якщо збільшити важливу частину:

2025-10-25-new-cgroup-v1-to-v2-conversion-formula-new-conversion-zoom.png

Нова формула є «майже лінійною», проте вона ретельно розроблена для розумного зіставлення діапазонів, щоб три важливі точки, зазначені вище, перетиналися.

Як це розвʼязує проблеми

  1. Кращя узгодженість пріоритетів:

    • Контейнер, що запитує 1 CPU (1024m) тепер отримає cpu.weight = 102. Це значення близьке до стандартного значення 100 в cgroup v2. Це відновлює передбачуване співвідношення пріоритетів між робочими навантаженнями Kubernetes і системними процесами.
  2. Покращена деталізація:

    • Контейнер, що запитує 100m CPU, отримає cpu.weight = 17, (дивіться тут). Це дозволяє краще розподіляти ресурси в контейнерах.

Впровадження та інтеграція

Ця зміна була впроваджена на рівні OCI. Іншими словами, вона не впроваджена в самому Kubernetes, тому впровадження нової формули перетворення залежить виключно від впровадження OCI runtime.

Наприклад:

  • runc: нова формула увімкнена з версії 1.3.2.
  • crun: нова формула увімкнена з версії 1.23.

Вплив на наявні розгортання

Важливо: Деякі споживачі можуть зазнати впливу, якщо вони використовують стару лінійну формулу перетворення. Застосування або інструменти моніторингу, які безпосередньо обчислюють очікувані значення CPU weight на основі попередньої формули, можуть потребувати оновлення, щоб врахувати нове квадратичне перетворення. Це особливо актуально для:

  • Настроюваних інструментів управління ресурсами, які прогнозують значення CPU weight.
  • Систем моніторингу, які перевіряють або очікують конкретні значення ваги.
  • Застосунків, які програмно встановлюють або перевіряють значення CPU weight.

У рамках проєкту Kubernetes рекомендується протестувати нову формулу перетворення в тестових середовищах перед оновленням OCI runtimes, щоб забезпечити сумісність з наявними інструментами.

Де можна дізнатися більше?

Для тих, хто цікавиться цим вдосконаленням:

  • Kubernetes GitHub Issue #131216 — Докладний технічний аналіз і приклади, включаючи обговорення та обґрунтування вибору вищезазначеної формули.
  • KEP-2254: cgroup v2 — Оригінальна реалізація cgroup v2 в Kubernetes.
  • Документація Kubernetes cgroup — Поточні рекомендації щодо управління ресурсами.

Як долучитися?

Якщо ви зацікавлені у розробці функцій на рівні вузлів Kubernetes, приєднуйтесь до спеціальної групи за інтересами Kubernetes Node Special Interest Group. Ми завжди раді новим учасникам та різноманітним поглядам на проблеми управління ресурсами.