Разумная автоматизация деплоя: как не потратить 6 часов на 30-секундную задачу
Пошаговый гайд по автоматизации деплоя с мониторингом. Узнайте, как автоматизировать процесс разумно — без избыточной сложности и с надёжным мониторингом.
Требования
- Базовые знания 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+ в неделю) или минимальной поддержке.