Kubernetes 1.37 зменшує ризик OOM під час великих читань з etcd
Beta-функція RangeStream передає великі колекції об’єктів частинами, щоб API server та etcd не тримали в пам’яті цілу сторінку відповіді одночасно.

Kubernetes 1.37 переводить потокове читання великих колекцій з etcd у beta та вмикає його за замовчуванням. Новий RPC RangeStream з etcd 3.7 розбиває відповідь на керовані за розміром частини. API server декодує черговий фрагмент, звільняє його і лише потім отримує наступний. Завдяки цьому обидві сторони не повинні одночасно утримувати в пам’яті цілу велику сторінку даних.

Звідки виникала пікова витрата пам’яті
Більшість List і Watch-запитів Kubernetes обслуговує з watch cache у пам’яті API server. Але цей кеш потрібно заповнити під час запуску або повторної ініціалізації. Для цього control plane читає з etcd повний стан ресурсу. Якщо в кластері дуже багато Pods, custom resources чи просто великих об’єктів, така операція стає помітною для пам’яті й затримок.
Старий шлях уже використовував пагінацію: API server просив у etcd фіксовану кількість ключів, а не всю колекцію одним запитом. Проблема в тому, що кількість ключів нічого не говорить про розмір значень. Сторінка з тисячею малих об’єктів і сторінка з тисячею великих CR можуть відрізнятися за обсягом у багато разів.
Unary-виклик Range спочатку збирав сторінку повністю на стороні etcd. Потім той самий payload перебував у пам’яті API server під час декодування. За невдалої комбінації великих значень і кількох паралельних читань пік міг стати непередбачуваним та завершитися OOM.
Як працює RangeStream
RangeStream приймає той самий RangeRequest і повертає той самий набір результатів, але передає їх чанками. Розмір частини адаптується до значень у відповіді: межа фактично контролюється байтами, а не лише числом ключів. Пам’ять звільняється поступово під час руху потоку.
API server застосовує новий шлях скрізь, де потрібно прочитати з etcd цілу колекцію: під час ініціалізації watch cache та у fallback-сценаріях, коли List-запит неможливо обслужити з кешу. Функція не змінює семантику API і не віддає клієнту неповний результат — змінюється внутрішній спосіб транспортування між control plane та сховищем.
Вимоги та безпечний fallback
- Kubernetes має бути версії 1.37 або новішої.
- etcd має бути версії 3.7 або новішої.
- Feature gate
EtcdRangeStreamу kube-apiserver повинен бути активним; у 1.37 він beta та увімкнений за замовчуванням.
Під час запуску API server визначає, чи підтримує etcd новий RPC. Якщо сховище старіше або виклик повертає Unimplemented, control plane автоматично повертається до пагінованого Range. Це спрощує поетапне оновлення, але означає, що сам факт запуску Kubernetes 1.37 ще не доводить використання потокового шляху.
Як перевірити, що функція справді працює
Kubernetes записує потокові читання в etcd-метрики з окремою міткою операції. Ненульове значення etcd_request_duration_seconds_count{operation="listStream"} підтверджує, що RangeStream використовувався. Якщо лічильник постійно дорівнює нулю, першою перевіркою має бути версія etcd і стан feature gate.
Для production-кластера варто порівняти не лише загальне середнє використання RAM. Корисніші метрики — піковий RSS etcd і kube-apiserver під час перезаповнення watch cache, частота OOM, тривалість List-запитів, кількість fallback та поведінка під кількома одночасними великими читаннями.
Практичний висновок: RangeStream найбільш корисний кластерам із великою кількістю об’єктів або важкими CRD. Після оновлення etcd і Kubernetes перевірте метрику listStream та виміряйте піки пам’яті на реальному навантаженні.
Обмеження
Функція знижує транспортний пік під час повного читання колекції, але не виправляє надмірний розмір самих об’єктів, неконтрольоване зростання CRD чи завеликі кеші. Вона також не є причиною відмовлятися від memory limits, резерву для control plane, backup etcd і перевірки масштабування.
Статус beta означає, що можливість уже достатньо зріла для широкого тестування, але команди все одно мають перевірити сумісність зі своєю збіркою, managed-сервісом і процедурою upgrade. Вимкнення можливе через --feature-gates=EtcdRangeStream=false, однак робити це без діагностики причини не варто.
Джерело та ліцензія
Матеріал підготовлено за дописом Jeffrey Ying Kubernetes v1.37: etcd RangeStream Cuts Memory Use on Large List Reads. Вміст Kubernetes Website поширюється за Creative Commons Attribution 4.0. Український текст перекладено й адаптовано редакцією з атрибуцією.
Матеріал перекладено, переказано та доповнено редакцією українською мовою.
Читайте далі — ми вже розбираємо наступну важливу тему.


