Разумная автоматизация деплоя: как не потратить 6 часов на 30-секундную задачу

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

Средний
Алексей Кузнецов
Алексей Кузнецов
Системный администратор9 июня 2026 г.5 мин чтения

Требования

  • Базовые знания Linux и командной строки
  • Установленный Git
  • Доступ к серверу для деплоя (SSH)
  • Базовое понимание CI/CD

Шаг 1. Оцените задачу перед автоматизацией

Прежде чем писать скрипт, задайте себе три вопроса: как часто выполняется задача? Сколько времени занимает ручное выполнение? Какова стоимость ошибки? Если задача выполняется реже раза в неделю и занимает меньше минуты — автоматизация, скорее всего, не окупится. Запишите текущий ручной процесс пошагово — это станет основой для скрипта.

# Пример: фиксируем текущий ручной процесс
# 1. Подключаемся к серверу
ssh user@production-server

# 2. Переходим в директорию проекта
cd /var/www/myapp

# 3. Пуллим изменения
git pull origin main

# 4. Устанавливаем зависимости
npm install --production

# 5. Перезапускаем приложение
pm2 restart myapp

Шаг 2. Напишите минимальный скрипт деплоя

Создайте простой bash-скрипт, который повторяет ручные шаги. Не усложняйте — на этом этапе цель заменить ручные команды на один вызов. Добавьте базовую обработку ошибок: если команда завершилась с ошибкой, скрипт должен остановиться и сообщить об этом.

#!/usr/bin/env bash
set -euo pipefail

# deploy.sh — минимальный скрипт деплоя

APP_DIR="/var/www/myapp"
APP_NAME="myapp"

echo "🚀 Начинаем деплой..."

cd "$APP_DIR"

echo "📥 Получаем последние изменения..."
git pull origin main

echo "📦 Устанавливаем зависимости..."
npm install --production

echo "🔄 Перезапускаем приложение..."
pm2 restart "$APP_NAME"

echo "✅ Деплой завершён успешно!"

Шаг 3. Добавьте проверку работоспособности (health check)

После деплоя нужно убедиться, что приложение работает. Добавьте health check — запрос к эндпоинту или проверку процесса. Если проверка не прошла — откатитесь к предыдущей версии. Это критически важно: без проверки вы не узнаете о проблеме, пока пользователи не начнут жаловаться.

#!/usr/bin/env bash
set -euo pipefail

APP_DIR="/var/www/myapp"
APP_NAME="myapp"
HEALTH_URL="http://localhost:3000/health"
MAX_RETRIES=5
RETRY_DELAY=3

# Сохраняем текущий коммит для возможного отката
CURRENT_COMMIT=$(git rev-parse HEAD)

deploy() {
  cd "$APP_DIR"
  git pull origin main
  npm install --production
  pm2 restart "$APP_NAME"
}

check_health() {
  local retries=0
  while [ $retries -lt $MAX_RETRIES ]; do
    if curl -sf "$HEALTH_URL" > /dev/null 2>&1; then
      return 0
    fi
    retries=$((retries + 1))
    echo "⏳ Ожидание готовности... (попытка $retries/$MAX_RETRIES)"
    sleep "$RETRY_DELAY"
  done
  return 1
}

rollback() {
  echo "⚠️  Health check не пройден. Откатываемся..."
  cd "$APP_DIR"
  git reset --hard "$CURRENT_COMMIT"
  npm install --production
  pm2 restart "$APP_NAME"
  echo "↩️  Откат к $CURRENT_COMMIT выполнен"
}

echo "🚀 Начинаем деплой..."
deploy

if check_health; then
  echo "✅ Деплой успешен, приложение работает"
else
  rollback
  exit 1
fi

Шаг 4. Настройте мониторинг без избыточности

Теперь добавьте мониторинг. Главное правило — не плодите инструменты. Один инструмент для метрик (Prometheus), один для алертов (Alertmanager), один для визуализации (Grafana). Три инструмента — это максимум для старта. Если ваша автоматизация требует пяти мониторинговых систем — вы пошли не тем путём.

# docker-compose.yml — минимальный стек мониторинга
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml

  alertmanager:
    image: prom/alertmanager:latest
    ports:
      - "9093:9093"
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3001:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=secret

  node-exporter:
    image: prom/node-exporter:latest
    ports:
      - "9100:9100"

Шаг 5. Настройте алерты на сбои деплоя

Создайте правила алертинга для ключевых метрик: время отклика, количество ошибок 5xx, использование CPU и памяти. Алерты должны приходить в один канал (Telegram, Slack или email) — не распыляйтесь на пять каналов одновременно. Настройте пороги так, чтобы не получать шум при штатных колебаниях.

# prometheus.yml — конфигурация с правилами алертов

rule_files:
  - "alerts.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets: ["alertmanager:9093"]

scrape_configs:
  - job_name: 'myapp'
    static_configs:
      - targets: ['localhost:3000']
    metrics_path: '/metrics'

  - job_name: 'node'
    static_configs:
      - targets: ['node-exporter:9100']

# alerts.yml — правила алертов
groups:
  - name: deployment
    rules:
      - alert: HighErrorRate
        expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Высокий уровень ошибок 5xx"

      - alert: HighResponseTime
        expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 2
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "95-й перцентиль времени отклика > 2 сек"

Шаг 6. Запустите деплой через CI/CD

Перенесите скрипт деплоя в CI/CD-пайплайн. Это избавит от необходимости запускать деплой вручную и добавит логирование каждого запуска. Используйте GitHub Actions, GitLab CI или любой другой привычный инструмент. Пайплайн должен: прогонять тесты, деплоить на staging, ждать подтверждения, деплоить на production.

# .github/workflows/deploy.yml

name: Deploy

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to production
        run: |
          ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} \
            "cd /var/www/myapp && git pull origin main && npm install --production && pm2 restart myapp"

      - name: Health check
        run: |
          for i in $(seq 1 10); do
            if curl -sf "${{ secrets.APP_URL }}/health"; then
              echo "✅ Приложение работает"
              exit 0
            fi
            sleep 5
          done
          echo "❌ Health check не пройден"
          exit 1

Шаг 7. Проведите ретроспективу автоматизации

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

# Чек-лист ретроспективы

## Метрики для оценки

# 1. Время деплоя (до и после)
echo "До автоматизации: 30 сек (ручной)"
echo "После автоматизации: 45 сек (включая health check)"

# 2. Время на поддержку
echo "Время на написание: 2 часа"
echo "Время на поддержку за неделю: 15 минут"

# 3. Надёжность
echo "Успешных деплоев: 12/12"
echo "Ложных алертов: 2"

# 4. Формула окупаемости
# savings = (manual_time * deployments_per_week * weeks) - automation_time
# savings = (0,5 * 5 * 52) - 120 = 130 - 120 = 10 минут экономии в год
# Вывод: для 5 деплоев в неделю автоматизация окупается за год

Разумная автоматизация деплоя: когда оно того стоит

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

Предварительные требования

  • Базовые знания Linux и командной строки
  • Установленный Git
  • Доступ к серверу для деплоя (SSH)
  • Базовое понимание CI/CD

Шаг 1. Оцените задачу перед автоматизацией

Прежде чем писать скрипт, задайте себе три вопроса: как часто выполняется задача? Сколько времени занимает ручное выполнение? Какова стоимость ошибки? Если задача выполняется реже раза в неделю и занимает меньше минуты — автоматизация, скорее всего, не окупится. Запишите текущий ручной процесс пошагово — это станет основой для скрипта.

# Пример: фиксируем текущий ручной процесс
# 1. Подключаемся к серверу
ssh user@production-server

# 2. Переходим в директорию проекта
cd /var/www/myapp

# 3. Пуллим изменения
git pull origin main

# 4. Устанавливаем зависимости
npm install --production

# 5. Перезапускаем приложение
pm2 restart myapp

Шаг 2. Напишите минимальный скрипт деплоя

Создайте простой bash-скрипт, который повторяет ручные шаги. Не усложняйте — на этом этапе цель заменить ручные команды на один вызов. Добавьте базовую обработку ошибок: если команда завершилась с ошибкой, скрипт должен остановиться и сообщить об этом.

#!/usr/bin/env bash
set -euo pipefail

# deploy.sh — минимальный скрипт деплоя

APP_DIR="/var/www/myapp"
APP_NAME="myapp"

echo "🚀 Начинаем деплой..."

cd "$APP_DIR"

echo "📥 Получаем последние изменения..."
git pull origin main

echo "📦 Устанавливаем зависимости..."
npm install --production

echo "🔄 Перезапускаем приложение..."
pm2 restart "$APP_NAME"

echo "✅ Деплой завершён успешно!"

Шаг 3. Добавьте проверку работоспособности (health check)

После деплоя нужно убедиться, что приложение работает. Добавьте health check — запрос к эндпоинту или проверку процесса. Если проверка не прошла, нужно откатиться к предыдущей версии. Это критически важно: без проверки вы не узнаете о проблеме, пока пользователи не начнут жаловаться.

#!/usr/bin/env bash
set -euo pipefail

APP_DIR="/var/www/myapp"
APP_NAME="myapp"
HEALTH_URL="http://localhost:3000/health"
MAX_RETRIES=5
RETRY_DELAY=3

# Сохраняем текущий коммит для возможного отката
CURRENT_COMMIT=$(git rev-parse HEAD)

deploy() {
  cd "$APP_DIR"
  git pull origin main
  npm install --production
  pm2 restart "$APP_NAME"
}

check_health() {
  local retries=0
  while [ $retries -lt $MAX_RETRIES ]; do
    if curl -sf "$HEALTH_URL" > /dev/null 2>&1; then
      return 0
    fi
    retries=$((retries + 1))
    echo "⏳ Ожидание готовности... (попытка $retries/$MAX_RETRIES)"
    sleep "$RETRY_DELAY"
  done
  return 1
}

rollback() {
  echo "⚠️  Health check не пройден. Откатываемся..."
  cd "$APP_DIR"
  git reset --hard "$CURRENT_COMMIT"
  npm install --production
  pm2 restart "$APP_NAME"
  echo "↩️  Откат к $CURRENT_COMMIT выполнен"
}

echo "🚀 Начинаем деплой..."
deploy

if check_health; then
  echo "✅ Деплой успешен, приложение работает"
else
  rollback
  exit 1
fi

Шаг 4. Настройте мониторинг без избыточности

Теперь добавьте мониторинг. Главное правило — не плодите инструменты. Один для метрик (Prometheus), один для алертов (Alertmanager), один для визуализации (Grafana) и один для сбора метрик сервера (node-exporter). Этого набора достаточно для старта. Если ваша автоматизация требует пяти мониторинговых систем — вы пошли не тем путём.

# docker-compose.yml — минимальный стек мониторинга
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml

  alertmanager:
    image: prom/alertmanager:latest
    ports:
      - "9093:9093"
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3001:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=secret

  node-exporter:
    image: prom/node-exporter:latest
    ports:
      - "9100:9100"

Шаг 5. Настройте алерты для обнаружения сбоев при деплое

Создайте правила алертинга для ключевых метрик: время отклика, количество ошибок 5xx, использование CPU и памяти. Алерты должны приходить в один канал (Telegram, Slack или email) — не распыляйтесь на пять каналов одновременно. Настройте пороги так, чтобы не получать шум при штатных колебаниях.

# prometheus.yml — конфигурация с правилами алертов

rule_files:
  - "alerts.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets: ["alertmanager:9093"]

scrape_configs:
  - job_name: 'myapp'
    static_configs:
      - targets: ['localhost:3000']
    metrics_path: '/metrics'

  - job_name: 'node'
    static_configs:
      - targets: ['node-exporter:9100']

# alerts.yml — правила алертов
groups:
  - name: deployment
    rules:
      - alert: HighErrorRate
        expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Высокий уровень ошибок 5xx"

      - alert: HighResponseTime
        expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 2
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "95-й перцентиль времени отклика > 2 с"

Шаг 6. Запустите деплой через CI/CD

Перенесите скрипт деплоя в CI/CD-пайплайн. Это избавит от необходимости запускать деплой вручную и добавит логирование каждого запуска. Используйте GitHub Actions, GitLab CI или любой другой привычный инструмент. Пайплайн должен прогонять тесты и деплоить на production с обязательной проверкой работоспособности.

# .github/workflows/deploy.yml

name: Deploy

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to production
        run: |
          ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} \
            "cd /var/www/myapp && git pull origin main && npm install --production && pm2 restart myapp"

      - name: Health check
        run: |
          for i in $(seq 1 10); do
            if curl -sf "${{ secrets.APP_URL }}/health"; then
              echo "✅ Приложение работает"
              exit 0
            fi
            sleep 5
          done
          echo "❌ Health check не пройден"
          exit 1

Шаг 7. Проведите ретроспективу автоматизации

После первой недели использования оцените результат. Задайте себе вопросы: сколько времени сэкономили? Сколько времени потратили на поддержку автоматизации? Сколько ложных срабатываний алертов было? Если на поддержку уходит больше времени, чем экономит автоматизация, упростите решение. Помните: лучшая автоматизация — та, которую не нужно чинить каждый день.

# Чек-лист ретроспективы

## Метрики для оценки

# 1. Время деплоя (до и после)
echo "До автоматизации: 30 с (ручной)"
echo "После автоматизации: 45 с (включая health check)"

# 2. Время на поддержку
echo "Время на написание: 2 часа = 120 мин"
echo "Время на поддержку за год: ~15 мин × 52 недели = 780 мин"

# 3. Надёжность
echo "Успешных деплоев: 12/12"
echo "Ложных алертов: 2"

# 4. Формула окупаемости (все значения в минутах)
# Экономия за год = (время на ручной деплой × количество деплоев в неделю × 52) − (время на написание + время на поддержку за год)
# Экономия = (0,5 × 5 × 52) − (120 + 780) = 130 − 900 = −770 мин
# Вывод: при 5 деплоях в неделю и 15 мин поддержки в неделю автоматизация не окупается.
# Но если поддержка занимает 5 мин в неделю:
# Экономия = (0,5 × 5 × 52) − (120 + 260) = 130 − 380 = −250 мин — всё ещё не окупается.
# Автоматизация окупается только при частых деплоях (15+ в неделю) или минимальной поддержке.
Поделиться:TelegramX / TwitterVK