Как обеспечить приложение перезапуском в Kubernetes?

Ответ

В Kubernetes основная ответственность за перезапуск контейнеров лежит на kubelet (на каждом узле) и контроллерах (например, Deployment). Вот как я настраиваю отказоустойчивость приложений.

1. Базовая политика перезапуска в Pod: В спецификации Pod можно задать restartPolicy для контейнеров. Для рабочих нагрузок всегда используется Always.

spec:
  containers:
  - name: app
    image: myapp:latest
  restartPolicy: Always

Однако, для долгоживущих приложений я редко описываю Pod'ы напрямую, а использую контроллеры.

2. Использование контроллеров для самовосстановления:

  • Deployment: Основной объект для stateless-приложений. Если Pod падает, ReplicaSet (часть Deployment) немедленно создаёт новый, чтобы поддерживать заданное количество реплик (replicas).
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: app-deployment
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: myapp
      template:
        spec:
          containers:
          - name: app
            image: myapp:stable

3. Пробы жизнеспособности (Liveness Probes): Ключевой механизм для обнаружения "зависших" приложений. Kubelet периодически выполняет проверку и перезапускает контейнер, если проба fails.

livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30 # Даём приложению время на старт
  periodSeconds: 10

4. Пробы готовности (Readiness Probes): Отличаются от liveness. Если проба готовности fails, Pod исключается из балансировщика нагрузки Service, но не перезапускается. Это позволяет контейнеру восстановиться без потери трафика.

5. Мониторинг и алертинг: Настраиваю Prometheus и Alertmanager для отслеживания частых перезапусков Pod'ов (метрика kube_pod_container_status_restarts_total). Частые рестарты — сигнал о проблеме в приложении или некорректных настройках проб.

Важно: Для stateful-приложений (StatefulSet) перезапуск контейнера в том же Pod'е обычно безопасен, так как том (volume) сохраняется. Полная гибель узла требует более сложных процедур восстановления, заложенных в логику самого Stateful-приложения.

Ответ 18+ 🔞

Давай разберём эту тему, а то тут некоторые думают, что кубер сам всё починит, как волшебная таблетка. Э сабака сука, нет, конечно.

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

1. Базовая настройка в самом Pod: restartPolicy В манифесте пода есть такая штука — политика перезапуска. Для нормальных сервисов всегда ставь Always. Но честно? Я редко когда пишу голые Pod'ы в продакшене, это как ходить по охуенно тонкому льду. Только для каких-нибудь одноразовых задач.

spec:
  containers:
  - name: app
    image: myapp:latest
  restartPolicy: Always # Вот это самое оно

2. Контроллеры — наше всё. Особенно Deployment. Вот где начинается магия. Ты создаёшь Deployment, а он за тебя создаёт ReplicaSet, который уже плодит поды. Если один под сдох, ReplicaSet тут же видит, что реплик стало меньше, и создаёт новый, чтобы достичь нужного числа. Автоматически, блядь! Красота.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 3  # Хочешь три копии приложения? Будет три, ёпта!
  selector:
    matchLabels:
          app: myapp
  template:
    spec:
          containers:
          - name: app
            image: myapp:stable

Вот это и есть основа отказоустойчивости. Упала одна реплика — остальные две работают, а третью уже поднимают.

3. Liveness Probe — чтобы убить зависшее приложение. А вот это, чувак, критически важная вещь. Без неё твоё приложение может лежать с пустыми глазами, не отвечать, но формально быть «живым». Kubelet будет тупо смотреть и ничего не делать. Нахуй так надо? Ты настраивае пробу (чаще всего HTTP запрос на /health), и если она начинает фейлиться, kubelet без лишних слов прибивает контейнер и запускает новый. Жестко, но эффективно.

livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30 # Даём время на старт, а то убьёт на взлёте!
  periodSeconds: 10

4. Readiness Probe — чтобы не совать трафик в сдохший под. Важно не путать с liveness! Если readiness проба падает, под НЕ ПЕРЕЗАПУСКАЕТСЯ. Его просто выкидывают из балансировки Service. Трафик на него перестаёт идти, и у него есть шанс прийти в себя без давления. Если не пришёл — тогда уже liveness его добьёт. Две эти пробы работают в паре, как хитрая жопа.

5. Мониторинг. Без него ты слепой. Настроил пробы, запустил деплоймент и расслабился? Какого хуя! Надо следить за метриками. Самая простая — kube_pod_container_status_restarts_total. Если видишь, что какой-то под перезапускается каждые пять минут — это пиздец, а не отказоустойчивость. Значит, проблема либо в кривом приложении, либо ты так настроил пробы, что они заебали здоровый сервис. Поднимаешь алерт в Alertmanager и идёшь разбираться.

И последнее, про StatefulSet. Для stateful-приложений (базы данных всякие) перезапуск контейнера в рамках одного пода — обычно ок, потому что том с данными остаётся. Но если вся нода легла, тут уже впендюрить новую ноду и примаунтить том — это история посерьёзнее, её надо в логике самого приложения прорабатывать.

Короче, суть в том, чтобы не надеяться на авось, а настроить эту связку: контроллеры + пробы + мониторинг. Тогда будет тебе и хиросима, и нигерсраки в одном флаконе, то есть отказоустойчивость.