Лучшие практики оптимизации производительности кластера Kubernetes
Оптимизируйте производительность Kubernetes с помощью правильно подобранных ресурсов, автоматического масштабирования, эффективной сети, выбора хранилища и постоянной наблюдаемости.
Лучшие практики оптимизации производительности кластера Kubernetes
Проблемы с производительностью кластера Kubernetes обычно проявляются в виде медленных развертываний, ожидающих Pod'ов, шумных соседей или неожиданных счетов за облачные ресурсы. Исправление редко заключается в одной магической настройке; вам нужны точные размеры ресурсов, правила масштабирования, соответствующие спросу, и достаточная наблюдаемость, чтобы видеть, где начинается давление.
Используйте этот чек-лист для настройки кластера без догадок.
Начните с запросов и лимитов
Планировщик использует запросы CPU и памяти, чтобы решить, куда поместить Pod'ы. Если запросы слишком низкие, узлы выглядят более пустыми, чем есть на самом деле, и рабочие нагрузки борются за ресурсы. Если запросы слишком высокие, планировщик тратит емкость впустую, и Pod'ы могут оставаться в ожидании.
Устанавливайте запросы на основе реальных данных использования. Например, если контейнер API потребляет около 300 милликор во время нормального трафика и достигает пика около 700 милликор во время прогрева развертывания, вы можете начать с:
resources:
requests:
cpu: "300m"
memory: "512Mi"
limits:
memory: "1Gi"
Будьте осторожны с лимитами CPU. Строгий лимит CPU может ограничивать сервисы, чувствительные к задержкам, даже если на узле есть свободный CPU. Лимиты памяти все еще полезны, потому что контейнер, превышающий свой лимит памяти, может быть убит до того, как он приведет к давлению памяти на весь узел.
Используйте автоматическое масштабирование с четкими сигналами
Горизонтальный автомасштабировщик Pod'ов работает хорошо, когда ваша метрика отслеживает пользовательский спрос. CPU может быть достаточным для простых сервисов без состояния, но глубина очереди, частота запросов или пользовательские метрики приложений часто являются лучшими сигналами для масштабирования.
kubectl autoscale deployment api \
--cpu-percent=70 \
--min=3 \
--max=20
Автомасштабировщик кластера, Karpenter или слой автомасштабирования узлов вашего облачного провайдера должны иметь возможность добавлять узлы до того, как Pod'ы будут долго ожидать. Проверьте, охватывают ли группы узлов размеры экземпляров, зоны, требования к GPU или метки, необходимые вашим рабочим нагрузкам.
Поддерживайте предсказуемое планирование
Производительность падает, когда критически важные Pod'ы попадают на перегруженные или неподходящие узлы. Используйте ограничения распределения топологии для сервисов с высоким трафиком, привязку узлов для рабочих нагрузок, специфичных для оборудования, и метки для узлов, которые должны запускать только узкий класс Pod'ов.
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: api
Это предотвращает скопление реплик на одном узле, когда в кластере есть лучшие варианты размещения.
Настройте сеть там, где это действительно болит
Большинству кластеров не требуется экзотическая настройка сети. Начните с поиска медленного пути: время поиска DNS, накладные расходы сервисной сетки, трафик между зонами, перегруженный входной контроллер или задержка между Pod'ом и базой данных.
Полезные проверки включают:
kubectl top pods -A
kubectl get endpointslices -A
kubectl describe ingress <имя>
kubectl logs -n kube-system -l k8s-app=kube-dns
Для болтливых сервисов держите Pod'ы и их основные зависимости в одном регионе и, по возможности, в одной зоне. Если вы используете сервисную сетку, измерьте задержку p95 и p99 с внедрением sidecar и без него для одной рабочей нагрузки, прежде чем широко внедрять изменения сетки.
Сопоставьте хранилище с рабочей нагрузкой
Выбор хранилища может доминировать в производительности для баз данных, очередей и CI-нагрузок. Выбирайте тома на основе задержки, IOPS, пропускной способности и поведения при сбоях, а не только емкости.
Например, Pod PostgreSQL нуждается в классе постоянного тома с предсказуемой задержкой и четким поведением резервного копирования. Кэш сборки может больше заботиться о пропускной способности и может терпеть перестройки. Веб-сервис без состояния должен полностью избегать постоянных томов, если у него нет реальной причины.
Следите за этими симптомами:
- Pod'ы застревают в состоянии
ContainerCreating, потому что тома подключаются медленно. - Задержка приложения растет, а CPU остается нормальным.
- Давление на диск узла вытесняет Pod'ы.
- StatefulSets блокируются, потому что том привязан к одной зоне.
Наблюдайте за кластером перед изменениями
Оптимизация без базовых метрик — это просто суета. Как минимум, отслеживайте CPU, память, перезапуски, ожидающие Pod'ы, условия давления на узлы, задержку API-сервера и задержку p95 рабочих нагрузок.
kubectl get nodes
kubectl describe node <имя-узла>
kubectl get pods -A --field-selector=status.phase=Pending
kubectl top nodes
Если вы используете Prometheus, добавьте оповещения для устойчивого давления на узлы, высокой частоты перезапусков, HPA на максимальном количестве реплик и недоступных реплик на критических развертываниях.
Вывод
Оптимизируйте Kubernetes, начиная с рабочей нагрузки. Правильно устанавливайте запросы, избегайте ненужного ограничения CPU, масштабируйтесь на основе сигналов спроса, распределяйте реплики и выбирайте хранилище, соответствующее рабочей нагрузке. Затем измеряйте после каждого изменения, чтобы знать, стал ли кластер быстрее, дешевле или просто другим.