Files
duocthu/docs/operations.md
T
VuQuangBao a85b0ccac8 Fix the F3 out-of-scope gate, close out the V1 feature audit, and clean up project docs
Also drop .github/ (GitHub-specific CI/CD workflows and ArgoCD
operational scripts) from this mirror -- Gitea auto-picked up
.github/workflows/*.yml as Actions and queued a run against secrets
that don't exist here. Not meaningful outside the GitHub-hosted repo
anyway.
2026-08-25 12:05:00 +07:00

104 lines
6.1 KiB
Markdown

# Vận hành, triển khai và xử lý sự cố
> Loại chính: How-to
> Phạm vi: k3s + ArgoCD (production kể từ cutover 2026-08-17)
Production (`realvuxbaro.me`) chạy trên k3s, quản lý bởi ArgoCD Application
**`medical-chatbot-app`** (ai-service + web + observability) và
**`medical-chatbot-data`** (PostgreSQL + Qdrant, tách release để prune/self-heal
phía app không bao giờ đụng vào dữ liệu). Cả hai đặt `syncPolicy.automated` với
`selfHeal` + `prune` — **mọi merge vào `master` áp thẳng vào production, không
có cổng duyệt thủ công.** EC2 Docker Compose (`52.0.158.61`) đã **stop** từ
2026-08-18, không còn nhận deploy tự động và không còn là đường lui sống; xem
mục Rollback bên dưới cho cách khởi động lại nếu cần.
## Deploy
Hai loại thay đổi đi hai đường khác nhau:
**Thay đổi code app** (`apps/ai-service/**`, `apps/web/**`, `packages/**`,
`ingestion/data/verified/drug_entities.json`) — merge vào `master` kích hoạt
`build-practice-images.yml`: build + push image GHCR gắn tag theo commit SHA,
sau đó `.github/scripts/sync_practice_argocd.py` ghi tag mới vào Application
`medical-chatbot-app` và gọi sync. Workflow tự xác nhận
`readytochat.realvuxbaro.me` đã lên bản mới trước khi báo thành công.
`ci.yml` (ruff/pytest/lint/build) chạy độc lập trên cùng push — **CI đỏ không
tự động chặn deploy**, hai workflow không phụ thuộc nhau.
**Thay đổi chart/config** (`infra/helm/**`) — `helm-chart.yml` lint + render +
assert bất biến (Qwen, rerank, TLS, `refute volumeClaimTemplates`...) trên PR.
Merge xong, ArgoCD tự phát hiện và sync — không qua CI nào chạy trên production
thật, review ở PR là cổng chắn duy nhất.
Sau deploy (cả hai loại):
1. xác nhận Application `Synced`/`Healthy` và image tag/chart revision đúng;
2. gửi smoke case qua web, gồm answerable có citation và abstain;
3. quan sát error rate, latency, provider failure và decision distribution;
4. ghi lại thời điểm, SHA/revision và kết quả.
## Rollback
**Image bị lỗi (phổ biến nhất):** `gh workflow run rollback-k3s.yml -f
target_sha=<sha tốt lần trước>`. Lấy SHA đó từ lần chạy `build-practice-images.yml`
thành công gần nhất trước đó (`gh run list --workflow=build-practice-images.yml`).
Workflow tự xác nhận image đã tồn tại trên GHCR, repoint `medical-chatbot-app`
(dùng chung `sync_practice_argocd.py` với đường deploy xuôi), chờ tới khi
Application thật sự `Synced`/`Healthy` trên đúng tag đó (không chỉ tin lệnh
sync đã gọi xong — có race với ArgoCD `selfHeal`, xem comment trong script),
rồi mới xác nhận `realvuxbaro.me` sống. Chưa tự động hoá; kích hoạt thủ công
qua `workflow_dispatch`, không trigger theo push.
**Chart/config bị lỗi:** `git revert` commit gây lỗi trên `master` qua PR bình
thường; ArgoCD `selfHeal` tự áp bản revert. Muốn ngay lập tức thay vì chờ chu kỳ
poll, sync thủ công qua ArgoCD UI/CLI.
**Sự cố nặng ở tầng cluster** (k3s tự nó hỏng, không phải lỗi ở app): Compose
EC2 (`i-039fc8f6102467a54`, `52.0.158.61`) đã **stop** (không terminate) ngày
2026-08-18 theo quyết định chỉ dùng 1 EC2 — **không còn là đường lui sống**.
Máy vẫn tồn tại (root EBS `DeleteOnTermination=true`, nên terminate mới mất
vĩnh viễn), đóng băng ở code `df57e6b` từ trước cutover. Muốn dùng lại làm
đường lui khẩn cấp: `aws ec2 start-instances --instance-ids
i-039fc8f6102467a54`, chờ container tự khởi động (`docker-compose.prod.yml`
không có auto-start service, kiểm tra lại), xác nhận corpus/schema còn tương
thích với migration hiện tại của production trước khi trỏ A record — thời
gian đứng máy càng lâu, xác suất lệch corpus càng cao. Đây là việc thủ công,
không có script/workflow nào làm sẵn.
Không có cơ chế nào ở trên tự rollback Qdrant corpus hay database migration.
Với corpus, dùng snapshot/migration riêng; không rollback dữ liệu phá huỷ khi
chưa có backup.
## Theo dấu request
1. Lấy `trace_id`, `correlation_id`, `otel_trace_id` từ response.
2. Tra `rag_retrieval_trace` để xem query, scope, intent, decision, reason, drug và citations.
3. Kiểm tra Prometheus request/stage duration, decision, provider failure và generation rejection.
4. Nếu OTel bật, tìm trace trong Tempo/Grafana để xác định stage chậm/lỗi.
5. Phân loại nguyên nhân: input/scope, corpus/retrieval, provider/model hoặc grounding.
`/metrics` có thể yêu cầu `Authorization: Bearer <token>` khi `METRICS_TOKEN` được đặt.
## Observability stack
Local stack là Prometheus, OpenTelemetry Collector, Tempo và Grafana. OTel mặc định
tắt. Observability failure không được làm service dừng trả lời; trace write failure
phải xuất hiện trong metric/log. Production monitoring cần readiness và synthetic
query vì health không chứng minh citation pipeline hoạt động end-to-end.
## Troubleshooting
| Triệu chứng | Kiểm tra đầu tiên | Không nên làm |
|---|---|---|
| service không ready | datastore, startup log, manifest/model/dimensions | bỏ qua manifest gate |
| `provider_unavailable` tăng | region, credential, quota, network, stage trace | báo “Dược thư không có dữ liệu” |
| retrieval score thấp | drug/section route, collection và manifest | hạ threshold không qua eval |
| grounding rejection tăng | evidence packet, model output, validator | hiển thị raw output |
| clarify lặp | history, field thiếu, circuit breaker | tăng loop vô hạn |
| citation sai trang | printed-page map, chunk payload, quarantine | thay printed page bằng physical page |
Các reason grounding quan trọng gồm `ungrounded_number`, `invalid_citation`,
`uncited_claim`, `unsupported_claim``incomplete_answer`. Giữ fail-closed và
thêm regression test trước khi sửa prompt/parser/validator.