Requests, limits и причины Pending
Готовность API теперь описана probes, однако мы ещё не сообщили Kubernetes, сколько ресурсов ожидаем для процесса. Добавим requests и limits к API и web. Это не автоматическое ускорение приложения: значения влияют на размещение и ограничения работы. Результат урока — научиться объяснять, почему Pod ожидает узел, получает меньше CPU или завершается при нехватке памяти.
Полный файл examples/kubernetes-web-lab/manifests/07-resources.yaml заменяет оба Deployment и сохраняет уже введённые конфигурацию, порты и probes. Не применяйте после него ранние файлы Deployment без понимания различий: старые декларации могут убрать новые настройки. Автор не измерял потребление приложений и не запускал нагрузку; числа ниже демонстрационные.
Ресурс, который просим при размещении
Request — заявленная потребность контейнера, учитываемая при выборе узла. Для API задаём 50m CPU и 64Mi памяти:
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 300m
memory: 128Mi
Тысяча millicpu соответствует одному CPU в принятой модели ресурсов. Поэтому 50m означает пять процентов единицы CPU, а не пятьдесят мегагерц. Значение не говорит, сколько запросов в секунду обработает приложение. Производительность зависит от работы обработчика, задержек, runtime и доступного окружения.
Request памяти участвует в решении о размещении. Scheduler сравнивает заявленные потребности Pod с доступными ресурсами узла. Он не размещает приложение исключительно по тому, насколько маленьким кажется его текущее фактическое потребление. Если требования не помещаются, Pod может остаться Pending, хотя на первый взгляд компьютер ещё не занят полностью.
В одном локальном узле важны также системные компоненты Kubernetes. Ресурсы ноутбука, лимиты Docker и allocatable узла — не одно число. Поэтому нельзя сложить только requests собственных API и объявить всю оставшуюся память свободной. Для обучения полезно читать описание узла и причину FailedScheduling, а не увеличивать случайный параметр наугад.
Для web предусмотрены другие значения: request 25m и 32Mi, limits 200m и 96Mi. Они показывают, что разные компоненты имеют разные потребности. Frontend-прокси и API не обязаны получать одинаковые настройки только потому, что оба используют Node. Но без измерения это учебные исходные значения, а не результат оптимизации.
Ограничение CPU и ограничение памяти
CPU limit может ограничивать время выполнения процесса. При достижении лимита запросы становятся медленнее, хотя процесс не обязательно завершается. Снаружи это может проявляться ростом задержки и таймаутами прокси. Если web ждёт API только пять секунд, слишком сильное ограничение CPU способно превратить медленную обработку в ответ 502.
Memory limit задаёт другую границу. При превышении разрешённого потребления контейнер может быть завершён системой. В Kubernetes это часто видно через причину OOMKilled и перезапуск. Такой исход нельзя описывать как «процесс просто немного замедлился». Он теряет память и активную работу, после чего новый процесс начинает состояние заново.
Модель requests и limits объясняется в документации управления ресурсами. Для веб-разработчика особенно важно не смешивать два симптома. Медленные ответы при CPU throttling и перезапуски из-за памяти требуют разных наблюдений и различных изменений.
Значение памяти Node включает не только ваш массив или кэш. Runtime использует память для heap, буферов, нативных частей и других структур. Настройка размера heap не является полным описанием потребления контейнера. Если продукт обрабатывает большие файлы, нужно учитывать буферы и потоковую передачу; увеличение одного лимита может скрыть проблему, но не изменить алгоритм.
Почему обновлению нужен запас
В API Deployment стратегия maxUnavailable: 0, maxSurge: 1. Она позволяет добавить одну новую копию прежде, чем убрать старую готовую. Поэтому при обновлении двух реплик может временно существовать третья. Для этой копии тоже нужны request CPU и памяти. Кластер, который вмещает обычное состояние, может не вместить промежуточное состояние rollout.
Представим, что два API и web уже заняли почти все allocatable ресурсы узла. Новая копия API остаётся Pending, старые продолжают работать, rollout не продвигается. Это разумное поведение выбранной стратегии: она предпочитает сохранить доступные копии. Ошибкой было бы удалить старые вручную, не установив причину отсутствия места.
Есть два предметных решения. Можно обеспечить запас ресурсов для дополнительной копии. Можно пересмотреть стратегию обновления, разрешив временную недоступность одной реплики, если продукт допускает такой риск. Выбор зависит от требований к доступности, а не от желания сделать колонку статуса зелёной любым способом.
Ресурсы также влияют на будущее масштабирование. Запись replicas: 4 не создаёт вычислительную мощность из ничего. Четыре экземпляра должны разместиться на узлах и получить достаточную долю работы. Если каждый объявляет слишком большие requests, часть копий будет ожидать. Если слишком маленькие, несколько приложений могут конкурировать за фактический ресурс сильнее ожидаемого.
Диагностика размещения и процесса
Будущие команды применяют новую декларацию и читают состояние:
kubectl --context kind-ploshchadka apply -f manifests/07-resources.yaml
kubectl --context kind-ploshchadka -n ploshchadka rollout status deployment/api
kubectl --context kind-ploshchadka -n ploshchadka get pods
kubectl --context kind-ploshchadka -n ploshchadka describe deployment api
Если какая-то копия не запускается, изучите её describe pod: в Events может быть информация о недостатке CPU или памяти. У запущенного, но перезапускающегося контейнера смотрите предыдущую причину завершения и предыдущий журнал. Само слово Pending не требует менять исходники Node, а само число рестартов не объясняет, был ли превышен memory limit.
Команда kubectl top использует Metrics API. В стандартном kind такая возможность не гарантирована: Metrics Server не установлен автоматически. Поэтому отсутствие вывода top не равно нулевому потреблению и не доказывает исправность приложения. В этом курсе не устанавливаем дополнительные компоненты ради выдуманных измерений.
Для будущей самостоятельной работы читатель может временно задать request, который превышает allocatable узла, и прочитать ожидаемую причину размещения. После наблюдения нужно вернуть исходное значение. Это демонстрация scheduler, не стресс-тест ноутбука. Здесь не приводится результат такого опыта, потому что автор его не выполнял.
В реальном продукте настройки уточняют по обычной нагрузке, пикам, распределению задержек и запасу на обновление. Среднее значение за короткий период недостаточно для memory limit, если редкий крупный запрос создаёт большой буфер. С другой стороны, огромные requests для каждой копии делают ресурсы недоступными другим приложениям без предметной причины.
После урока у «Площадки» есть явные потребности экземпляров и запасная копия при rollout. Следующий материал рассматривает namespace и ограниченные права наблюдателя, чтобы доступ к диагностике не требовал выдачи полномочий изменять всё окружение.