Полная диагностика Custom Resources в Kubernetes: от простых ошибок до глубокой отладки | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Полная диагностика Custom Resources в Kubernetes: от простых ошибок до глубокой отладки

01 апреля 2026 9 мин. чтения

Когда ваш Custom Resource (CR) не работает, тратить часы на хаотичные поиски причины — непозволительная роскошь. Эта статья предлагает системный, пошаговый подход к диагностике, проверенный на практике в production-средах. Вы получите четкий алгоритм действий — от базовой проверки статуса через kubectl get до глубокой отладки логики контроллера с помощью специализированных инструментов вроде kube-events и ksniff. Мы разберем не только как «тушить пожар», но и как настроить проактивный мониторинг, чтобы проблемы выявлялись до сбоев в работе приложений.

С чего начать: быстрая проверка статуса и событий Custom Resource

При обнаружении неработоспособности Custom Resource важно действовать методично, а не наугад. Следующий алгоритм из 4 шагов поможет быстро локализовать проблему и сэкономить время.

  1. Проверка существования и базового статуса. Первым делом убедитесь, что сам ресурс и его определение (CRD) существуют в кластере. Используйте команды: kubectl get crd и kubectl get <crd.name>. В выводе обратите внимание на колонку READY (должна быть True) и STATUS. Состояние Unknown или пустой статус — первый сигнал о проблеме.
  2. Детальный осмотр через kubectl describe. Если статус в get неясен, выполните kubectl describe <cr>. Ключевые секции для анализа: Events (события Kubernetes о ресурсе, ищите Warning или Error), Status/Conditions (состояние с точки зрения контроллера, например, Ready=False с сообщением) и Finalizers (их зацикливание может блокировать операции). Для быстрого поиска ошибок: kubectl describe <cr> | grep -A10 -B5 -i 'error\\|fail'.
  3. Проверка логов контроллера. Найдите под контроллера, управляющего этим CR: kubectl get pods -l app=<controller-label> -n <namespace>. Просмотрите его логи: kubectl logs -f <pod-name> -n <namespace>. Ищите ошибки реконсиляции (reconciliation errors), сообщения об отказе в доступе (RBAC) или проблемы с валидацией.
  4. Анализ событий в namespace. Иногда проблема не в самом ресурсе, а в его окружении. Просмотрите все события в namespace, отсортированные по времени: kubectl get events --sort-by='.lastTimestamp' -n <namespace>.

На этом этапе часто выявляются типичные ошибки: синтаксические ошибки в YAML-манифесте, неверное значение apiVersion, отсутствие необходимых прав у ServiceAccount контроллера или проблемы с веб-хуками валидации.

Команда kubectl get: первичная оценка состояния

Команда kubectl get — ваш основной инструмент для первичной оценки. Вот конкретные примеры и интерпретация вывода.

Примеры команд и вывода:

# 1. Проверка существования CRD
kubectl get crd
# Ожидаемый вывод включает ваше CRD в списке, колонка ESTABLISHED=True.

# 2. Получение всех экземпляров конкретного CR
kubectl get myapps.example.com
# Вывод: NAME, READY, STATUS, AGE.
# Здоровый ресурс: READY=True, STATUS может быть "Running", "Available" или аналогичный.

# 3. Получение детального статуса в YAML
kubectl get myapp my-instance -o yaml | grep -A5 -B5 'status'
# Этот сниппет поможет быстро увидеть, заполнен ли статус контроллером.

Интерпретация ключевых состояний:

  • READY=False: Контроллер явно указал, что ресурс не готов. Причина будет в поле status.conditions или в логах контроллера.
  • STATUS=Unknown: Часто означает, что контроллер еще не обработал ресурс или не может связаться с API-сервером.
  • Пустой статус: Контроллер не обновил поле status. Это может быть нормой на начальном этапе (ресурс только создан) или признаком того, что контроллер "завис" или имеет недостаточные права для обновления статуса.

Глубокий анализ через kubectl describe: где искать причину

Вывод kubectl describe содержит консолидированную информацию из разных источников. Разберем его по секциям.

Секция Events: Самый важный источник для диагностики. Здесь Kubernetes фиксирует ключевые события жизненного цикла ресурса. Ищите события типа Warning.

  • Пример ошибки: Failed to create (проблема при создании), ValidationError (не прошла валидация CRD или веб-хука), FailedSync (контроллер не смог синхронизировать состояние).

Секция Status / Conditions: Здесь контроллер сообщает о внутреннем состоянии ресурса. Condition — это структура с полями type, status (True, False, Unknown), reason и message.

Conditions:
  - type: Ready
    status: "False"
    reason: "SomeDependencyMissing"
    message: "Required ConfigMap 'app-config' not found."

Поле message часто содержит точную причину проблемы.

Finalizers и Annotations: Проверьте, нет ли в finalizers значений, указывающих на внешние зависимости (например, kubernetes.io/pvc-protection). Зависший finalizer может помешать удалению ресурса. Annotations могут содержать служебную информацию от контроллера или других систем.

Инструменты глубокой отладки: заглядываем внутрь контроллера

Если базовые проверки не выявили причину, значит, проблема глубже — в логике самого контроллера, его взаимодействии с другими сервисами или в сетевом уровне. На этом этапе необходимы специализированные инструменты.

Мониторинг событий кластера с kube-events

Kube-events — это инструмент для агрегации, фильтрации и экспорта событий Kubernetes. Он позволяет проактивно отслеживать проблемы, связанные с вашими CR.

Установка и базовая настройка:

# Установка через Helm (предполагается, что Helm уже настроен)
helm repo add kube-events https://labring.github.io/kube-events
helm install kube-events kube-events/kube-events -n kube-events --create-namespace

Настройка фильтров для вашего CRD: Вы можете настроить kube-events на отправку уведомлений (в Slack, Webhook) или запись в лог только тех событий, которые касаются определенных ресурсов. Это делается через ConfigMap с правилами фильтрации. Например, правило для отслеживания событий Warning для всех ресурсов типа MyApp в определенном namespace.

Интеграция с Loki или Elasticsearch: Направьте выходной поток событий в вашу систему централизованного логирования. Это позволит коррелировать события Kubernetes с логами приложений и метриками, что критически важно для расследования инцидентов.

Трассировка сетевых запросов контроллера с помощью ksniff

Ksniff — это плагин для kubectl, который позволяет захватывать сетевой трафик из пода, используя Wireshark или tcpdump. Незаменим для диагностики проблем, когда контроллер должен взаимодействовать с внешними API, базами данных или другими сервисами, но эти вызовы завершаются неудачно.

Безопасное использование в production:

  1. Установите ksniff согласно официальной инструкции.
  2. Захват трафика следует выполнять только на конкретном поде контроллера и на строго ограниченное время.
  3. Рассмотрите возможность создания временного отладочного пода с теми же сетевыми политиками вместо прямого вмешательства в продакшен-поды.

Пример команды:

# Захват трафика с пода контроллера и открытие в Wireshark
kubectl sniff <pod-name> -n <namespace> -p -o ./capture.pcap

В анализе захваченного трафика ищите неудачные HTTP-запросы (коды ответа 4xx, 5xx), таймауты TCP-соединений или ошибки TLS/SSL.

Анализ логики и состояния контроллера

Когда проблема в бизнес-логике, нужно смотреть внутрь контроллера.

  • Повышение уровня детализации логов (Verbosity): Многие контроллеры, построенные на Operator SDK или Kubebuilder, поддерживают флаг -v или переменную окружения LOG_LEVEL для увеличения детализации логов. Установите уровень в debug или 10, чтобы увидеть детали каждого цикла реконсиляции.
  • Проверка кэша контроллера: Контроллеры используют клиентский кэш. Если кэш устарел, контроллер может работать с неактуальными данными. Принудительная пересинхронизация (restart пода) может быть временным решением для проверки этой гипотезы.
  • Доступность API: Убедитесь, что ваш CRD и его API-группа доступны в кластере: kubectl api-resources --api-group=<your.group>. Если группа не отображается, возможно, проблема с установкой CRD.

Проактивный мониторинг: как не допустить сбоев

Переход от реактивной отладки к проактивному мониторингу — признак зрелости эксплуатации. Вот как настроить наблюдение за состоянием ваших Custom Resources.

Настройка алертинга на основе метрик контроллера

Большинство современных контроллеров (особенно на основе controller-runtime) экспортируют стандартные метрики Prometheus. Ключевые из них для мониторинга:

  • controller_runtime_reconcile_errors_total: Счетчик ошибок реконсиляции. Рост этой метрики — прямой сигнал о проблемах.
  • workqueue_depth: Глубина очереди работ контроллера. Постоянно растущая очередь указывает на то, что контроллер не успевает обрабатывать изменения.
  • controller_runtime_reconcile_time_seconds: Гистограмма времени реконсиляции. Резкое увеличение времени может сигнализировать о проблемах с производительностью или внешними зависимостями.

Пример правила PrometheusRule для Alertmanager:

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: alert-custom-controller-errors
spec:
  groups:
  - name: custom-controller.rules
    rules:
    - alert: HighReconcileErrorRate
      expr: rate(controller_runtime_reconcile_errors_total{controller="myapp-controller"}[5m]) > 0.1
      for: 2m
      labels:
        severity: warning
      annotations:
        summary: "High error rate for MyApp controller"
        description: "MyApp controller is failing to reconcile resources at a rate of {{ $value }} errors/sec."

Регулярные проверки здоровья через Kubernetes Jobs

Для контроллеров, которые не экспортируют метрики, или для проверки бизнес-логики (например, доступности внешнего сервиса, на который ссылается CR) можно использовать периодические Kubernetes Jobs.

Пример CronJob для проверки состояния CR:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: healthcheck-myapp
spec:
  schedule: "*/5 * * * *" # Каждые 5 минут
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: healthcheck-sa # SA с правами на get для вашего CR
          containers:
          - name: checker
            image: bitnami/kubectl:latest
            command:
            - /bin/bash
            - -c
            - |
              # Проверяем, есть ли CR с состоянием Ready=False
              if kubectl get myapps.example.com -n default -o json | jq -e '.items[] | select(.status.conditions[]?.type=="Ready" and .status.conditions[]?.status=="False")' > /dev/null; then
                echo "CRITICAL: Found MyApp resources that are not Ready."
                # Здесь можно отправить webhook-уведомление
                exit 1
              else
                echo "OK: All MyApp resources are healthy."
                exit 0
              fi
          restartPolicy: OnFailure

Этот Job будет завершаться с ошибкой (exit code 1), если найдет проблемные ресурсы, что можно отслеживать через мониторинг самих Jobs или отправлять уведомление через механизм onFailure.

Чеклист и готовые команды для быстрого восстановления

В критической ситуации нет времени перечитывать статью. Используйте эту шпаргалку как пошаговый план действий.

Пошаговый алгоритм диагностики (шпаргалка)

  1. Базовый статус: kubectl get <crd.name> -o wide. Ожидаем: READY=True. Если нет — перейти к шагу 2.
  2. События ресурса: kubectl describe <cr> | grep -A10 -B2 -i "events:". Ищем события типа Warning или Error.
  3. Условия (Conditions): kubectl get <cr> -o yaml | yq '.status.conditions'. Ищем условие с status: "False" и читаем reason/message.
  4. Логи контроллера: kubectl logs -f -l app=<controller-label> --tail=100. Ищем ошибки реконсиляции, RBAC, валидации.
  5. События namespace: kubectl get events --sort-by='.lastTimestamp' --field-selector involvedObject.kind=<CRD Kind>. Контекстные события вокруг ресурса.
  6. Глубокая отладка: Если шаги 1-5 не помогли, используйте kube-events для истории или ksniff для анализа сетевого взаимодействия контроллера.

Примечание по версионности: Команды актуальны для Kubernetes версий 1.24+. В более старых версиях могут быть различия в выводе kubectl get или доступности некоторых флагов. Всегда сверяйтесь с документацией для вашей версии кластера.

Частые ошибки и их решения (из практики)

  • Проблема: CR создан, но поле status пустое.
    Диагностика: Проверьте логи контроллера на наличие ошибок. Убедитесь, что ServiceAccount контроллера имеет права update на subresource status для вашего CRD в RBAC-правилах.
    Решение: Добавьте в ClusterRole: - apiGroups: ["example.com"]; resources: ["myapps/status"]; verbs: ["get", "update", "patch"].
  • Проблема: Постоянные реконсиляции (reconcile loops), высокий CPU контроллера.
    Диагностика: Включите debug-логирование контроллера. Проверьте, не обновляет ли контроллер в каждом цикле аннотации или метки ресурса, что снова запускает реконсиляцию.
    Решение: В логике контроллера используйте патчинг (patch) вместо обновления (update) всего объекта и избегайте обновлений, если фактическое состояние не изменилось.
  • Проблема: Finalizer блокирует удаление CR.
    Диагностика: kubectl get <cr> -o yaml | grep finalizers. Удаление зависает на стадии Terminating.
    Решение (с риском): Принудительно удалите finalizer: kubectl patch <cr> -p '{"metadata":{"finalizers":[]}}' --type=merge. Внимание! Сначала убедитесь, что контроллер, отвечающий за этот finalizer, больше не работает, иначе может остаться "мусор" в внешних системах.
  • Проблема: ValidationError при создании/обновлении CR.
    Диагностика: Сообщение об ошибке в kubectl describe или событиях. Проверьте схему CRD (kubectl get crd <name> -o yaml) на соответствие данным в вашем манифесте.
    Решение: Исправьте манифест согласно схеме. Если ошибка от Admission Webhook, проверьте логи веб-хука.

Для более глубокого понимания основ, на которых построены многие контроллеры, рекомендуем наше руководство «Что такое Docker: концепция контейнеризации для системных администраторов и DevOps». Оно поможет разобраться в фундаментальных принципах изоляции и управления зависимостями, критически важных при разработке операторов.

Поделиться:
Сохранить гайд? В закладки браузера