Kubernetes

Теория: Надёжность и стабильность

Развёртывание приложения в Kubernetes — это только начало. Запустить Pod недостаточно. В production важнее другое: приложение должно оставаться доступным при сбоях, не мешать соседям по узлу, переживать обновления и автоматически подстраиваться под нагрузку. Kubernetes решает эти задачи через пробы состояния, контроль ресурсов и механизмы масштабирования.

Главная идея проста. Kubernetes управляет не процессами, а состоянием системы. Он постоянно сравнивает «что должно работать» с «что работает сейчас» — и исправляет расхождения. Но чтобы это работало, ему нужно понимать, в каком состоянии находится само приложение.

Как Kubernetes понимает, что приложение живо

Представьте Pod. Контейнер запущен, процесс внутри работает, но приложение зависло. HTTP-сервер не отвечает, база не принимает соединения, обработчик очереди стоит. Для операционной системы всё нормально — процесс существует. Для Kubernetes Pod находится в состоянии Running. Без дополнительных сигналов Kubernetes считает, что всё в порядке, и продолжает направлять трафик на сломанный экземпляр.

Kubernetes не знает о внутреннем состоянии приложения без настроенных проб. Он видит только факт существования процесса. Поэтому система предоставляет механизм probes — активных проверок, которые позволяют измерять реальное состояние приложения, а не просто наличие запущенного контейнера.

Пробы состояния: логика жизненного цикла

Пробы работают в порядке жизни Pod. Сначала Kubernetes проверяет, запустилось ли приложение. Потом — готово ли оно принимать трафик. И уже после этого — продолжает ли оно нормально работать.

Эта последовательность важна. Именно в таком порядке и нужно их понимать.

Startup Probe — проверка запуска

Некоторые приложения запускаются не мгновенно. Например, сервис на JVM — виртуальной машине Java — сначала прогревает runtime, загружает классы и только потом начинает принимать запросы. Если в этот момент Kubernetes начнёт проверять живучесть, он может решить, что контейнер «завис», и уйдёт в цикл перезапусков.

Startup Probe решает эту проблему. Пока проверка запуска не прошла успешно, остальные пробы не выполняются.

startupProbe:
  httpGet:
    path: /startup
    port: 8080
  periodSeconds: 10
  failureThreshold: 30

Kubernetes будет проверять endpoint /startup каждые 10 секунд. Если за 30 попыток приложение так и не вышло в рабочее состояние — контейнер перезапускается. Если проверка прошла — Startup Probe отключается навсегда, и система переходит к следующим этапам.

Так Kubernetes отличает «медленный старт» от «настоящего зависания».

Readiness Probe — проверка готовности

Запуститься — не значит быть готовым принимать трафик. Приложение может подняться, но ещё не подключиться к базе, не прогреть кеш или не загрузить конфигурацию.

Readiness Probe определяет, готов ли Pod обслуживать запросы.

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  periodSeconds: 5
  failureThreshold: 3

Пока проверка не успешна, Pod не включается в Service. Трафик на него не поступает. Как только приложение возвращает успешный статус — Pod подключается к балансировке.

Если в процессе работы приложение временно теряет зависимость (например, база недоступна), Readiness Probe может вернуть ошибку. Тогда Kubernetes временно уберёт Pod из балансировки, не перезапуская контейнер. Когда зависимость восстановится — Pod автоматически вернётся в работу.

Это ключевой механизм бесшовных Rolling Update. Новый Pod не получит трафик, пока не станет готов. Старый Pod продолжит работать до полной готовности нового.

Liveness Probe — проверка живучести

Даже готовое приложение может зависнуть. Поток заблокировался, deadlock, бесконечный цикл. Процесс жив, но сервис мёртв.

Liveness Probe отвечает за обнаружение таких ситуаций.

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  periodSeconds: 10
  failureThreshold: 3

Если несколько проверок подряд возвращают ошибку — Kubernetes считает контейнер неработоспособным и перезапускает его. Так система автоматически восстанавливается после зависаний, не требуя вмешательства человека.

Важно: Liveness Probe должна проверять только сам процесс, не внешние зависимости. Если в /health добавить проверку базы данных, то при падении базы все поды начнут перезапускаться — хотя сами приложения работают нормально. Это приведёт к каскадному сбою. Проверку внешних зависимостей выносите в Readiness Probe.

Способы выполнения проверок

Kubernetes не навязывает способ проверки. Он ожидает только сигнал «успешно / неуспешно».

Самый распространённый вариант — HTTP-endpoint. Приложение возвращает HTTP-статус 200–399 — значит всё в порядке.

httpGet:
  path: /healthz
  port: 8080

Если HTTP не используется, можно проверять сам факт открытия TCP-соединения.

tcpSocket:
  port: 3306

Успешное соединение означает, что сервис доступен.

Если требуется сложная логика, можно выполнить команду внутри контейнера.

exec:
  command:
    - /bin/sh
    - -c
    - pg_isready -U postgres

Возврат exit code 0 означает успешную проверку.

Пример: API интернет-магазина

Рассмотрим реальный сценарий — backend интернет-магазина на Go. Приложение обрабатывает заказы, работает с PostgreSQL и Redis.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: shop-api
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: shop-api
  template:
    metadata:
      labels:
        app: shop-api
    spec:
      containers:
        - name: api
          image: registry.example.com/shop/api:2.4.1
          ports:
            - containerPort: 8080
          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: shop-secrets
                  key: database-url
            - name: REDIS_URL
              valueFrom:
                secretKeyRef:
                  name: shop-secrets
                  key: redis-url

          startupProbe:
            httpGet:
              path: /healthz/startup
              port: 8080
            periodSeconds: 5
            failureThreshold: 12

          readinessProbe:
            httpGet:
              path: /healthz/ready
              port: 8080
            periodSeconds: 5
            failureThreshold: 3

          livenessProbe:
            httpGet:
              path: /healthz/live
              port: 8080
            periodSeconds: 10
            failureThreshold: 3

          resources:
            requests:
              cpu: "250m"
              memory: "256Mi"
            limits:
              cpu: "500m"
              memory: "512Mi"

Приложение реализует три endpoint:

  • /healthz/startup — возвращает 200 после запуска HTTP-сервера и подключения к базе
  • /healthz/ready — возвращает 200, когда PostgreSQL и Redis доступны и отвечают на запросы
  • /healthz/live — возвращает 200, если основной цикл обработки работает (без проверки внешних сервисов)

При старте у приложения есть 60 секунд (12 попыток × 5 секунд) на инициализацию. После этого Kubernetes начинает проверять готовность каждые 5 секунд и живучесть каждые 10 секунд.

Контроль потребления ресурсов

На одном узле могут работать десятки Pod. Если один контейнер начнёт потреблять всю память или процессор, он нарушит работу остальных. Поэтому Kubernetes управляет ресурсами через requests и limits.

requests — минимальные ресурсы, которые контейнер гарантированно получит. По ним Scheduler решает, на какой узел можно поставить Pod.

requests:
  cpu: "250m"
  memory: "256Mi"

Если в кластере нет узла с таким объёмом свободных ресурсов — Pod останется в Pending. Это защищает от запуска приложения в условиях нехватки ресурсов.

limits — верхняя граница потребления.

limits:
  cpu: "500m"
  memory: "512Mi"

Если контейнер превышает CPU-лимит — он замедляется (throttling). Если превышает лимит памяти — контейнер завершается с ошибкой OOMKilled и перезапускается.

Так система остаётся стабильной даже при ошибках в приложении.

Классы QoS

На основе requests и limits Kubernetes присваивает Pod класс качества обслуживания.

Если requests равны limits — Pod получает класс Guaranteed. Это самые защищённые контейнеры, их Kubernetes убирает последними при нехватке ресурсов.

Если requests меньше limits — класс Burstable. Средний приоритет.

Если ресурсы не указаны — BestEffort. Такие контейнеры будут остановлены первыми при перегрузке узла.

В production не используют BestEffort. Это стандартная практика в Kubernetes.

Автоматическое масштабирование

Нагрузка в production редко стабильна. Днём трафик высокий, ночью низкий. Держать постоянное число реплик неэффективно.

Horizontal Pod Autoscaler решает эту задачу автоматически.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: shop-api-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: shop-api
  minReplicas: 3
  maxReplicas: 15
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

Если средняя загрузка CPU превышает 70% — HPA увеличивает число реплик. Если падает — уменьшает. Так система адаптируется к нагрузке без ручного вмешательства.

Обновления без простоя

При обновлении версии приложения Kubernetes создаёт новые Pods и удаляет старые. Но если в этот момент допустить слишком много одновременных остановок — сервис станет недоступен.

PodDisruptionBudget задаёт минимальное число Pod, которые должны оставаться доступными.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: shop-api-pdb
  namespace: production
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: shop-api

Даже при обслуживании узлов или обновлениях Kubernetes не допустит падения сервиса ниже этого уровня.

Итог

Startup Probe позволяет безопасно запускаться. Readiness Probe управляет подачей трафика. Liveness Probe восстанавливает зависшие контейнеры.

Requests и limits защищают кластер от перегрузки. HPA автоматически масштабирует систему. PDB удерживает доступность при обновлениях.

Все эти механизмы работают вместе — как единая система самовосстановления.

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

Пробы дают системе понимание состояния приложений. Контроль ресурсов задаёт правила потребления. Масштабирование обеспечивает гибкость. Бюджеты доступности гарантируют устойчивость.

Именно поэтому Kubernetes стал стандартом для production-инфраструктуры.

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

+7 800 100 22 47

бесплатно по РФ

+7 495 085 21 62

бесплатно по Москве

108813 г. Москва, вн.тер.г. поселение Московский,
г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3
ОГРН 1217300010476
ИНН 7325174845