Skip to main content

Практическое руководство по аудиту ресурсов кластера 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 отсутствует, не переживайте — я покажу альтернативные способы получения метрик. Вы можете использовать Prometheus для долгосрочного анализа, если он пресутсвуют внутри вашей инфраструктуры .

Метод 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'а.

Получение данных

Так как приведённая ниже команда может выполнить сбор summary статистики только с одного узла, то провести процедуру необходимо будет на всех узлах кластера с вашими pods.  

# На узле кластера
curl -ks https:http://127.0.0.1:10250/8001/api/v1/nodes/$(hostname)/proxy/stats/summary > /tmp/summary.json

# Или с удаленного хоста (при наличии доступа)
curl -k https://<node-ip>:10250/stats/summary > /tmp/summary.json

Парсинг JSON-ответа

Summary API возвращает подробную статистику в JSON формате. Вот простой Python-скрипт для извлечения ключевых метрик:

#!/usr/bin/env python3
import json
import sys

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.0
        total_memory = 0.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}')

if __name__ == "__main__":
    # ИспользованиеЕсли parse_kubelet_stats(имя файла передано аргументом — используем его, иначе — /tmp/summary.json
    filename = sys.argv[1] if len(sys.argv) > 1 else "/tmp/summary.json")
    parse_kubelet_stats(filename)

Преимущества метода

  • Работает даже без 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 limitrangepods --all-namespaces \
  | grep -E -A2 -B2 "Namespace:|Name:|Container:|Limits:|Requests:"

Метод 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: СборПростой скрипт для сбора фактических метрик при наличии Metric Server

#!/bin/bash

# ПолучаемОдноразовый текущееснимок потребление«сейчас» в current_usage.txt
echo "TIMESTAMP              NAME                          CONTAINER             CPU(cores)   MEMORY(bytes)" > current_usage.txt
kubectl top pods -n production-all-namespaces --containers --no-headers \
  | awk -v D="$(date -Iseconds)" \
        '{ printf "%-24s %-28s %-20s %12s %12s\n", D, $1, $2, $3, $4 }' \
  >> current_usage.txt

# Собираем данныеСбор в течение часа длякаждые получения5 среднихминут значенийв usage_log.txt
echo "TIMESTAMP              NAME                          CONTAINER             CPU(cores)   MEMORY(bytes)" > usage_log.txt
for i in {1..12}; do
  echo "$(date): " >> usage_log.txt
  kubectl top pods -n-all-namespaces production--containers --no-headers \
    | awk -v D="$(date -Iseconds)" \
          '{ printf "%-24s %-28s %-20s %12s %12s\n", D, $1, $2, $3, $4 }' \
    >> usage_log.txt
  sleep 300  # 5 минут
done

Шаг 2: Извлечение requests/limits

# Создаем подробный отчет
kubectl getdescribe pods -n-all-namespaces production -o json\
  | jqgrep -rE '-A2 .items[] | 
{
  name: .metadata.name,
  containers: [.spec.containers[] | {
    name: .name,
    cpu_req: .resources.requests.cpu //-B2 "none",
    mem_req: .resources.requests.memory // Namespace:|Name:|Container:|Limits:|Requests:"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)

Интерпретация результатов и рекомендации

Типичные проблемы и их решения

  1. Завышенные requests

    • Симптомы: низкая утилизация узлов, проблемы с планированием
    • Решение: уменьшить requests на основе фактического потребления
  2. Заниженные limits

    • Симптомы: частые OOM kills, нестабильная работа приложений
    • Решение: увеличить limits с учетом пиковых нагрузок
  3. Отсутствие requests/limits

    • Симптомы: непредсказуемое поведение кластера
    • Решение: установить базовые значения, использовать LimitRange

Рекомендуемые практики

  1. Установите requests на уровне 75-80% от среднего потребления
  2. Установите limits на уровне 150-200% от requests для CPU
  3. Для памяти: limits должны быть близки к максимальному наблюдаемому потреблению
  4. Используйте 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 — это не разовая задача, а постоянный процесс оптимизации. Используя описанные методы, вы сможете:

  • Выявить неэффективное использование ресурсов
  • Предотвратить проблемы с производительностью
  • Оптимизировать затраты на инфраструктуру
  • Обеспечить стабильную работу приложений

Помните: мониторинг ресурсов должен сочетаться с пониманием специфики ваших приложений. Не всегда математически оптимальные значения являются лучшими с точки зрения надежности системы.

Начните с базового аудита раз в неделю, постепенно автоматизируя процесс и внедряя более сложные инструменты мониторинга по мере роста вашего кластера.