Введение: почему даже опытные инженеры ошибаются в Kubernetes
Kubernetes остаётся стандартом оркестрации контейнеров в 2026 году, но сложность системы приводит к регулярным инцидентам даже в зрелых командах. Спешка при первичной настройке, устаревшая документация и недостаток практики в production-среде создают благоприятную почву для ошибок. По данным внутреннего аудита нашей базы знаний, 8 из 10 обращений по Kubernetes связаны с одними и теми же проблемами: неправильные requests/limits, слишком широкие RBAC-права и отсутствие мониторинга. Эта статья разбирает 10 типичных ошибок и даёт проверенные решения. Материал рассчитан на DevOps-инженеров и системных администраторов, которые хотят сократить время отладки и предотвратить инциденты до их влияния на бизнес.
Каждый раздел содержит конкретные команды, примеры манифестов и практические рекомендации. Команды диагностики нужно выполнять с учётом прав доступа и namespace: отсутствие результата иногда означает не отсутствие проблемы, а недостаточные разрешения. Если вы уже столкнулись с нестабильностью кластера, начните с чек-листа в заключении: он поможет быстро определить критичную зону.
Ошибка 1: Игнорирование requests и limits для контейнеров
Отсутствие requests и limits нарушает планирование ресурсов. Планировщик Kubernetes не может принять адекватное решение о размещении подов, а kubelet не знает, когда нужно вмешаться. Это приводит к перегрузке узлов, хаотичному вытеснению подов и деградации сервисов. В production-среде такая ошибка часто проявляется как случайные OOMKilled и непредсказуемые задержки ответа API.
Requests определяют минимальный объём CPU и памяти, который гарантируется контейнеру при планировании. Limits задают верхнюю границу потребления. При отсутствии limits контейнер с утечкой памяти может забрать все ресурсы узла и нарушить работу соседних подов. При отсутствии requests планировщик размещает поды без учёта реальной нагрузки, что ведёт к переподписке и деградации.
Как правильно установить requests и limits: пошаговая инструкция
Настройка ресурсов требует данных о реальном потреблении. Действуйте по алгоритму:
- Запустите приложение без limits на тестовом окружении.
- Соберите метрики потребления за 7-14 дней с помощью
kubectl top podsили Prometheus. - Установите requests на уровне 70-80% от среднего потребления.
- Установите limits на уровне 150-200% от пикового потребления.
- Настройте Vertical Pod Autoscaler в режиме рекомендаций для дальнейшей корректировки.
Проценты из примера не заменяют нагрузочное тестирование: для latency-критичных сервисов requests проверяйте по p95/p99 потребления, а для batch-workload учитывайте длительные пики. Не задавайте requests и limits одинаковыми для всех контейнеров.
Пример манифеста с корректными значениями:
apiVersion: v1
kind: Pod
metadata:
name: web-app
spec:
containers:
- name: nginx
image: nginx:1.25
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"Признаки проблемы и быстрая проверка
В production ошибка обычно проявляется как:
- Статус
OOMKilledи рост числа перезапусков контейнеров. - Поды в статусе
Evicted, несмотря на отсутствие очевидной нагрузки на приложение. - Рост latency API server и задержек ответа приложения при пиковом трафике.
Начните проверку с команд kubectl top pods, kubectl describe pod и kubectl describe node. Сопоставьте фактическое потребление с секцией Allocated resources и событиями узла. Если проблема возникает только в одном workload, сначала скорректируйте его requests/limits; если давление на память есть на нескольких узлах, проверьте ёмкость кластера и правила планирования.
Ошибка 2: Недостаточная настройка RBAC: риски безопасности
RBAC (Role-Based Access Control) управляет правами пользователей и сервисных аккаунтов. Ошибка здесь открывает доступ к секретам, конфигурациям и управлению кластером. Частая проблема: использование cluster-admin для всех сервисных аккаунтов или привязка ролей на уровне кластера вместо namespace. Это нарушает принцип наименьших привилегий и расширяет поверхность атаки.
Если злоумышленник получает доступ к поду с привилегированным сервисным аккаунтом, он может прочитать все секреты в namespace или выйти за его пределы. Аудит безопасности Kubernetes начинается именно с проверки RBAC.
Практическое руководство: создание ролей и привязок с минимальными правами
Для типового сценария разработчика, которому нужен доступ только к подам в своём namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: development
name: developer-role
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: development
name: developer-binding
subjects:
- kind: User
name: "dev-user"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer-role
apiGroup: rbac.authorization.k8s.ioИспользуйте Role и RoleBinding для ограничения прав в рамках namespace. ClusterRole и ClusterRoleBinding применяйте только для действительно кластерных ресурсов: узлы, PersistentVolumes, namespace'ы. Для сервисных аккаунтов отдельно проверьте права на чтение Secrets, выполнение команд в подах и изменение workload.
Аудит RBAC: как найти и исправить избыточные разрешения
Проверьте, какие действия разрешены текущему пользователю:
kubectl auth can-i --list --namespace=developmentДля поиска всех привязок к cluster-admin:
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects'Быстрая проверка в инциденте: выполните kubectl auth can-i get secrets --all-namespaces от имени проверяемой учётной записи и сравните результат с необходимым сценарием. Если права избыточны, сначала удалите неиспользуемые ClusterRoleBinding и замените их namespace-уровневыми RoleBinding после проверки зависимостей.
Инструменты kube-bench и RBAC-lookup автоматизируют проверку. В managed Kubernetes часть прав управляется провайдером, но RBAC пользователей, namespace и приложений остаётся зоной ответственности команды. Подробный пятишаговый алгоритм проверки кластера описан в нашем руководстве по аудиту безопасности Kubernetes.
Ошибка 3: Использование устаревших версий Kubernetes и компонентов
Kubernetes поддерживает три последние минорные версии. Эксплуатация более старых версий означает наличие известных уязвимостей без исправлений. В 2026 году кластеры на версиях 1.24 и ниже не получают обновлений безопасности. Это прямой риск компрометации production-среды. Перед планированием обновления сверяйтесь с актуальной матрицей поддержки дистрибутива и облачного провайдера: у managed Kubernetes дата доступности версий может отличаться.
Устаревшие версии также несовместимы с новыми API. Манифесты, написанные для актуальных версий, могут не работать на старых кластерах, и наоборот. Обновление откладывается из-за страха даунтайма, но без него кластер становится всё более уязвимым.
Стратегия безопасного обновления кластера без даунтайма
Перед изменением зафиксируйте версии Kubernetes, CNI, ingress-контроллера, CSI-драйверов и критичных операторов. План обновления:
- Создайте резервную копию etcd и манифестов.
- Проверьте deprecated API и совместимость манифестов с целевой версией.
kubectl convertиспользуйте только если этот инструмент доступен в вашей версии и установлен отдельно. - Обновите control plane по одной мастер-ноде.
- Обновите worker nodes по одной, с drain и cordon.
- Проверьте работу кластера после каждого шага.
Для кластеров на kubeadm используйте kubeadm upgrade plan и kubeadm upgrade apply. В managed Kubernetes control plane обычно обновляет провайдер, а команда планирует node pools, disruption budget и совместимость аддонов. В self-hosted-кластере дополнительно проверьте сертификаты, доступность etcd и процедуру возврата.
Быстрая проверка перед обновлением: сохраните вывод kubectl get nodes, kubectl get pods -A и список событий, затем проверьте готовность реплик и PDB. Если после обновления растёт число Pending или CrashLoopBackOff, остановите дальнейший rollout и сначала проверьте CNI, CSI и admission-компоненты.
Ошибка 4: Некорректная конфигурация сети: проблемы связности и безопасности
Сетевая конфигурация определяет, как поды общаются друг с другом и с внешним миром. Ошибки здесь проявляются как таймауты между сервисами, недоступность API и утечки трафика. Частая проблема: отсутствие NetworkPolicy, что позволяет любому поду обращаться к любому другому поду в кластере.
Выбор CNI-плагина влияет на производительность и функциональность. Calico и Cilium поддерживают NetworkPolicy и обеспечивают хорошую производительность. Flannel проще, но сам по себе не предоставляет сетевые политики. Фактические возможности зависят от режима установки и конфигурации CNI, поэтому проверяйте документацию конкретного дистрибутива.
Настройка NetworkPolicy для изоляции трафика: примеры
Политика, разрешающая трафик только от подов из namespace frontend к подам с меткой app: backend:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
ports:
- protocol: TCP
port: 8080Убедитесь, что namespace действительно имеет метку name: frontend: NetworkPolicy выбирает метки, а не текстовое имя namespace. При включении политики сначала разрешите необходимый DNS и служебный трафик, затем добавляйте ограничения по одному сервису.
Как проверить сеть и что исправить сначала
Симптомы сетевой ошибки: таймауты или ошибки DNS только между отдельными сервисами, недоступность Service при работающем pod и рост retransmit в TCP. Выполните kubectl exec из исходного пода, проверьте DNS, имя Service и порт, затем изучите NetworkPolicy и события CNI. Для низкоуровневой диагностики используйте tcpdump внутри подов или на узле, если это разрешено политиками безопасности.
Диагностика сетевых проблем требует системного подхода: сначала проверьте DNS, затем маршруты, затем политики. В managed Kubernetes дополнительно проверьте security groups и правила сети провайдера; в kubeadm и self-hosted-кластерах проверьте маршруты между узлами и состояние CNI-подов.
Ошибка 5: Отсутствие мониторинга и алертов: как не пропустить инцидент
Кластер без мониторинга работает вслепую. Вы узнаёте о проблеме только когда пользователи начинают жаловаться. Это увеличивает время восстановления и усложняет поиск корневой причины. Мониторинг обязателен для production-среды.
Стек Prometheus + Grafana стал стандартом для Kubernetes. Prometheus собирает метрики с API server, kubelet и подов. Grafana визуализирует их в дашбордах. Alertmanager отправляет уведомления при нарушении порогов.
Минимальный набор метрик для Kubernetes-кластера
Отслеживайте эти метрики:
node_cpu_usage- загрузка CPU на узлах.node_memory_usage- потребление памяти на узлах.pod_memory_usage- потребление памяти подами.apiserver_request_duration_seconds- задержка API server.kubelet_running_pods- количество запущенных подов.
Настройте алерты на использование ресурсов выше 80%, на рост количества перезапусков подов и на задержку API server выше 500 мс. Порог нужно проверять на исторических данных: единый порог для всех workload часто даёт ложные срабатывания.
Как проверить мониторинг во время инцидента
Проверьте, поступают ли свежие данные: сравните время последнего значения в Prometheus с текущим временем, состояние targets и наличие алерта в Alertmanager. Затем сопоставьте метрики узлов, подов и API server с событиями kubectl get events -A. Если метрик нет только у одного workload, проверьте ServiceMonitor или аннотации; если пропал весь источник, проверьте сам Prometheus, kubelet и сетевой доступ.
Быстрая диагностика через метрики описана в руководстве по диагностике Kubernetes.
Ошибка 6: Игнорирование лимитов на количество объектов в кластере
Большое количество объектов перегружает etcd и API server. Каждый запрос к API server обрабатывается дольше, а etcd растёт в размерах. Это замедляет все операции в кластере. Без квот одна команда может создать тысячи подов и нарушить работу остальных.
Признаки проблемы в production: медленные операции kubectl, задержки создания workload, рост размера etcd и большое число завершённых Job или старых ReplicaSet. Быстро проверьте количество объектов по namespace и состояние API server, затем найдите владельца ресурсов, которые создаются неконтролируемо.
Установите ResourceQuota для ограничения количества объектов в namespace:
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-counts
namespace: development
spec:
hard:
pods: "100"
services: "20"
secrets: "50"
configmaps: "50"LimitRange задаёт ограничения по умолчанию для подов, которые не указывают requests и limits. Регулярно очищайте неиспользуемые ресурсы: завершённые Job'ы, старые ReplicaSet'ы, неиспользуемые ConfigMap'ы и Secrets. Сначала ограничьте создание новых объектов квотами и исправьте контроллер, который генерирует лишние ресурсы; очистку выполняйте после проверки владельцев.
Ошибка 7: Неправильное управление секретами: хранение чувствительных данных
Секреты в Kubernetes хранятся в etcd в base64-кодировке. Это не шифрование, а кодирование. Любой, кто получит доступ к etcd, прочитает все секреты. Хранение паролей и токенов в открытом виде в манифестах - прямой путь к компрометации.
Используйте внешние системы управления секретами: HashiCorp Vault, Sealed Secrets или External Secrets Operator. Они интегрируются с Kubernetes и обеспечивают шифрование. Включите шифрование etcd на уровне кластера:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-key>
- identity: {}Никогда не храните секреты в образах контейнеров или в переменных окружения, которые видны через kubectl describe pod. Используйте secretKeyRef для монтирования секретов как файлов или переменных окружения. Учтите, что включение шифрования защищает данные при хранении, но не исправляет уже утёкший секрет: после инцидента ключи и токены нужно отозвать и заменить.
В managed Kubernetes настройка encryption provider и доступ к etcd обычно ограничены провайдером. В kubeadm и self-hosted-кластерах ответственность за конфигурацию, ротацию ключей и проверку восстановления лежит на администраторе.
Ошибка 8: Отсутствие резервного копирования и плана восстановления
Потеря etcd означает потерю всего состояния кластера: поды, сервисы, конфигурации. Без резервной копии восстановление невозможно. Человеческая ошибка, сбой диска или атака могут уничтожить кластер за секунды.
Бэкапируйте три компонента: etcd, манифесты приложений и данные в Persistent Volumes. Для etcd используйте встроенный механизм снапшотов:
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-snapshot.db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.keyБыстрая проверка резервного копирования состоит из трёх шагов: убедитесь, что последний файл существует и доступен изолированно от кластера, проверьте его целостность, затем выполните пробное восстановление в отдельной среде. Для PV отдельно проверьте, поддерживает ли CSI-драйвер snapshots и восстановление.
Для комплексного восстановления используйте Velero. Он бэкапит объекты Kubernetes и данные PV в внешнее хранилище. В managed Kubernetes уточните, какие компоненты и snapshots входят в сервис резервного копирования провайдера. Полное руководство по аварийному восстановлению кластера доступно в материале по восстановлению Kubernetes. Тестируйте восстановление регулярно: бэкап, который не проверяли, не считается бэкапом.
Ошибка 9: Пренебрежение безопасностью пода: запуск с привилегиями
Запуск контейнеров с root-правами или с привилегированным режимом расширяет поверхность атаки. Если злоумышленник эксплуатирует уязвимость в таком контейнере, он получает доступ к узлу. Это позволяет ему читать секреты других подов, изменять конфигурацию кластера и распространять атаку.
Признаки проблемы: под отклоняется политикой безопасности после изменения namespace, контейнер требует доступ к hostPath или неожиданно запускается от root. Быстро проверьте манифест и фактические параметры через kubectl get pod -o yaml и kubectl describe pod. Учитывайте, что Pod Security Admission может быть включён на уровне namespace, а дополнительный контроль может обеспечиваться admission-политиками.
Настройте SecurityContext для каждого пода:
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
containers:
- name: app
image: myapp:1.0
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: trueВключите Pod Security Admission на уровне namespace. Это предотвращает запуск подов с привилегиями и root-правами. Проверяйте образы на уязвимости перед развёртыванием. Исключения для системных workload оформляйте явно и регулярно пересматривайте.
Ошибка 10: Недостаточное тестирование изменений перед применением в production
Прямое применение манифестов в production без тестирования - частая причина инцидентов. Ошибка в конфигурации может привести к удалению сервиса, потере данных или нарушению сетевой связности. Ручные изменения не отслеживаются и затрудняют откат.
Перед применением проверьте манифесты на синтаксис и схему, сравните итоговое состояние с текущим через dry-run и протестируйте rollout в staging. Для диагностики неудачного изменения используйте историю Deployment, события и состояние ReplicaSet, а не только сообщение об ошибке в CI/CD.
Используйте GitOps-подход с ArgoCD или Flux. Все изменения проходят через git-репозиторий, тестируются в staging-окружении и автоматически применяются в production. Это обеспечивает воспроизводимость и возможность отката. Репозиторий должен содержать правила ревью, проверку секретов и понятный процесс экстренного отката.
Внедрите canary-развёртывания для новых версий приложений. Направляйте небольшой процент трафика на новую версию и следите за метриками. При обнаружении проблем автоматически откатывайтесь. Для инфраструктурных изменений используйте тестовые кластеры, идентичные production по конфигурации, насколько это возможно.
Приоритет исправления ошибок: что чинить в первую очередь
Если времени мало и в кластере уже есть инцидент, используйте такой порядок:
- Восстановите наблюдаемость: проверьте доступность API server, состояние узлов, подов и алертов.
- Стабилизируйте доступ к данным: убедитесь в наличии актуальной резервной копии etcd и PV.
- Устраните непосредственную нехватку ресурсов и проверьте requests/limits, OOMKilled и Evicted.
- Ограничьте опасный доступ: проверьте RBAC, привилегированные поды и доступ к Secrets.
- Восстановите сетевую связность: DNS, CNI, Service и NetworkPolicy.
- После стабилизации зафиксируйте изменение в GitOps, протестируйте его и только затем планируйте обновление версии или очистку объектов.
Такой маршрут помогает сначала снизить риск потери данных и повторного сбоя, а затем перейти к устранению первопричины. Не начинайте обновление или массовую очистку ресурсов, пока не подтверждены состояние бэкапа и наблюдаемость.
Заключение: чек-лист для предотвращения ошибок в Kubernetes
Используйте чек-лист как диагностический маршрут по критичным зонам:
- Сначала проверьте доступность API server, готовность nodes и ошибки в событиях кластера.
- Затем проверьте requests и limits, фактическое потребление и наличие OOMKilled или Evicted.
- Проверьте RBAC: права текущих пользователей и сервисных аккаунтов, лишние cluster-admin и границы namespace.
- Проверьте версию Kubernetes, совместимость компонентов и план обновления для kubeadm, managed Kubernetes или self-hosted.
- Проверьте DNS, CNI, маршруты, Service и NetworkPolicy между namespace'ами.
- Убедитесь, что Prometheus и Alertmanager собирают метрики и отправляют алерты.
- Проверьте ResourceQuota, LimitRange и количество объектов в каждом namespace.
- Убедитесь, что секреты зашифрованы в etcd, не попадают в Git и управляются через внешние системы.
- Проверьте актуальность резервных копий etcd и PV, а также результат последнего тестового восстановления.
- Убедитесь, что поды запускаются без root-прав и привилегированного режима, а изменения проходят через GitOps и staging.
Каждый пункт этого чек-листа закрывает конкретный риск. При ограниченном времени двигайтесь от доступности API и данных к ресурсам, доступам и сети, а после стабилизации оформите исправления в GitOps. Для углублённого изучения самовосстановления и отказоустойчивости обратитесь к материалу о механизмах самовосстановления Kubernetes.