Files
goodgo-platform/docs/backup-restore.md
Ho Ngoc Hai 11f2bf26e6
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
chore: update project documentation, audit reports, and initialize IDE configuration files
2026-04-19 03:12:54 +07:00

251 lines
8.1 KiB
Markdown

# Sao Lưu & Khôi Phục Thảm Họa
## Mục Tiêu RTO / RPO
| Chỉ số | Mục tiêu | Ghi chú |
|--------|----------|---------|
| **RPO** (Mục tiêu Điểm Khôi phục) | ≤ 24 giờ | Sao lưu hàng ngày lúc 02:00 UTC; trường hợp xấu nhất là mất toàn bộ dữ liệu trong một ngày |
| **RTO** (Mục tiêu Thời gian Khôi phục) | ≤ 30 phút | Khôi phục từ bản sao lưu volume cục bộ; lâu hơn nếu lấy từ nơi lưu trữ ngoài site |
> Để giảm RPO hơn nữa, hãy xem xét lưu trữ WAL cho PostgreSQL (khôi phục liên tục theo thời gian thực) và lên lịch sao lưu thường xuyên hơn.
---
## Sao Lưu PostgreSQL
### Tổng quan
Sao lưu PostgreSQL tự động hàng ngày chạy bên trong Docker container `pg-backup` bằng `pg_dump` với nén định dạng tùy chỉnh. Các bản sao lưu được lưu trữ trong Docker volume `pg_backups`.
## Cấu Hình Sao Lưu
| Thiết lập | Mặc định | Biến môi trường |
|-----------|---------|----------------|
| Lịch | Hàng ngày lúc 02:00 UTC | Cron trong service `pg-backup` |
| Thời gian lưu | 7 ngày | `BACKUP_RETENTION_DAYS` |
| Định dạng | Tùy chỉnh (`pg_dump --format=custom`) | — |
| Nén | Mức 6 | — |
| Lưu trữ | Docker volume `pg_backups` | — |
## Liệt Kê Các Bản Sao Lưu
```bash
docker exec goodgo-pg-backup ls -lh /backups/
```
## Sao Lưu Thủ Công
```bash
docker exec goodgo-pg-backup /scripts/pg-backup.sh
```
## Quy Trình Khôi Phục
### 1. Xác định bản sao lưu cần khôi phục
```bash
docker exec goodgo-pg-backup ls -lht /backups/
```
### 2. Dừng các service ứng dụng
```bash
docker compose stop ai-services
# Stop any NestJS API processes
```
### 3. Chạy lệnh khôi phục
```bash
docker exec -it goodgo-pg-backup /scripts/pg-restore.sh /backups/goodgo_YYYYMMDD_HHMMSS.sql.gz
```
Script khôi phục sẽ:
- Chấm dứt các kết nối cơ sở dữ liệu đang hoạt động
- Xóa và tạo lại cơ sở dữ liệu
- Khôi phục từ bản sao lưu đã chọn
### 4. Xác minh khôi phục
```bash
docker exec goodgo-postgres psql -U goodgo -d goodgo -c '\dt'
docker exec goodgo-postgres psql -U goodgo -d goodgo -c 'SELECT count(*) FROM "User";'
```
### 5. Chạy migration Prisma (nếu cần)
```bash
pnpm prisma migrate deploy
```
### 6. Khởi động lại các service
```bash
docker compose up -d
```
## Xác Minh Bản Sao Lưu
Kiểm tra log sao lưu:
```bash
docker exec goodgo-pg-backup cat /var/log/pg-backup.log
```
Xác minh tính toàn vẹn của bản sao lưu mà không cần khôi phục:
```bash
docker exec goodgo-pg-backup pg_restore --list /backups/goodgo_YYYYMMDD_HHMMSS.sql.gz
```
---
## Sao Lưu & Khôi Phục Redis
Redis được cấu hình với tính năng bền vững AOF (`--appendonly yes`). Dữ liệu được lưu trong Docker volume `redis_data`.
### Snapshot Thủ Công
```bash
# Trigger an RDB snapshot
docker exec goodgo-redis redis-cli -a "$REDIS_PASSWORD" BGSAVE
# Wait for completion
docker exec goodgo-redis redis-cli -a "$REDIS_PASSWORD" LASTSAVE
```
### Sao Lưu Volume
```bash
# Stop Redis to ensure consistent snapshot
docker compose stop redis
# Copy volume data to a backup location
docker run --rm -v goodgo-platform-ai_redis_data:/data -v $(pwd)/backups:/backup \
alpine tar czf /backup/redis_$(date +%Y%m%d_%H%M%S).tar.gz -C /data .
docker compose start redis
```
### Khôi Phục Redis
```bash
docker compose stop redis
# Clear existing data and restore
docker run --rm -v goodgo-platform-ai_redis_data:/data -v $(pwd)/backups:/backup \
alpine sh -c "rm -rf /data/* && tar xzf /backup/redis_YYYYMMDD_HHMMSS.tar.gz -C /data"
docker compose start redis
```
> **Lưu ý:** Redis được dùng làm cache với chính sách loại bỏ `allkeys-lru`. Mất toàn bộ dữ liệu không nghiêm trọng — API sẽ tự động nạp lại các mục cache theo yêu cầu. Việc khôi phục chỉ cần thiết khi dữ liệu phiên hoặc trạng thái hàng đợi phải được giữ nguyên.
---
## Sao Lưu & Khôi Phục Typesense
Dữ liệu Typesense được lưu trữ trong Docker volume `typesense_data`.
### Tạo Snapshot
```bash
# Typesense built-in snapshot API
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
"http://localhost:8108/operations/snapshot?snapshot_path=/data/snapshots/$(date +%Y%m%d)"
```
### Sao Lưu Volume
```bash
docker compose stop typesense
docker run --rm -v goodgo-platform-ai_typesense_data:/data -v $(pwd)/backups:/backup \
alpine tar czf /backup/typesense_$(date +%Y%m%d_%H%M%S).tar.gz -C /data .
docker compose start typesense
```
### Khôi Phục Typesense
```bash
docker compose stop typesense
docker run --rm -v goodgo-platform-ai_typesense_data:/data -v $(pwd)/backups:/backup \
alpine sh -c "rm -rf /data/* && tar xzf /backup/typesense_YYYYMMDD_HHMMSS.tar.gz -C /data"
docker compose start typesense
```
### Xây Dựng Lại Từ Nguồn
Nếu bản sao lưu không có sẵn, Typesense có thể được xây dựng lại bằng cách lập chỉ mục lại từ PostgreSQL:
```bash
# After Typesense restarts with empty data:
pnpm run typesense:reindex
```
---
## Sổ Tay Khôi Phục Thảm Họa
### Kịch bản 1: Lỗi PostgreSQL (container crash hoặc hỏng dữ liệu)
1. **Đánh giá:** `docker logs goodgo-postgres` — kiểm tra tình trạng hỏng dữ liệu hoặc OOM
2. **Dừng service:** `docker compose stop api ai-services`
3. **Thử khởi động lại:** `docker compose restart postgres`
4. Nếu khởi động lại thất bại (hỏng dữ liệu):
- `docker compose stop postgres`
- Xóa volume: `docker volume rm goodgo-platform-ai_postgres_data`
- Tạo lại: `docker compose up -d postgres`
- Khôi phục từ bản sao lưu: `docker exec goodgo-pg-backup /scripts/pg-restore.sh /backups/<latest>.sql.gz`
- Xác minh: `docker exec goodgo-postgres psql -U goodgo -d goodgo -c '\dt'`
- Chạy migration: `pnpm prisma migrate deploy`
5. **Khởi động lại các service:** `docker compose up -d`
6. **Xác minh:** Kiểm tra API health tại `http://localhost:3000/health`
**RTO dự kiến:** ~15 phút (sao lưu cục bộ), ~30 phút (sao lưu ngoài site)
### Kịch bản 2: Service Bị Crash (API, AI-services hoặc Web)
1. **Kiểm tra log:** `docker compose logs --tail=100 <service>`
2. **Khởi động lại service:** `docker compose restart <service>`
3. Nếu crash lặp lại:
- Kiểm tra giới hạn tài nguyên: `docker stats`
- Kiểm tra biến môi trường: `docker compose config`
- Rollback về image tag trước nếu triển khai gần đây gây ra sự cố
4. **Xác minh:** Kiểm tra các endpoint health
**RTO dự kiến:** ~5 phút
### Kịch bản 3: Hỏng Toàn Bộ Máy Chủ
1. Cung cấp máy chủ mới với Docker + Docker Compose
2. Clone repo và thiết lập `.env` từ secrets manager
3. Pull image: `docker compose pull`
4. Khôi phục bản sao lưu PostgreSQL từ nơi lưu trữ ngoài site
5. Khởi động tất cả service: `docker compose up -d`
6. Kích hoạt lập chỉ mục lại Typesense: `pnpm run typesense:reindex`
7. Xác minh tất cả endpoint health
**RTO dự kiến:** ~60 phút (phụ thuộc vào tốc độ truyền bản sao lưu)
### Kịch bản 4: Hỏng Dữ Liệu (cấp độ ứng dụng)
1. Xác định phạm vi: những bảng/bản ghi nào bị ảnh hưởng
2. Nếu hạn chế: khôi phục các bảng cụ thể bằng `pg_restore --table=<name>`
3. Nếu diện rộng: khôi phục toàn bộ từ bản sao lưu tốt cuối cùng được biết đến
4. Xóa cache Redis: `docker exec goodgo-redis redis-cli -a "$REDIS_PASSWORD" FLUSHALL`
5. Lập chỉ mục lại Typesense: `pnpm run typesense:reindex`
---
## Tổng Hợp Log
Log được tổng hợp qua Loki + Promtail và có thể xem trong Grafana:
- **Grafana**: http://localhost:3002 (dashboard: "GoodGo - Logs")
- **Loki**: http://localhost:3100
- **Thời gian lưu log**: 15 ngày (được cấu hình trong `monitoring/loki/loki-config.yml`)