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

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

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • AI для кодаНовое
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • 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 обеспечивает безостановочный деплой.

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

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

    Комментарии

    0

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

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

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

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

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

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

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

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

    Angular

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

    Feature-Sliced Design

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

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

    Картинка поста Git флоу для команды разработчиков: гайд по веткам и релизам
    Иконка аватараАнтон
    Иконка календаря30 сентября 2026
    gitgit-flowкомандная работа+ 2middleИконка уровня middle

    Git флоу для команды разработчиков: гайд по веткам и релизам

    Git флоу для команды разработчиков: разбираем Git Flow, GitHub Flow и trunk-based development — как выбрать модель веток и избежать конфликтов при совместной работе.

    Иконка чипа0
    Иконка глаза92
    Иконка комментариев0
    Картинка поста Микросервисная архитектура для начинающих: гайд с примерами
    Иконка аватараАнтон
    Иконка календаря23 сентября 2026
    микросервисыархитектураbackend+ 2juniorИконка уровня junior

    Микросервисная архитектура для начинающих: гайд с примерами

    Микросервисная архитектура простыми словами: чем она отличается от монолита, какие есть плюсы и минусы, и как спроектировать первую систему на микросервисах — с примерами кода.

    Иконка чипа0
    Иконка глаза185
    Иконка комментариев0
    Иконка аватараАнтон
    Иконка календаря01 октября 2026
    AI-инструментыDevOpsразработка+ 2middleИконка уровня middle

    Gemini CLI в России: как установить и настроить

    Установить Gemini CLI из России можно без VPN и без ухищрений — это обычный npm-пакет, он скачивается и запускается на любой машине. Упирается всё на следующем шаге: 18 июня 2026 года Google перестал обслуживать запросы Gemini CLI для бесплатных аккаунтов и подписчиков Google AI Pro и Ultra, а единственный оставшийся путь — вход по API-ключу — требует биллинга в регионе, где Россия не числится. Ниже разбираем, как агент ставится, как устроены три способа входа, почему ни один из них не доводи...

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