PurpleSchool — курсы программирования онлайн
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развития
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • PurpleSchool — курсы программирования онлайн
    • AI для кодаНовое
    • Сообщество
    • PurpleПлюс
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    Graceful shutdown, health checks и zero-downtime deploy: чек-лист для продакшна

    Graceful shutdown, health checks и zero-downtime deploy: чек-лист для продакшна

    Аватар автора Graceful shutdown, health checks и zero-downtime deploy: чек-лист для продакшна

    Антон Ларичев

    Иконка календаря03 апреля 2026
    devopsnode.jsdockerseniorИконка уровня senior
    Картинка поста Graceful shutdown, health checks и zero-downtime deploy: чек-лист для продакшна

    Введение

    Graceful shutdown в Node.js — это механизм корректного завершения приложения, при котором ни один пользовательский запрос не теряется. В продакшне, где каждый потерянный запрос — это потенциально потерянный клиент, правильная реализация graceful shutdown критически важна. В сочетании с health checks и стратегией zero-downtime deploy вы получаете систему, которая обновляется без простоя.

    В этой статье разберём практический чек-лист: от обработки сигналов завершения до настройки readiness probe в Kubernetes. Все примеры — на Node.js с Docker и Kubernetes.

    Как реализовать graceful shutdown в Node.js

    При получении сигнала SIGTERM (который отправляет Docker или Kubernetes при остановке контейнера) приложение должно выполнить три действия: прекратить приём новых соединений, дождаться завершения текущих запросов и закрыть внешние подключения.

    import { createServer } from 'http';
    
    const server = createServer((req, res) => {
      // Обработка запроса
      res.writeHead(200);
      res.end('OK');
    });
    
    let isShuttingDown = false;
    
    // Обработчик graceful shutdown
    function shutdown(signal: string) {
      console.log(`Получен сигнал ${signal}, начинаем завершение...`);
      isShuttingDown = true;
    
      // Прекращаем приём новых соединений
      server.close(() => {
        console.log('Все соединения закрыты, завершаем процесс');
        process.exit(0);
      });
    
      // Принудительное завершение через таймаут
      setTimeout(() => {
        console.error('Таймаут graceful shutdown, принудительное завершение');
        process.exit(1);
      }, 10000);
    }
    
    process.on('SIGTERM', () => shutdown('SIGTERM'));
    process.on('SIGINT', () => shutdown('SIGINT'));
    
    server.listen(3000);
    

    Как закрыть соединения с базой данных и Redis при завершении

    Одного server.close() недостаточно. Нужно закрыть все внешние ресурсы — пулы соединений с базой данных, Redis-клиенты, очереди сообщений:

    import { Pool } from 'pg';
    import { createClient } from 'redis';
    
    const pgPool = new Pool({ connectionString: process.env.DATABASE_URL });
    const redis = createClient({ url: process.env.REDIS_URL });
    
    async function shutdown(signal: string) {
      console.log(`Получен ${signal}, начинаем drain...`);
      isShuttingDown = true;
    
      server.close(async () => {
        try {
          // Закрываем пул PostgreSQL
          await pgPool.end();
          console.log('PostgreSQL пул закрыт');
    
          // Закрываем Redis
          await redis.quit();
          console.log('Redis соединение закрыто');
    
          process.exit(0);
        } catch (err) {
          console.error('Ошибка при закрытии ресурсов:', err);
          process.exit(1);
        }
      });
    
      setTimeout(() => process.exit(1), 15000);
    }
    

    Настройка health checks для Docker и Kubernetes

    Health checks — это механизм, который сообщает оркестратору о состоянии приложения. В Kubernetes используются три типа проб: liveness probe, readiness probe и startup probe.

    Эндпоинт health check в приложении

    import express from 'express';
    
    const app = express();
    let isShuttingDown = false;
    let isReady = false;
    
    // Liveness — приложение живо
    app.get('/health/live', (req, res) => {
      res.status(200).json({ status: 'alive' });
    });
    
    // Readiness — приложение готово принимать трафик
    app.get('/health/ready', (req, res) => {
      if (isShuttingDown || !isReady) {
        return res.status(503).json({ status: 'not ready' });
      }
      res.status(200).json({ status: 'ready' });
    });
    
    // Отмечаем готовность после инициализации
    async function bootstrap() {
      await pgPool.connect(); // Проверяем соединение с БД
      await redis.connect();
      isReady = true;
      console.log('Приложение готово к приёму трафика');
    }
    

    Readiness probe в Kubernetes: как настроить правильно

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: api-server
    spec:
      replicas: 3
      template:
        spec:
          containers:
            - name: api
              image: myapp:latest
              ports:
                - containerPort: 3000
              livenessProbe:
                httpGet:
                  path: /health/live
                  port: 3000
                initialDelaySeconds: 5
                periodSeconds: 10
                failureThreshold: 3
              readinessProbe:
                httpGet:
                  path: /health/ready
                  port: 3000
                initialDelaySeconds: 3
                periodSeconds: 5
                failureThreshold: 2
              startupProbe:
                httpGet:
                  path: /health/live
                  port: 3000
                failureThreshold: 30
                periodSeconds: 2
          terminationGracePeriodSeconds: 30
    

    Ключевые параметры: readinessProbe с failureThreshold: 2 быстро выводит под из балансировки, а terminationGracePeriodSeconds задаёт максимальное время для graceful shutdown.

    Чек-лист zero-downtime deploy для продакшна

    Zero-downtime deploy — это стратегия обновления, при которой пользователи не замечают процесс деплоя. Вот полный чек-лист:

    Приложение

    1. Обрабатывает SIGTERM и выполняет graceful shutdown
    2. Отдаёт 503 на readiness probe при завершении
    3. Закрывает все соединения (БД, Redis, очереди)
    4. Имеет таймаут принудительного завершения
    5. Эндпоинты /health/live и /health/ready реализованы

    Docker

    FROM node:20-alpine
    
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci --only=production
    COPY dist/ ./dist/
    
    # Используем tini для корректной передачи сигналов
    RUN apk add --no-cache tini
    ENTRYPOINT ["/sbin/tini", "--"]
    
    HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
      CMD wget -qO- http://localhost:3000/health/live || exit 1
    
    CMD ["node", "dist/main.js"]
    

    Важный момент: без init-процесса (tini или --init в docker run) Node.js не получит SIGTERM, и контейнер будет убит через SIGKILL после таймаута.

    Kubernetes

    spec:
      strategy:
        type: RollingUpdate
        rollingUpdate:
          maxUnavailable: 0
          maxSurge: 1
      template:
        spec:
          containers:
            - name: api
              lifecycle:
                preStop:
                  exec:
                    command: ["sh", "-c", "sleep 5"]
    

    Параметр maxUnavailable: 0 гарантирует, что ни один под не будет удалён, пока новый не пройдёт readiness probe. А preStop hook с задержкой даёт время на распространение изменений в endpoint-ах кластера.

    Частые ошибки при настройке безостановочного деплоя

    Нет обработки SIGTERM. Приложение не слушает сигналы — контейнер убивается через SIGKILL через 30 секунд, все текущие запросы теряются.

    Liveness вместо readiness. Если использовать только liveness probe без readiness, Kubernetes не знает, готов ли под к трафику. Новый под начинает получать запросы до полной инициализации.

    Слишком короткий terminationGracePeriodSeconds. Если у вас есть длительные запросы (загрузка файлов, генерация отчётов), 30 секунд по умолчанию может не хватить. Увеличьте до 60-120 секунд.

    Отсутствие preStop hook. Без задержки перед завершением Kubernetes может отправлять трафик на под, который уже начал завершаться. Добавьте sleep 5 в preStop.

    Node.js как PID 1 в Docker. Без tini или --init Node.js запускается как PID 1 и не обрабатывает сигналы стандартным образом.

    Заключение

    Graceful shutdown, health checks и zero-downtime deploy — это три столпа надёжного продакшна. Реализация graceful shutdown в Node.js требует обработки SIGTERM, закрытия соединений и таймаута. Health checks через liveness и readiness probe дают оркестратору полную картину состояния приложения. А правильная стратегия rolling update с maxUnavailable: 0 и preStop hook обеспечивает безостановочный деплой.

    Используйте чек-лист из этой статьи перед каждым выводом сервиса в продакшн — это сэкономит часы отладки и предотвратит потерю пользовательских запросов.

    Иконка глаза270

    Комментарии

    0

    Постройте личный план изучения Nuxt - fullstack Vue фреймворк до уровня Middle — бесплатно!

    Nuxt - fullstack Vue фреймворк — часть карты развития Frontend

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Основы разработки

    Антон Ларичев
    Гарантия
    Бонусы
    иконка звёздочки рейтинга5.0
    бесплатно
    Подробнее
    изображение курса

    Angular

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Гарантия
    Бонусы
    иконка звёздочки рейтинга5.0
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Feature-Sliced Design

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.5
    3 999 ₽ 6 990 ₽
    Подробнее

    Похожие статьи

    Картинка поста Redis на практике: кеширование, очереди и pub/sub для вашего бэкенда
    Иконка аватараАнтон
    Иконка календаря20 апреля 2026
    nodejsdockerapimiddleИконка уровня middle

    Redis на практике: кеширование, очереди и pub/sub для вашего бэкенда

    Redis на практике: разбираем кеширование с TTL и инвалидацией, очереди сообщений через BullMQ и pub/sub для уведомлений в реальном времени. Готовые примеры на Node.js и TypeScript.

    Иконка чипа0
    Иконка глаза423
    Иконка комментариев0
    Картинка поста Как AI меняет code review: инструменты и практики для команды
    Иконка аватараАнтон
    Иконка календаря18 апреля 2026
    aidevopstestingmiddleИконка уровня middle

    Как AI меняет code review: инструменты и практики для команды

    AI code review в 2026 году сокращает время проверки кода на 40-60%. Разбираем лучшие инструменты — CodeRabbit, PR-Agent, Claude Code Review — и пошаговый план внедрения в команде.

    Иконка чипа0
    Иконка глаза465
    Иконка комментариев0
    Картинка поста PostgreSQL для начинающих: создаём базу и пишем первые запросы
    Иконка аватараАнтон
    Иконка календаря20 мая 2026
    PostgreSQLSQLБазы данныхjuniorИконка уровня junior

    PostgreSQL для начинающих: создаём базу и пишем первые запросы

    PostgreSQL для начинающих: пошаговое руководство по созданию базы данных, таблиц и написанию первых SQL-запросов с примерами.

    Иконка чипа0
    Иконка глаза8
    Иконка комментариев0
    Иконка чипа0