پرش به محتویات

۲۰. راهنماهای عملیاتی زیرساخت (Runbook)

این چک‌لیست‌ها برای شروع بررسی هستند، نه اجرای کورکورانه تغییرات. در رخدادهای تولیدی ابتدا محدوده اثر و شواهد را ثبت کنید و برای تغییرات پرریسک، تأیید و روش بازگشت داشته باشید.

هر runbook همین قالب را دارد: نشانه ← بررسی اولیه ← رفع ← تأیید ← بازگشت ← ارجاع. قالب خالی: templates/RUNBOOK-TEMPLATE.md.

قبل از هر چیز

sudo ./scripts/incident-snapshot.sh را اجرا کنید تا حالت قبل از تغییر ثبت شود.

۱. سرویس Nginx یا وب‌سایت پاسخ نمی‌دهد

نشانه: timeout/۵xx/اتصال رد شد از بیرون.

بررسی اولیه

sudo nginx -t
systemctl status nginx --no-pager
sudo journalctl -u nginx -b -n 150 --no-pager
sudo ss -lntp | grep -E ':(80|443)\b'
curl -sS -D- -o /dev/null http://127.0.0.1/
  • اگر nginx -t ناموفق است، خروجی خطا و فایل/خط را ثبت کنید؛ پیش از اصلاح، نسخه پشتیبان فایل را بگیرید.
  • اگر پورت شنود نمی‌شود، وضعیت سرویس و تداخل پورت را بررسی کنید.
  • اگر پاسخ محلی درست ولی پاسخ بیرونی ناموفق است، DNS، فایروال، Load Balancer و مسیر شبکه را جداگانه بررسی کنید.
  • اگر 502/504: backend را بررسی کنید (curl مستقیم به upstream، لاگ برنامه) (وب).

رفع و تأیید: پس از تغییر: sudo nginx -t و سپس Reload کنترل‌شده؛ در پایان درخواست واقعی را از مسیر کلاینت آزمایش کنید.
بازگشت: فایل پیکربندی قبلی را برگردانید، nginx -t ، reload.

۲. فضای دیسک یا inode رو به اتمام است

df -hT
df -ih
sudo du -xhd1 /var 2>/dev/null | sort -h
sudo journalctl --disk-usage
sudo lsof +L1
  • تشخیص دهید کدام filesystem پر است؛ خروجی du فقط همان mount را پوشش نمی‌دهد مگر مسیر و گزینه‌ها درست انتخاب شده باشند.
  • فایل‌های دیتابیس، فایل‌های بازشده، و لاگ‌های موردنیاز ممیزی را بدون بررسی حذف نکنید.
  • پاک‌سازی را با سیاست نگهداری سازمان و برنامه بازیابی هماهنگ کنید.
  • پس از اقدام، df -hT و سرویس‌های وابسته را دوباره بررسی کنید.
  • علت تکرار را رفع کنید (لاگ بدون چرخش، کانتینر، بکاپ محلی انباشته) و هشدار ۸۰٪ بگذارید.

۳. کانتینر Docker بالا نمی‌آید یا دائماً Restart می‌شود

docker compose ps
docker compose logs --tail=200 SERVICE
docker inspect CONTAINER --format '{{.State.Status}} {{.State.ExitCode}} {{.State.OOMKilled}} {{.State.Error}}'
docker system df
  • ابتدا علت خروج، متغیرهای محیطی، اتصال شبکه، وابستگی‌ها و مجوز Volume را بررسی کنید. کد 137 = OOM/KILL (Docker).
  • پیش از down -v، حذف Volume یا اجرای prune، اثر آن بر داده‌های پایدار را مشخص کنید.
  • پس از اصلاح، وضعیت کانتینر، Healthcheck، لاگ برنامه و دسترسی واقعی به سرویس را تأیید کنید.

۴. DNS یا TLS مشکل دارد

getent hosts example.com
resolvectl status 2>/dev/null || cat /etc/resolv.conf
curl -Iv https://example.com
openssl s_client -connect example.com:443 -servername example.com </dev/null
  • خطای Resolve را از خطای اتصال TCP و خطای اعتبار گواهی جدا کنید.
  • تاریخ/ساعت سیستم، زنجیره گواهی، نام دامنه (SAN)، انقضا و SNI را بررسی کنید.
  • غیرفعال‌کردن اعتبارسنجی TLS راه‌حل دائمی نیست و می‌تواند ارتباط را ناامن کند.
  • گواهی تمدیدشده ولی وب‌سرور reload نشده؟ گواهی را از روی سرویس بخوانید (نه فایل).

۵. SSH یا دسترسی راه دور قطع شده است

systemctl status ssh --no-pager || systemctl status sshd --no-pager
sudo sshd -t
sudo ss -lntp | grep ssh
sudo journalctl -u ssh -b -n 150 --no-pager
  • در بعضی توزیع‌ها نام سرویس ssh و در بعضی sshd است.
  • پیش از تغییر Firewall یا sshd_config، یک نشست فعال یا کنسول خارج از باند را حفظ کنید.
  • پس از تغییر، پیکربندی را با sshd -t بررسی و اتصال جدید را در یک نشست جداگانه آزمایش کنید؛ نشست فعلی را زود نبندید.
  • اگر از بیرون قفل شده‌اید (کنسول لازم): sudo ufw status / nft list ruleset (قانون SSH)، sshd -T | grep -E 'permitroot|passwordauth|allowusers' ، ls -ld ~ ~/.ssh ~/.ssh/authorized_keys (مجوزها)، sudo fail2ban-client status sshd (بن‌شدن)، getent passwd USER ، chage -l USER (قفل/انقضا).

۶. حافظه تمام شده / OOM

free -h
sudo dmesg -T | grep -iE 'out of memory|killed process' | tail
ps -eo pid,user,comm,rss --sort=-rss | head
systemctl show SERVICE -p MemoryMax -p MemoryCurrent
  • پردازش پرمصرف را شناسایی کنید؛ ریستارت سرویس نشتی راه موقت است (قبلش pmap -x PID | tail -1 و ثبت RSS).
  • بررسی کنید سقف cgroup/کانتینر بیش از حد کم نیست.
  • افزودن swap کوتاه‌مدت؛ دائمی: رفع نشت/افزایش RAM.
  • هشدار برای MemAvailable پایین بگذارید.

۷. دیتابیس پاسخ نمی‌دهد

systemctl status postgresql --no-pager        # یا mysql / mariadb
sudo journalctl -u postgresql -b -n 100 --no-pager
pg_isready                                    # PostgreSQL
mysqladmin ping                               # MySQL/MariaDB
df -hT /var/lib/postgresql /var/lib/mysql 2>/dev/null
sudo -u postgres psql -c "select count(*) from pg_stat_activity;"
  • دیسک پر رایج‌ترین دلیل توقف است (WAL/binlog)؛ قبل از هر کار فضا را بررسی کنید.
  • «too many connections»: connection pooler، نشت اتصال در برنامه، max_connections.
  • فایل‌های داده را هرگز دستی حذف/جابه‌جا نکنید؛ بازیابی از بکاپ/ریپلیکا طبق روش خود DB.
  • پس از بازگشت، سلامت داده و تأخیر ریپلیکا را بررسی کنید.

۸. دیسک/RAID خراب یا degrade

cat /proc/mdstat
sudo mdadm --detail /dev/md0
sudo smartctl -H /dev/sdX
sudo dmesg -T | grep -iE 'I/O error|ata[0-9]|medium error' | tail
  • اول بکاپ تأییدشده، بعد تعویض. RAID5/6 هنگام rebuild آسیب‌پذیر است؛ بار را کم کنید.
  • دیسک خراب را با سریال شناسایی کنید (lsblk -o NAME,SERIAL)، نه فقط /dev/sdX.
  • mdadm --manage /dev/md0 --fail/--remove/--add فقط پس از اطمینان از دیسک درست.
  • بعد از rebuild: cat /proc/mdstat و scrub.

۹. ساعت/NTP اشتباه

timedatectl
chronyc tracking
chronyc sources -v
  • منبع زمان قابل‌دسترس است؟ (فایروال UDP 123)
  • اختلاف بزرگ: sudo chronyc makestep (پرش ساعت؛ روی سرویس‌های حساس به زمان با احتیاط).
  • در VM: از دوگانگی همگام‌سازی hypervisor و NTP پرهیز کنید.

۱۰. پایان رخداد و ثبت گزارش

  • زمان شروع، زمان کشف و محدوده کاربران/سرویس‌های تحت تأثیر ثبت شد.
  • شواهد اولیه شامل status، لاگ‌ها، منابع و آخرین تغییرات ذخیره شد.
  • اقدام اصلاحی و دلیل انتخاب آن ثبت شد.
  • آزمون عملکردی از دید کاربر انجام شد.
  • روش بازگشت و وضعیت پشتیبان مشخص است.
  • علت ریشه‌ای، اقدام پیشگیرانه، مالک و مهلت پیگیری تعیین شد.
  • هشدار مانیتورینگ برای تشخیص زودتر اضافه شد.

قالب گزارش: templates/INCIDENT-TEMPLATE.md.