docs(lps): 운영 가이드 — 관측(readyz/ops/알림)·라이브 스모크·Docker 배포

P4/P5 반영: /readyz·/v1/lps/ops·워커 하트비트·임계 알림 env, LPS_LIVE 라이브 스모크,
docker compose 배포(헤드풀 Chromium+Xvfb·시크릿 env·프로필 볼륨·HEALTHCHECK).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
민헌 2026-07-09 23:27:02 +09:00
parent eb1ff8fee1
commit 97e566f844

View File

@ -101,15 +101,32 @@ SELECT avg(ip_request_no), count(*) FROM bot_detection;
SELECT key, until, reason FROM search_negative ORDER BY created_at DESC;
```
## 4-1. 관측·알림 (모니터링)
| 엔드포인트/신호 | 용도 |
|------|------|
| `GET /healthz` | liveness — 프로세스 살아있는지(DB 무관) |
| `GET /readyz` | readiness — DB 도달성까지 확인(실패 503). LB/오케스트레이터용 |
| `GET /v1/lps/ops` | 운영 스냅샷: 큐 카운트 + `oldest_pending_sec`(큐 지연) + `dead_1h` + `stuck_running` + `blocks_1h`(최근 차단). 외부 모니터가 스크랩·알림 |
| 워커 하트비트 | `/tmp/lps_worker_heartbeat`(mtime) — 컨테이너 HEALTHCHECK 가 신선도<120s 로 행/좀비 워커 감지 |
**임계 알림**(워커 ops-monitor): 초과 시 WARN 로그 + (env 있으면) Slack 호환 웹훅.
```
LPS_ALERT_WEBHOOK=https://hooks.slack.com/... # 있으면 알림 전송
LPS_ALERT_DEAD_1H=20 LPS_ALERT_BLOCKS_1H=80 LPS_ALERT_QUEUE_LAG_SEC=300
```
## 5. 테스트
```bash
python -m pytest
python -m pytest # 단위·통합(96) — 브라우저/네트워크 불필요
LPS_LIVE=1 python -m pytest tests/test_browser_base.py::test_live_smoke # 라이브 스모크(셀렉터·안티봇 드리프트 감지)
```
> ⚠️ **워커가 실행 중이면 테스트가 깨집니다** — 워커가 같은 `lps_db`의 테스트 작업을 가로채기 때문. 테스트 전 워커를 멈추세요:
> ```bash
> pkill -f worker_main.py
> ```
> 라이브 스모크는 IP 의존·느려서 기본 skip. 배포 후 셀렉터가 깨졌는지 수동/야간 점검용.
## 6. 문제 해결
@ -125,10 +142,20 @@ python -m pytest
| 검색이 너무 느림/비쌈 | `result.metrics`로 소스별 시간·DECODO 바이트 확인. 대역폭이 대부분(오픈마켓 크롤) |
| `result.desc = LPS_JOB_NOT_FOUND` | 존재하지 않거나 잘못된 job_id |
## 7. 배포 시 유의 (예정)
- Chrome을 **headless**로(서버엔 화면 없음) — 단 Cloudflare Turnstile은 headful이 더 잘 통과, 튜닝 필요
- Docker 이미지에 **chromium 설치** 필요
- **프록시(residential)** 사실상 필수 — 클라우드 IP는 쉽게 차단됨. 포트(IP) 풀은 넉넉히(회전 여유)
- 워커 여러 개는 **워커별 Chrome 프로필 분리 + 다른 프록시 IP**(이미 `WORKER_CONCURRENCY`로 자동 처리)
- 시크릿(config.local.toml)은 이미지에 굽지 말고 **마운트** 권장
- **비용**: 대역폭이 원가의 대부분(오픈마켓 크롤) — 같은 상품 재크롤을 줄이는 TTL 캐시가 다음 절감 후보
## 7. Docker 배포
```bash
# 루트에서 (DB 는 외부 PostgreSQL, host.docker.internal 로 연결)
docker compose build lps-api lps-worker
docker compose up -d lps-api lps-worker
docker logs -f lps-worker # 웜업·검색 로그
docker ps # lps-worker "(healthy)" 확인
```
- **워커 = 헤드풀 Chromium + Xvfb**(`Dockerfile.worker`): **headless 는 Akamai·Cloudflare Turnstile 에 탐지됨**(실측). Xvfb 가상 디스플레이로 headful 실행.
- **API = lean**(`Dockerfile`, 브라우저 불필요).
- **시크릿은 이미지에 안 굽고 env 주입**: `OPENAI_API_KEY`·`DECODO_*`·`NAVER_KEYS` (compose 주석 참고). 로컬은 config.local.toml.
- **Chrome 프로필 영속 볼륨**(`lps-profiles:/profiles`, `LPS_PROFILE_DIR`): 재시작해도 cf_clearance 유지 → 재웜업 회피.
- **워커 헬스**: HEALTHCHECK(하트비트<120s)로 행 워커 감지. k8s 는 liveness probe 로 자동 재시작 연결.
**남은 배포 과제**: API 인증·레이트리밋(비용 남용 방지), 다중 레플리카 시 분산 레이트리밋/프록시 IP 조정.
**비용**: 대역폭이 원가의 대부분(오픈마켓 크롤) — 같은 상품 재크롤을 줄이는 **TTL 캐시**가 다음 절감 후보.