Автоматическое восстановление: проектирование самовосстанавливающихся систем | AdminWiki

Автоматическое восстановление: проектирование самовосстанавливающихся систем

17 августа 2026 8 мин. чтения

Что такое самовосстанавливающиеся системы и зачем они нужны

Самовосстанавливающаяся система обнаруживает сбои и устраняет их без участия инженера. Ручное восстановление занимает часы: дежурный получает алерт, подключается к серверу, читает логи, перезапускает сервис. Автоматическое восстановление сокращает это время до минут, потому что healthcheck фиксирует отказ, а systemd или Kubernetes сразу выполняют перезапуск.

Практический эффект: сервис падает ночью, liveness probe в Kubernetes определяет неработающий контейнер и пересоздает под за 30 секунд. Инженер узнает об инциденте из утреннего отчета, а пользователи не заметили простоя. Нагрузка на дежурного администратора снижается, команда перестает тратить время на рутинные перезапуски.

Для системных администраторов и DevOps-инженеров это означает переход от реактивной работы к проактивной. Инфраструктура сама держит заданное состояние, а специалисты занимаются улучшением, а не тушением пожаров. Материал по автоматизации инфраструктуры для DevOps и сисадминов дополняет эту тему готовыми сценариями для Ansible и Bash.

Ключевые метрики деградации: как понять, что сервис скоро упадет

Деградация редко наступает мгновенно. Перед отказом сервис обычно показывает рост latency, увеличение ошибок или аномальное потребление памяти. Задача метрик - зафиксировать эти сигналы до того, как сервис станет недоступным.

Базовый набор метрик для любого сервиса: загрузка CPU, использование RAM, свободное место на дисках, количество ошибок 5xx, latency и throughput. Prometheus собирает эти данные по endpoint /metrics. Пороговые значения устанавливают на основе SLO: если latency выше 500 мс дольше 5 минут, запускается алерт или автоматическое масштабирование.

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

Начните с базовых метрик инфраструктуры, затем добавьте бизнес-показатели. Для веб-сервисов используйте RED-метод: Rate (запросы в секунду), Errors (доля ошибок), Duration (время обработки). Для фоновых воркеров важны глубина очереди и время обработки задачи. Для баз данных - количество соединений и время выполнения запросов.

Свяжите метрики с SLO/SLI. Если целевой уровень доступности 99.9%, допустимое время простоя в месяц - 43 минуты. Метрики должны предупреждать о приближении к этому порогу заранее, а не после его превышения. Пример: рост latency выше 500 мс запускает дополнительный инстанс через HPA, предотвращая перегрузку основного.

Настройка healthcheck-механизмов

Healthcheck - это проверка состояния сервиса. Она определяет, работает ли приложение, готово ли принимать трафик и не зависло ли оно. В Docker и Kubernetes healthcheck реализуется через команды или HTTP-запросы к специальным endpoint.

Healthcheck в Docker

Dockerfile поддерживает директиву HEALTHCHECK. Пример для веб-сервиса на FastAPI:

FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Параметры: interval - периодичность проверки, timeout - таймаут ответа, start-period - время на запуск приложения, retries - количество неудач до пометки unhealthy. Оркестраторы используют этот статус для перезапуска контейнера или исключения из балансировки.

Пробы в Kubernetes

Kubernetes использует три типа проб: livenessProbe, readinessProbe и startupProbe. Liveness проверяет, жив ли контейнер. Readiness определяет, готов ли под принимать трафик. StartupProbe защищает медленно стартующие приложения от преждевременного перезапуска.

YAML-манифест с пробами:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-server
  template:
    metadata:
      labels:
        app: api-server
    spec:
      containers:
      - name: api
        image: api-server:1.4.2
        ports:
        - containerPort: 8000
        startupProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 5
          periodSeconds: 5
          failureThreshold: 30
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 15
          periodSeconds: 10
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /ready
            port: 8000
          initialDelaySeconds: 5
          periodSeconds: 5
          failureThreshold: 3

initialDelaySeconds задает паузу перед первой проверкой, periodSeconds - интервал между проверками, failureThreshold - количество неудач до срабатывания. При провале liveness kubelet перезапускает контейнер. При провале readiness под исключается из Service до восстановления.

Автоматический перезапуск сервисов с systemd

systemd управляет сервисами на уровне операционной системы. Директивы Restart и RestartSec обеспечивают автоматический перезапуск упавшего процесса. WatchdogSec обнаруживает зависания, когда процесс жив, но не отвечает.

Пример unit-файла с автоматическим перезапуском

[Unit]
Description=Nginx web server
After=network.target

[Service]
Type=simple
ExecStart=/usr/sbin/nginx -g 'daemon off;'
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
StartLimitIntervalSec=60
StartLimitBurst=5
TimeoutStopSec=10

[Install]
WantedBy=multi-user.target

Restart=on-failure перезапускает сервис только при ненулевом коде выхода. RestartSec=5s задает паузу между попытками. StartLimitIntervalSec и StartLimitBurst ограничивают частоту перезапусков: если сервис упал 5 раз за 60 секунд, systemd прекращает попытки и помечает сервис как failed. Это защищает от бесконечного цикла перезапусков при критической ошибке конфигурации.

Использование Watchdog для обнаружения зависаний

Watchdog решает проблему зависшего процесса. Если приложение перестало отвечать, но не завершилось, обычный Restart не сработает. Директива WatchdogSec задает интервал, в течение которого приложение должно отправить сигнал через sd_notify:

[Service]
Type=notify
ExecStart=/usr/local/bin/my-app
WatchdogSec=30s
Restart=on-failure

Приложение должно вызывать sd_notify(0, "WATCHDOG=1") каждые 30 секунд. Если сигнал не пришел, systemd считает сервис зависшим и перезапускает его. Для Python используйте библиотеку systemd.daemon, для Go - пакет go-systemd.

Самовосстановление в Kubernetes

Kubernetes построен вокруг идеи желаемого состояния. Вы описываете, сколько реплик должно работать, а контроллеры поддерживают это состояние при сбоях.

ReplicaSet и контроллеры

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

Для stateful-приложений используйте StatefulSet: он сохраняет имена подов и порядок запуска, что важно для баз данных и систем хранения. Подробнее о самовосстановлении в Kubernetes читайте в отдельном материале по контроллерам и пробам.

Горизонтальное автомасштабирование (HPA)

HPA изменяет количество реплик на основе метрик. При росте CPU выше 70% HPA добавляет поды, при снижении - убирает. Пример конфигурации:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-server-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-server
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

HPA использует метрики из metrics-server или Prometheus Adapter. Кастомные метрики позволяют масштабироваться по бизнес-показателям: глубине очереди, количеству активных сессий, latency.

Мониторинг и алертинг для раннего обнаружения проблем

Мониторинг фиксирует состояние системы, алертинг уведомляет об отклонениях. Prometheus собирает метрики, Alertmanager обрабатывает правила и отправляет уведомления в Slack, email или Telegram.

Настройка Prometheus и Alertmanager

Базовая конфигурация prometheus.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100']
  - job_name: 'kubernetes-pods'
    kubernetes_sd_configs:
      - role: pod

rule_files:
  - '/etc/prometheus/alerts.yml'

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['localhost:9093']

node_exporter собирает метрики хоста, kube-state-metrics - метрики объектов Kubernetes. Alertmanager настраивается на отправку в Slack через webhook URL.

Создание правил алертов

Примеры правил в alerts.yml:

groups:
  - name: infrastructure
    rules:
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "CPU usage above 85% on {{ $labels.instance }}"
      - alert: ServiceDown
        expr: up == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Service {{ $labels.job }} is down"
      - alert: HighErrorRate
        expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Error rate above 5%"

Правило HighCPUUsage срабатывает при загрузке CPU выше 85% в течение 10 минут. ServiceDown фиксирует недоступность endpoint. HighErrorRate отслеживает долю ошибок 5xx. Тестируйте алерты через promtool test rules перед загрузкой в продакшен.

Продвинутые практики: cgroups, лимиты ресурсов и изоляция

cgroup v2 - механизм ядра Linux для управления ресурсами. Он предоставляет единую иерархию, безопасную делегацию поддеревьев и улучшенный учет памяти. Для использования cgroup v2 требуется ядро Linux 5.8 или новее и поддержка со стороны container runtime. Kubernetes автоматически определяет cgroup v2 и работает без дополнительной настройки.

Ограничение ресурсов в Docker и Kubernetes

Лимиты предотвращают деградацию соседних сервисов. Контейнер без лимита памяти может вызвать OOM-killer и уронить другие процессы на узле. Пример лимитов в Docker:

docker run -d \
  --memory=512m \
  --memory-swap=1g \
  --cpus=2 \
  --name api-server \
  api-server:1.4.2

В Kubernetes лимиты задаются в манифесте:

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

Requests гарантируют ресурсы, limits ограничивают максимальное потребление. Правильный расчет лимитов требует анализа реального потребления: заниженные limits приводят к OOM-kill, завышенные - к неэффективному использованию узлов.

Типичные ошибки и как их избежать

Первая ошибка - слишком агрессивные перезапуски. Если сервис падает каждые 10 секунд, а systemd перезапускает его мгновенно, вы получаете бесконечный цикл. Используйте StartLimitIntervalSec и failureThreshold для ограничения частоты попыток.

Вторая ошибка - отсутствие backoff. При перезапуске после сбоя сервису нужно время на восстановление. RestartSec=0 или periodSeconds=1 создают дополнительную нагрузку и маскируют корневую причину.

Третья ошибка - игнорирование метрик. Healthcheck на /health может возвращать 200 OK, пока приложение деградирует: медленно отвечает, копит ошибки, теряет данные. Добавляйте метрики latency и error rate, настраивайте алерты на них.

Четвертая ошибка - неправильные пробы. Liveness probe с коротким initialDelaySeconds перезапускает медленно стартующие приложения. Используйте startupProbe для приложений с долгой инициализацией.

Внедряйте самовосстановление постепенно: начните с одного сервиса, протестируйте поведение при искусственных сбоях, затем масштабируйте на остальные. Готовые скрипты для автоматизации резервного копирования и восстановления помогут построить тестовый стенд для проверки процедур.

Заключение: путь к надежной инфраструктуре

Самовосстанавливающаяся инфраструктура строится на четырех элементах: метрики деградации, healthcheck-механизмы, автоматический перезапуск и мониторинг с алертингом. Метрики показывают приближение сбоя, healthcheck фиксирует отказ, systemd или Kubernetes перезапускают сервис, Prometheus и Alertmanager уведомляют команду.

Начните с малого: добавьте liveness probe в один Deployment, настройте Restart=on-failure в одном unit-файле, подключите Prometheus к одному серверу. Через неделю вы увидите сокращение ручных операций. Через месяц - снижение времени простоя с часов до минут. Для размещения отказоустойчивой инфраструктуры подойдет Timeweb Cloud с поддержкой Kubernetes и гибким масштабированием ресурсов.

При диагностике сбоев на мероприятиях и в продакшене используйте чек-листы из руководства по типичным проблемам с инфраструктурным кодом. Для автоматизации рутинных задач - готовые скрипты Ansible, Terraform и Bash из практического гайда по автоматизации инфраструктуры.

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