Практическое руководство по аудиту ресурсов кластера Kubernetes
В этой статье мы разберем практические методы анализа ресурсного профиля кластера Kubernetes. Я покажу вам, как использовать встроенные инструменты для получения реальной картины потребления CPU и памяти вашими подами, и сравнить эти данные с заданными ограничениями. Эти знания критически важны для оптимизации производительности и затрат на инфраструктуру.
Зачем нужен аудит ресурсов?
Представьте ситуацию: ваши поды "падают" с ошибками OutOfMemory (OOM), планировщик не может разместить новые поды из-за нехватки ресурсов, или, наоборот, кластер простаивает с низкой утилизацией. Все эти проблемы связаны с неправильной настройкой ресурсных лимитов и запросов (requests/limits).
Когда вы указываете Pod, можете опционально указать, сколько каждого ресурса нужно контейнеру. Когда вы указываете запрос ресурса для контейнеров в Pod, kube-scheduler использует эту информацию для решения, на какой узел поместить Pod. Когда вы указываете лимит ресурса для контейнера, kubelet обеспечивает эти лимиты, чтобы запущенный контейнер не мог использовать больше ресурса, чем установленный лимит.
Подготовка к аудиту
Перед началом работы убедитесь, что в вашем кластере установлен и функционирует Metrics Server. Metrics API предлагает базовый набор метрик для поддержки автоматического масштабирования и похожих случаев использования. Этот API делает доступной информацию об использовании ресурсов для узлов и подов, включая метрики CPU и памяти.
Проверить наличие Metrics Server можно командой:
kubectl get apiservice v1beta1.metrics.k8s.io
Если статус показывает True, можно приступать к работе. Если Metrics Server отсутствует, не переживайте — я покажу альтернативные способы получения метрик.
Метод 1: kubectl top pods — быстрый обзор нагрузки
Команда kubectl top — это ваш первый инструмент для получения мгновенного снимка потребления ресурсов. Она работает через Metrics API и обращается к данным, собираемым kubelet'ами на каждом узле.
Базовое использование
# Показать использование ресурсов всех подов во всех namespace'ах
kubectl top pods --all-namespaces
# Показать детализацию по контейнерам
kubectl top pods --all-namespaces --containers
# Показать использование ресурсов узлов
kubectl top nodes
Практические примеры
Давайте разберем несколько полезных сценариев:
# Найти топ-10 подов по потреблению памяти в конкретном namespace
kubectl top pods -n production | sort -k3 -hr | head -10
# Показать только поды, потребляющие больше 500m CPU (милликор)
kubectl top pods --all-namespaces | awk 'NR==1 || $3 > 500'
# Показать поды с высоким потреблением памяти (больше 1Gi)
kubectl top pods --all-namespaces | awk 'NR==1 || $4~/[0-9]+Gi/ && $4+0 > 1'
Что показывают эти метрики:
- CPU — текущее потребление в ядрах (1000m = 1 ядро)
- Memory — рабочий набор памяти (working set) в мебибайтах
Важно понимать: kubectl top показывает моментальный снимок, а не среднее значение за период. Для получения более репрезентативных данных запускайте команду несколько раз в разное время.
Метод 2: Прямое обращение к kubelet Summary API
Если Metrics Server недоступен или вы хотите получить более детальную информацию, можно обратиться напрямую к Summary API kubelet'а.
Получение данных
# На узле кластера
curl -k https://127.0.0.1:10250/stats/summary > /tmp/summary.json
# Или с удаленного хоста (при наличии доступа)
curl -k https://<node-ip>:10250/stats/summary > /tmp/summary.json
Парсинг JSON-ответа
Summary API возвращает подробную статистику в JSON формате. Вот простой Python-скрипт для извлечения ключевых метрик:
import json
def parse_kubelet_stats(filename):
with open(filename, 'r') as f:
data = json.load(f)
print(f'{"POD NAME":40} {"CPU (cores)":>12} {"Memory (MiB)":>15}')
print("-" * 70)
for pod in data.get("pods", []):
pod_name = pod["podRef"]["name"]
# Суммируем метрики по всем контейнерам пода
total_cpu = 0
total_memory = 0
for container in pod.get("containers", []):
cpu_usage = container.get("cpu", {}).get("usageNanoCores", 0)
memory_usage = container.get("memory", {}).get("workingSetBytes", 0)
total_cpu += cpu_usage / 1e9 # nanocores to cores
total_memory += memory_usage / (1024 * 1024) # bytes to MiB
print(f'{pod_name:40} {total_cpu:12.3f} {total_memory:15.0f}')
# Использование
parse_kubelet_stats("/tmp/summary.json")
Преимущества метода
- Работает даже без Metrics Server
- Предоставляет более детальную статистику
- Включает метрики файловой системы и сети
- Не требует дополнительных компонентов в кластере
Ограничения
- Показывает данные только с одного узла
- Требует сетевого доступа к kubelet API
- Нужны соответствующие права доступа (RBAC)
Метод 3: Анализ requests и limits через kubectl describe
Теперь перейдем к анализу того, что было заявлено в спецификациях подов. Это критически важно для понимания разрыва между фактическим и планируемым потреблением ресурсов.
Получение информации о конкретном поде
# Детальная информация о поде
kubectl describe pod <pod-name> -n <namespace>
# Извлечение только секции Resources
kubectl describe pod <pod-name> -n <namespace> | grep -A 10 "Limits:\|Requests:"
Массовое извлечение данных с помощью JSONPath
Для анализа всех подов в namespace используйте JSONPath запросы:
# Создание CSV файла с данными о ресурсах
kubectl get pods -n <namespace> -o jsonpath='
NAME,CONTAINER,CPU_REQ,MEM_REQ,CPU_LIM,MEM_LIM
{range .items[*]}
{range .spec.containers[*]}
{$.metadata.name},{.name},{.resources.requests.cpu},{.resources.requests.memory},{.resources.limits.cpu},{.resources.limits.memory}
{"\n"}
{end}
{end}' > resources.csv
Более читаемый вариант вывода
# Скрипт для форматированного вывода
kubectl get pods -n default -o json | jq -r '
.items[] |
{
pod: .metadata.name,
containers: [
.spec.containers[] | {
name: .name,
requests: .resources.requests // {},
limits: .resources.limits // {}
}
]
} |
"\(.pod):\n" +
(.containers[] | " \(.name): req(\(.requests.cpu // "none")/\(.requests.memory // "none")) lim(\(.limits.cpu // "none")/\(.limits.memory // "none"))\n")
'
Проверка LimitRange
Не забывайте про объекты LimitRange, которые могут автоматически назначать дефолтные значения:
# Проверка LimitRange в namespace
kubectl describe limitrange -n <namespace>
# Просмотр всех LimitRange в кластере
kubectl get limitrange --all-namespaces
Метод 4: Использование docker stats для детальной диагностики
Если на узлах кластера используется Docker runtime, команда docker stats предоставляет детальную статистику контейнеров в реальном времени.
Основные команды
# Показать статистику всех запущенных контейнеров
docker stats
# Получить единичный снимок (без постоянного обновления)
docker stats --no-stream
# Показать статистику конкретных контейнеров
docker stats --no-stream $(docker ps --format "table {{.Names}}" | grep k8s)
Интерпретация вывода
Docker stats показывает следующие метрики:
- CPU % — процент использования CPU
- MEM USAGE/LIMIT — текущее использование памяти и лимит
- MEM % — процент от доступной памяти системы
- NET I/O — сетевой трафик
- BLOCK I/O — дисковые операции
Для containerd runtime
Если используется containerd, аналогичную информацию можно получить командой:
# Список всех задач
ctr -n k8s.io tasks list
# Метрики конкретной задачи
ctr -n k8s.io tasks metrics <task-id>
Практический пример: комплексный аудит
Давайте проведем пошаговый аудит реального namespace:
Шаг 1: Сбор фактических метрик
# Получаем текущее потребление
kubectl top pods -n production --containers > current_usage.txt
# Собираем данные в течение часа для получения средних значений
for i in {1..12}; do
echo "$(date): " >> usage_log.txt
kubectl top pods -n production >> usage_log.txt
sleep 300 # 5 минут
done
Шаг 2: Извлечение requests/limits
# Создаем подробный отчет
kubectl get pods -n production -o json | jq -r '
.items[] |
{
name: .metadata.name,
containers: [.spec.containers[] | {
name: .name,
cpu_req: .resources.requests.cpu // "none",
mem_req: .resources.requests.memory // "none",
cpu_lim: .resources.limits.cpu // "none",
mem_lim: .resources.limits.memory // "none"
}]
} |
[.name, (.containers[0].cpu_req), (.containers[0].mem_req), (.containers[0].cpu_lim), (.containers[0].mem_lim)] |
@csv
' > pod_resources.csv
Шаг 3: Анализ расхождений
Создайте простую таблицу сравнения в Excel или используйте awk для базового анализа:
# Найти поды без установленных requests
kubectl get pods -n production -o json | jq -r '
.items[] |
select(.spec.containers[].resources.requests == null or .spec.containers[].resources.requests == {}) |
.metadata.name
'
# Найти поды с потреблением выше requests
# (требует комбинирования данных из kubectl top и describe)
Интерпретация результатов и рекомендации
Типичные проблемы и их решения
-
Завышенные requests
- Симптомы: низкая утилизация узлов, проблемы с планированием
- Решение: уменьшить requests на основе фактического потребления
-
Заниженные limits
- Симптомы: частые OOM kills, нестабильная работа приложений
- Решение: увеличить limits с учетом пиковых нагрузок
-
Отсутствие requests/limits
- Симптомы: непредсказуемое поведение кластера
- Решение: установить базовые значения, использовать LimitRange
Рекомендуемые практики
- Установите requests на уровне 75-80% от среднего потребления
- Установите limits на уровне 150-200% от requests для CPU
- Для памяти: limits должны быть близки к максимальному наблюдаемому потреблению
- Используйте Vertical Pod Autoscaler для автоматической оптимизации
Автоматизация процесса
Для регулярного мониторинга создайте простой скрипт:
#!/bin/bash
# audit_resources.sh
NAMESPACE=${1:-default}
OUTPUT_DIR="./audit_results_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$OUTPUT_DIR"
echo "Collecting metrics for namespace: $NAMESPACE"
# Сбор текущих метрик
kubectl top pods -n "$NAMESPACE" --containers > "$OUTPUT_DIR/current_usage.txt"
# Сбор информации о requests/limits
kubectl get pods -n "$NAMESPACE" -o json | jq -r '
.items[] | [
.metadata.name,
(.spec.containers[0].resources.requests.cpu // "none"),
(.spec.containers[0].resources.requests.memory // "none"),
(.spec.containers[0].resources.limits.cpu // "none"),
(.spec.containers[0].resources.limits.memory // "none")
] | @csv
' > "$OUTPUT_DIR/pod_resources.csv"
# Проверка LimitRange
kubectl describe limitrange -n "$NAMESPACE" > "$OUTPUT_DIR/limitranges.txt" 2>/dev/null
echo "Audit completed. Results saved in: $OUTPUT_DIR"
Заключение
Регулярный аудит ресурсов кластера Kubernetes — это не разовая задача, а постоянный процесс оптимизации. Используя описанные методы, вы сможете:
- Выявить неэффективное использование ресурсов
- Предотвратить проблемы с производительностью
- Оптимизировать затраты на инфраструктуру
- Обеспечить стабильную работу приложений
Помните: мониторинг ресурсов должен сочетаться с пониманием специфики ваших приложений. Не всегда математически оптимальные значения являются лучшими с точки зрения надежности системы.
Начните с базового аудита раз в неделю, постепенно автоматизируя процесс и внедряя более сложные инструменты мониторинга по мере роста вашего кластера.