Команда Kubernetes перевела поддержку etcd RangeStream в статус beta в версии Kubernetes v1.37. Новая возможность позволяет API-серверу получать большие наборы данных из etcd потоково, уменьшая пиковое потребление памяти и делая нагрузку на кластер более предсказуемой.
Проблема больших запросов к etcd
API-сервер Kubernetes активно использует кэш наблюдения (watch cache). При запуске или восстановлении этого кэша ему нужно получить полное состояние ресурсов из etcd. В больших кластерах такие операции могут быть ресурсоёмкими: например, когда в кластере много Pod’ов или других объектов.
Ранее Kubernetes уже использовал постраничную загрузку данных из etcd: вместо чтения всей коллекции сразу API-сервер запрашивал фиксированное количество ключей за раз. Однако такой подход не учитывал размер самих объектов. Страница с несколькими крупными объектами могла занимать значительно больше памяти, чем ожидалось.
Кроме того, стандартный вызов Range в etcd сначала полностью собирал ответ в памяти и только затем отправлял его клиенту. В результате одна и та же большая порция данных могла одновременно находиться в памяти etcd и API-сервера во время обработки.
Как работает RangeStream
В etcd версии 3.7 появился новый потоковый RPC-вызов RangeStream. Он использует тот же запрос RangeRequest, но вместо формирования полного ответа сразу разбивает данные на части и отправляет их постепенно.
Размер частей подбирается автоматически в зависимости от объёма возвращаемых данных. Благодаря этому нагрузка ограничивается не количеством ключей, а фактическим размером данных. Обработанные части освобождаются из памяти сразу после передачи, поэтому системе больше не нужно удерживать всю коллекцию целиком.
После включения функции API-сервер использует RangeStream во всех случаях, когда ему нужно получить полную коллекцию объектов из etcd. В первую очередь это касается инициализации кэша наблюдения, а также ситуаций, когда запрос списка (List) нельзя выполнить из кэша и приходится обращаться напрямую к etcd.
Теперь API-сервер декодирует данные по мере поступления очередной части и освобождает память перед загрузкой следующей. В результате ни etcd, ни API-сервер не держат в памяти весь набор объектов одновременно.
Требования и совместимость
Для использования RangeStream нужны:
-
Kubernetes версии 1.37 или новее;
-
etcd версии 3.7 или новее;
-
включённая возможность
EtcdRangeStreamвkube-apiserver.
В Kubernetes v1.37 эта возможность находится в статусе beta и включена по умолчанию. При необходимости её можно отключить параметром:
--feature-gates=EtcdRangeStream=false
API-сервер при запуске проверяет поддержку RangeStream в используемом экземпляре etcd. Если backend не поддерживает новый RPC-вызов, Kubernetes автоматически возвращается к прежнему механизму постраничного чтения через Range.
Как проверить использование RangeStream
Потоковые чтения отображаются в метриках etcd с отдельной меткой операции:
etcd_request_duration_seconds_count{operation="listStream"}
Если счётчик увеличивается, API-сервер использует новый механизм. Нулевое значение обычно означает, что используется старый вариант чтения через Range — например, из-за версии etcd ниже 3.7.
RangeStream стал частью улучшений Kubernetes v1.37, направленных на работу больших кластеров. Основной эффект от изменения — снижение пикового потребления памяти при операциях со значительными объёмами данных в control plane.
Все практические разборы наиболее актуальных тем смотрите в дайджесте бесплатных уроков сентября.
Источник: habr.com