Управление ресурсами Kubernetes и автомасштабирование

KubernetesBeginner
Практиковаться сейчас

Введение

Планировщику нужны запросы ресурсов, чтобы размещать Pod, kubelet применяет ограничения, а HorizontalPodAutoscaler нужны метрики и корректная базовая величина использования. Вместе эти механизмы образуют единый рабочий процесс управления ёмкостью.

Вы настроите запросы и ограничения, изучите текущее использование ресурсов, создадите HPA, создадите нагрузку и проследите за изменением количества реплик.

Эти настройки связаны в цепочку зависимостей. Запрос CPU задаёт базовый уровень, metrics-server сообщает о недавнем использовании ресурсов, а HPA сопоставляет эти значения и решает, нужно ли изменить количество реплик. Если не задать запрос, процентное использование CPU не будет иметь осмысленного знаменателя.

Настройка запросов и ограничений

На этом шаге разверните пример Kubernetes с HPA и явно заданными ресурсами.

Запрос — это объём ресурса, используемый при планировании и в качестве знаменателя для автомасштабирования. Ограничение — максимально допустимое потребление контейнера. CPU измеряется в ядрах или миллиядрах (100m — это 0,1 ядра), а память — в единицах объёма, например Mi.

cd /home/labex/project/resource-autoscaling
kubectl create namespace practice-capacity
kubectl create deployment cpu-demo -n practice-capacity --image=registry.k8s.io/hpa-example:latest --replicas=1

Добавьте контракт ресурсов в созданный Deployment. Команда kubectl set resources обновляет шаблон Pod и поэтому запускает новый rollout:

kubectl set resources deployment/cpu-demo -n practice-capacity --requests=cpu=100m,memory=32Mi --limits=cpu=200m,memory=64Mi
kubectl expose deployment cpu-demo -n practice-capacity --port=80 --target-port=80
kubectl rollout status deployment/cpu-demo -n practice-capacity --timeout=60s
kubectl get deployment cpu-demo -n practice-capacity -o jsonpath='{.spec.template.spec.containers[0].resources}{"\n"}'

100m означает одну десятую ядра CPU. Запросы влияют на планирование и расчёт использования, а ограничения устанавливают предел потребления контейнера.

Вывод JSONPath должен содержать и requests, и limits. Одного ограничения недостаточно: оно не задаёт знаменатель, необходимый HPA для расчёта использования.

deployment "cpu-demo" successfully rolled out
{"limits":{"cpu":"200m","memory":"64Mi"},"requests":{"cpu":"100m","memory":"32Mi"}}

JSON может вывести ключи в другом порядке. Проверяйте наличие всех четырёх значений, а не их положение в строке.

Изучение метрик ресурсов

На этом шаге проверьте подготовленный конвейер сбора метрик и изучите текущее использование ресурсов.

kubectl top показывает недавний снимок использования ресурсов — по смыслу он похож на команду top в операционной системе. Эта команда не отображает настроенные запросы или ограничения: они по-прежнему являются частью спецификации рабочей нагрузки.

cd /home/labex/project/resource-autoscaling
kubectl get deployment metrics-server -n kube-system
for attempt in $(seq 1 18); do
  if kubectl top nodes >/dev/null 2>&1 && kubectl top pods -n practice-capacity --containers >/dev/null 2>&1; then
    break
  fi
  echo "Waiting for the first metrics sample (${attempt}/18)..."
  sleep 5
done
kubectl top nodes
kubectl top pods -n practice-capacity --containers

kubectl top считывает недавние метрики, а не запросы ресурсов. Метрики могут появиться не сразу; если для нового Pod пока нет данных, повторите команду через несколько секунд.

Цикл выполняет повторные попытки автоматически. Он не более 18 раз бесшумно проверяет готовность метрик, ждёт между попытками пять секунд, а затем после появления данных один раз запускает две видимые команды top. В проверках >/dev/null отбрасывает обычный вывод, а 2>&1 направляет сообщения об ошибках туда же. Благодаря этому ожидаемые сообщения о том, что метрики ещё не готовы, не отображаются в терминале. Такая задержка нормальна для конвейера получения недавних значений и не означает, что Pod завершился с ошибкой.

Значения для узла и Pod будут различаться, поэтому обращайте внимание на наличие столбцов CPU и памяти, а не на точные числа. Параметр --containers позволяет разделить показатели, если Pod содержит несколько контейнеров.

Например, в тестовой среде были получены таблица узлов и таблица по контейнерам, похожие на следующие:

NAME         CPU(cores)   CPU(%)   MEMORY(bytes)   MEMORY(%)
labex-v135   182m         9%       1602Mi          44%

POD                         NAME          CPU(cores)   MEMORY(bytes)
cpu-demo-...                hpa-example   1m           9Mi

Ваши значения могут отличаться — это измеренные показатели, а не параметры конфигурации.

Создание HorizontalPodAutoscaler

На этом шаге задайте целевое среднее использование CPU на уровне 30 процентов и разрешите от одной до четырёх реплик.

При запросе 100m цель в 30% соответствует примерно 30m среднего использования CPU на один Pod. HPA изменяет желаемое количество реплик Deployment, но не уменьшает его ниже min=1 и не увеличивает выше max=4.

cd /home/labex/project/resource-autoscaling
kubectl autoscale deployment cpu-demo -n practice-capacity --cpu=30% --min=1 --max=4
kubectl get hpa cpu-demo -n practice-capacity
kubectl describe hpa cpu-demo -n practice-capacity

Использование рассчитывается относительно запроса CPU в размере 100m. Без этого запроса процентная цель для CPU не имела бы знаменателя.

В текущем синтаксисе kubectl autoscale процент указывается явно через --cpu=30%. Этот вариант заменяет устаревший флаг --cpu-percent, который Kubernetes 1.35 помечает как устаревший.

В первые несколько секунд в столбце TARGETS может отображаться <unknown>, пока собирается новый образец метрики. Команда describe hpa показывает условия и события, по которым можно понять, располагает ли контроллер доступными метриками.

Поэтому начальная таблица может выглядеть следующим образом и при этом не свидетельствовать об ошибке:

NAME       REFERENCE             TARGETS              MINPODS   MAXPODS   REPLICAS
cpu-demo   Deployment/cpu-demo   cpu: <unknown>/30%   1         4         0

После следующей синхронизации контроллера значение <unknown> сменится на измеренный процент, а REPLICAS начнёт отражать состояние Deployment.

Создание нагрузки и наблюдение за масштабированием

На этом шаге запустите временный клиент, который в течение не более 60 секунд будет повторно отправлять запросы к Service.

Команда BusyBox timeout запускает вложенный цикл запросов на 60 секунд. Цикл while многократно обращается к ресурсоёмкой конечной точке демонстрационного приложения, а >/dev/null отбрасывает тела ответов, чтобы терминал оставался читаемым. По достижении лимита времени команда обычно возвращает ненулевой код завершения, поэтому || true воспринимает это запланированное завершение как нормальное.

cd /home/labex/project/resource-autoscaling
kubectl run load-generator -n practice-capacity --image=busybox:1.36 --image-pull-policy=IfNotPresent --restart=Never --rm -i -- sh -c 'timeout 60 sh -c "while true; do wget -qO- http://cpu-demo >/dev/null; done" || true'
kubectl get hpa cpu-demo -n practice-capacity
kubectl get deployment cpu-demo -n practice-capacity

HPA реагирует асинхронно, поэтому изменение количества реплик может продолжиться уже после завершения работы клиента. Ориентируйтесь на условия и события HPA, а не ожидайте мгновенного масштабирования.

Если в первой таблице масштабирование ещё не отобразилось, ненадолго запустите kubectl get hpa cpu-demo -n practice-capacity -w и нажмите Ctrl+C, когда увидите изменение. Параметр -w отслеживает обновления, но не изменяет HPA. Точное время намеренно не используется при проверке, поскольку циклы обработки метрик выполняются асинхронно.

В тестовом запуске HPA обнаружил использование выше целевого значения и увеличил Deployment до двух готовых реплик:

NAME       REFERENCE             TARGETS        MINPODS   MAXPODS   REPLICAS
cpu-demo   Deployment/cpu-demo   cpu: 55%/30%   1         4         2

NAME       READY   UP-TO-DATE   AVAILABLE
cpu-demo   2/2     2            2

Точные значения использования и количество реплик могут отличаться. Важно следующее: текущее значение 55% превысило цель 30%, поэтому требуемая ёмкость увеличилась, но осталась в пределах от 1 до 4 реплик.

Итоги

Вы связали запросы, ограничения, текущие метрики, целевые значения использования и решения HPA в единый процесс. Управление ёмкостью — это цикл обратной связи: задайте базовый уровень, наблюдайте за использованием, определите границы и изучайте условия работы контроллера.