Введение: почему Kubernetes называют self-healing системой
Kubernetes автоматически поддерживает заданное состояние приложений и восстанавливает их после сбоев без ручного вмешательства. Этот принцип называется self-healing. Оркестратор постоянно сравнивает фактическое состояние кластера с желаемым, описанным в манифестах, и устраняет расхождения.
Ключевые механизмы самовосстановления: контроллеры ReplicaSet и StatefulSet, которые следят за количеством подов, пробы liveness и readiness, которые проверяют состояние контейнеров, и планировщик, который размещает поды на здоровых узлах. Если под упал, контроллер пересоздает его. Если контейнер завис, liveness-проба перезапустит его. Если узел вышел из строя, планировщик перенесет нагрузку на другие ноды.
Материал основан на реальном опыте эксплуатации кластеров и актуален для версий Kubernetes 2026 года. Мы разберем каждый механизм, типовые сценарии отказов и практическую настройку проб для высокой доступности.
Ключевые механизмы самовосстановления: контроллеры и пробы
Самовосстановление в Kubernetes строится на двух уровнях. Контроллеры поддерживают нужное количество реплик приложения, а пробы контролируют состояние каждого контейнера. Эти механизмы работают вместе: контроллер создает под, пробы проверяют его работоспособность, при сбое проба инициирует перезапуск, а контроллер при необходимости пересоздает под целиком.
ReplicaSet: гарантия количества подов
ReplicaSet следит за тем, чтобы в кластере всегда работало заданное количество подов. Если под удален вручную или упал из-за ошибки, ReplicaSet немедленно создает новый. Контроллер работает в цикле reconcile: получает текущее состояние, сравнивает с желаемым, выполняет корректирующие действия.
ReplicaSet обычно не используется напрямую. Им управляет Deployment, который добавляет стратегии обновления версий и откаты. При удалении пода ReplicaSet создает замену в течение секунд. Это базовый уровень самовосстановления для stateless-приложений: веб-серверов, API, микросервисов.
Ограничение ReplicaSet: он не подходит для stateful-приложений, которым нужны стабильные идентификаторы и постоянные тома. Для таких задач используется StatefulSet. Подробнее о работе контроллеров и их архитектуре читайте в разборе механизмов watch и reconcile loop.
StatefulSet: самовосстановление для stateful-приложений
StatefulSet сохраняет стабильные идентификаторы подов и привязку к постоянным томам. Каждый под получает предсказуемое имя вида mysql-0, mysql-1, mysql-2. При падении пода StatefulSet пересоздает его с тем же именем и тем же PersistentVolumeClaim, данные сохраняются.
StatefulSet также управляет порядком запуска и остановки подов. При масштабировании вниз он удаляет поды по одному, начиная с последнего. При восстановлении после сбоя поды запускаются в обратном порядке. Это важно для кластерных систем, где важен порядок инициализации.
Пример: под с базой данных postgres-1 упал. StatefulSet пересоздает его с тем же именем и подключает тот же PVC. Данные не теряются, репликация восстанавливается автоматически. Если вам нужен полный пример настройки StatefulSet с постоянными томами, смотрите руководство по отказоустойчивому кластеру.
Пробы живости (liveness) и готовности (readiness): контроль состояния
Пробы проверяют состояние контейнера изнутри. Liveness-проба отвечает на вопрос: жив ли процесс? Если проба не проходит несколько раз подряд, kubelet перезапускает контейнер. Readiness-проба отвечает на вопрос: готов ли контейнер принимать трафик? Если нет, под исключается из балансировки сервиса, но не перезапускается.
Разница принципиальна. Liveness лечит зависания и deadlock'и. Readiness защищает от отправки трафика в под, который еще загружается или временно не может обрабатывать запросы. Типичный пример: приложение стартует 30 секунд, загружает данные в память. Readiness-проба с initialDelaySeconds: 30 не пустит трафик до готовности. Liveness-проба с тем же delay начнет проверять живость только после старта.
Неправильная настройка проб приводит к ложным срабатываниям: контейнер перезапускается без причины или продолжает получать трафик, будучи неработоспособным. Практические примеры конфигурации разберем в разделе настройки.
Типовые сценарии отказов и реакция Kubernetes
Kubernetes обрабатывает три основных типа сбоев: отказ узла, зависание контейнера и сетевые проблемы. В каждом сценарии задействованы разные механизмы, и время восстановления отличается.
Падение ноды: пересоздание подов на других узлах
Когда узел выходит из строя, kubelet на нем перестает отправлять heartbeat в control plane. Через 40 секунд узел помечается как NotReady. Через 5 минут (значение по умолчанию для pod-eviction-timeout) controller-manager инициирует эвакуацию подов: они пересоздаются на здоровых узлах.
Процесс выглядит так: kubelet замолчал, control plane пометил узел NotReady, таймаут истек, Deployment Controller запросил создание новых подов, scheduler разместил их на доступных нодах. Для stateless-приложений восстановление занимает около 5-6 минут. Для stateful-приложений с PVC на локальных дисках может потребоваться ручное вмешательство.
Рекомендация: настройте pod-eviction-timeout в зависимости от критичности сервисов. Для production-кластеров значение 2-3 минуты сокращает время простоя, но увеличивает риск ложной эвакуации при временных сетевых проблемах.
Зависание контейнера: liveness-проба перезапускает
Контейнер может зависнуть без падения процесса: deadlock, бесконечный цикл, исчерпание ресурсов. Liveness-проба обнаруживает это и перезапускает контейнер. Типы проб: HTTP GET, TCP socket, exec-команда.
Пример конфигурации HTTP liveness-пробы:
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3Kubelet выполняет проверку каждые 10 секунд. После трех неудачных попыток контейнер перезапускается. Параметр initialDelaySeconds дает приложению время на запуск до первой проверки.
Риск: слишком агрессивные пробы с коротким periodSeconds и низким failureThreshold вызывают ненужные перезапуски при временных замедлениях. Для приложений с длительными операциями увеличьте timeoutSeconds до 10-15 секунд.
Потеря сети: как Kubernetes обрабатывает сетевые сбои
Kubernetes различает отказ узла и сетевую изоляцию. Если kubelet не может связаться с control plane, узел помечается как NotReady, но поды на нем продолжают работать. Это ключевое отличие от падения ноды: приложения могут быть доступны для клиентов, но control plane не видит их.
При восстановлении связи состояние синхронизируется: kubelet отправляет актуальный статус подов, control plane обновляет информацию. Если сетевой раздел длится дольше pod-eviction-timeout, поды эвакуируются, и после восстановления связи возможен запуск дубликатов. Для предотвращения этого используйте PodDisruptionBudget и правильно настраивайте readiness-пробы, чтобы исключать поды с сетевыми проблемами из трафика.
Readiness-проба с проверкой сетевой доступности зависимостей (база данных, кэш) автоматически уберет под из балансировки при сетевом сбое, не перезапуская его.
Практическая настройка проб для высокой доступности
Правильная конфигурация проб определяет стабильность системы. Ошибки здесь приводят к ложным перезапускам или пропуску реальных сбоев.
Параметры проб: как избежать ложных срабатываний
Каждый параметр пробы влияет на поведение системы:
- initialDelaySeconds: задержка перед первой проверкой. Учитывайте реальное время запуска приложения. Для Java-приложений с длительной инициализацией устанавливайте 30-60 секунд.
- periodSeconds: интервал между проверками. Значение 10 секунд подходит для большинства приложений. Слишком частое выполнение создает лишнюю нагрузку.
- timeoutSeconds: таймаут ожидания ответа. Для HTTP-проб достаточно 5 секунд. Для exec-проб с тяжелыми командами увеличьте до 10-15.
- failureThreshold: количество неудач до срабатывания. Значение 3-5 предотвращает ложные перезапуски при кратковременных замедлениях.
- successThreshold: количество успехов для перехода в рабочее состояние. Для readiness-проб значение 1 обычно достаточно.
Главное правило: liveness-проба не должна проверять внешние зависимости. Если приложение живо, но база данных недоступна, liveness должна проходить. Иначе контейнер будет перезапускаться без пользы. Внешние зависимости проверяет readiness-проба.
Примеры конфигурации: HTTP, TCP, exec пробы
HTTP-проба для веб-сервиса:
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3TCP-проба для базы данных, где HTTP-эндпоинта нет:
livenessProbe:
tcpSocket:
port: 5432
initialDelaySeconds: 20
periodSeconds: 10
failureThreshold: 3
readinessProbe:
tcpSocket:
port: 5432
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3Exec-проба для проверки файла или процесса:
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 10
periodSeconds: 15
failureThreshold: 3Перед деплоем тестируйте пробы локально. Проверьте, что эндпоинты отвечают ожидаемым кодом, а команды завершаются за разумное время. Готовые production-манифесты с настроенными пробами и ограничениями ресурсов найдете в руководстве по Deployment.
Стратегии обновления и лимиты ресурсов для отказоустойчивости
Самовосстановление работает не только при сбоях, но и при плановых изменениях. Правильные стратегии обновления и лимиты ресурсов предотвращают каскадные отказы.
Rolling update: обновление без простоя
Rolling update постепенно заменяет старые поды новыми, сохраняя доступность сервиса. Параметры maxSurge и maxUnavailable управляют процессом. maxSurge: 1 позволяет создать один дополнительный под сверх желаемого количества. maxUnavailable: 0 запрещает удалять старые поды до готовности новых.
Пример для deployment с 3 репликами: при обновлении версии Kubernetes создает один новый под, ждет его готовности, затем удаляет один старый. В любой момент доступно минимум 3 пода. Для критичных сервисов устанавливайте maxUnavailable: 0 и maxSurge: 1.
Сравнение стратегий обновления: Rolling Update, Blue-Green и Canary разобрано в отдельном руководстве.
Лимиты ресурсов: предотвращение каскадных отказов
Requests и limits определяют, сколько CPU и памяти получает под. Requests используются планировщиком для размещения подов. Limits ограничивают максимальное потребление. Без лимитов один под может занять всю память узла и вызвать OOM kill других контейнеров.
Пример установки ресурсов:
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"Рекомендации: устанавливайте requests на уровне среднего потребления, limits с запасом 50-100%. Используйте мониторинг для определения фактических значений. Метрики CPU, памяти и сети для диагностики описаны в руководстве по troubleshooting.
PodDisruptionBudget: защита от добровольных disruptions
PodDisruptionBudget (PDB) ограничивает количество одновременно недоступных подов при добровольных disruptions: дренаж узла, обновление кластера, обслуживание. PDB не защищает от непроизвольных сбоев, таких как падение ноды.
Пример PDB для deployment с 3 репликами:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: app-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: my-appПри дренаже узла система не позволит удалить больше одного пода одновременно. Для критичных сервисов устанавливайте minAvailable на уровне N-1, где N - количество реплик. Если вы используете облачную инфраструктуру для Kubernetes, обратите внимание на Timeweb Cloud с готовыми кластерами и гибким масштабированием ресурсов.
Заключение: самовосстановление как фундамент надежности
Самовосстановление Kubernetes строится на трех уровнях: контроллеры поддерживают количество подов, пробы контролируют состояние контейнеров, стратегии обновления и лимиты ресурсов предотвращают сбои при изменениях. Каждый уровень требует правильной настройки под конкретное приложение.
ReplicaSet и StatefulSet гарантируют, что нужное количество подов всегда работает. Liveness-пробы перезапускают зависшие контейнеры. Readiness-пробы управляют трафиком. Rolling update обновляет без простоя. Лимиты ресурсов защищают узлы от перегрузки. PDB сохраняет доступность при обслуживании.
Правильная настройка требует понимания поведения приложения: время запуска, зависимости, паттерны потребления ресурсов. Тестируйте сценарии отказов: удаляйте поды, останавливайте узлы, обрывайте сеть. Проверяйте, что система восстанавливается за ожидаемое время. Материал проверен на практике и актуален для версий Kubernetes 2026 года.