Відновлення вебсайту після збою
Відновлення — стресовий процес, який має бути спланований заздалегідь. Наявність runbook із чіткими кроками скорочує час відновлення в 3–5 разів у порівнянні з діагностикою на ходу.
Класифікація збоїв та перші дії
Сайт недоступний (HTTP 5xx або timeout):
# 1. Перевіряємо сервіс
systemctl status nginx php8.2-fpm
# 2. Перезавантажуємо якщо завис
sudo systemctl restart php8.2-fpm
sudo systemctl restart nginx
# 3. Дивимося логи
journalctl -u nginx -n 100 --no-pager
tail -100 /var/log/php8.2-fpm.log
Диск переповнений:
df -h # знаходимо заповнений розділ
du -sh /var/log/* | sort -rh | head -10 # де місце
# Очищення логів
truncate -s 0 /var/log/nginx/access.log
journalctl --vacuum-size=100M
# Очищення Docker
docker system prune -f
OOM (Out of Memory):
dmesg | grep -i "out of memory"
# Збільшуємо swap (тимчасове рішення)
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
База даних впала:
# PostgreSQL
sudo systemctl restart postgresql
# Перевіряємо логи
tail -50 /var/log/postgresql/postgresql-14-main.log
# Якщо пошкоджені файли — відновлення з резервної копії
Відновлення з резервної копії: крок за кроком
# 1. Визначаємо останню робочу резервну копію
aws s3 ls s3://my-backups/database/ | tail -5
# 2. Завантажуємо
aws s3 cp s3://my-backups/database/mysite_20241201_060000.dump.gz /tmp/
# 3. Створюємо нову БД (стару не чіпаємо — спочатку тестуємо)
createdb mysite_restored
gunzip < /tmp/mysite_20241201_060000.dump.gz | pg_restore -d mysite_restored --no-owner
# 4. Перевіряємо цілісність
psql -d mysite_restored -c "SELECT COUNT(*) FROM users;"
psql -d mysite_restored -c "SELECT MAX(created_at) FROM orders;"
# 5. Переключаємо програму на відновлену БД
# Змінюємо DB_NAME у .env
# Перезавантажуємо програму
# 6. Перейменовуємо БД (якщо підходить)
# ALTER DATABASE mysite RENAME TO mysite_broken;
# ALTER DATABASE mysite_restored RENAME TO mysite;
Відновлення файлів
# Відновлення uploads/ з S3
aws s3 sync s3://my-backups/files/ /var/www/mysite/storage/app/public/ \
--exact-timestamps
# Права після відновлення
chown -R www-data:www-data /var/www/mysite/storage/
chmod -R 755 /var/www/mysite/storage/
Відкат коду
# Через Git
git log --oneline -10 # знаходимо робочий коміт
git checkout <commit-hash>
# або
git revert <bad-commit>
# Через Docker (якщо використовується)
docker pull myregistry/myapp:previous-tag
docker stop myapp
docker run -d --name myapp myregistry/myapp:previous-tag
Шаблон Runbook
## Runbook: Відновлення після повного відмови
**Умова:** сайт недоступний більше 5 хвилин
### Крок 1: Діагностика (5 хв)
- [ ] `ssh deploy@server`
- [ ] `systemctl status nginx php-fpm mysql`
- [ ] `df -h` — перевірка диска
- [ ] `free -m` — перевірка пам'яті
### Крок 2: Швидке відновлення (5–10 хв)
- [ ] Перезавантаження сервісів
- [ ] Якщо не допомогло — відновлення з резервної копії (див. розділ вище)
### Крок 3: Сповіщення
- [ ] Slack: #incidents — статус інциденту
- [ ] Статус-сторінка — інцидент створений
### Крок 4: Post-mortem
- [ ] RCA протягом 24 годин після відновлення
Час відновлення з підготовленим runbook та актуальними резервними копіями: 30 хв – 2 години.







