Operations
배포와 운영
배포는 커밋 기반이 아니라 이미지 기반입니다 — 이미지는 빌드 시점의 작업 트리를 반영하므로, 어느 브랜치에 서 있는지가 곧 배포 내용입니다.
배포 (EKS)
아래는 저장소의 docs/runbooks/deploy-production.md 요약입니다. 계정 ID와
클러스터 이름은 자리표시자로 바꿔 두었습니다.
1. 무엇을 배포하는지 확인
git status
git branch --show-current
git log -1 --oneline
관련 없는 변경이 섞여 있으면 먼저 git stash 합니다.
2. 사전 검사
cd dashboard/server && node --test *.test.js
cd dashboard/web && npm install && npm run build
3. 빌드 & 푸시 (Graviton = arm64)
TAG=$(date -u +%Y%m%d-%H%M%S)
aws ecr get-login-password --region <region> \
| docker login --username AWS --password-stdin <account>.dkr.ecr.<region>.amazonaws.com
docker buildx build --platform linux/arm64 \
-t <account>.dkr.ecr.<region>.amazonaws.com/cc-ab-dashboard:$TAG \
-t <account>.dkr.ecr.<region>.amazonaws.com/cc-ab-dashboard:latest \
--push dashboard/
4. 롤아웃 & 검증
kubectl --context <cluster> -n claude-code set image deployment/dashboard \
dashboard=<account>.dkr.ecr.<region>.amazonaws.com/cc-ab-dashboard:$TAG
kubectl --context <cluster> -n claude-code rollout status deployment/dashboard --timeout=120s
kubectl --context <cluster> -n claude-code get pods -l app=dashboard
기대 상태: 파드 2/2 Running, deployment 이미지가 방금 태그와 일치,
로그에 dashboard listening on :8080만 있고 스택트레이스 없음.
롤백은 kubectl rollout undo deployment/dashboard. 크래시 루프면 먼저
의심할 것: 이름이 바뀐 환경 변수, ClickHouse 접속 실패(CH_URL /
CH_PASSWORD), Basic Auth 값 오류. /healthz는 Basic Auth
면제이므로 포트포워딩으로 직접 찔러 보는 게 가장 빠릅니다.
ECS / Fargate에 올리기
이미지는 그대로 씁니다 — 위 3번까지가 동일하고, 롤아웃만 ECS 방식으로 바뀝니다. 앱이 쿠버네티스에 의존하지 않으므로 코드 변경은 없습니다.
| 항목 | 값 |
|---|---|
| 태스크 아키텍처 | ARM64 (이미지가 linux/arm64) · Fargate |
| 컨테이너 포트 | 8080 (PORT env로 변경 가능) |
| 헬스체크 | GET /healthz — Basic Auth 면제, ClickHouse ping 포함 |
| 필수 env | CH_URL · CH_DB · CH_USER · CH_PASSWORD |
| 태스크 롤 | Ask Claude 챗을 쓸 때만 Bedrock InvokeModelWithResponseStream (해당 inference profile ARN으로 좁힐 것) |
| 시크릿 | ClickHouse 비밀번호와 Basic Auth는 Secrets Manager/SSM secrets로 주입 |
| 네트워크 | ClickHouse에 HTTP(기본 8123)로 닿는 서브넷 · ALB 타깃 그룹 8080 |
aws ecs update-service --cluster <cluster> --service dashboard \
--task-definition dashboard:<revision> --force-new-deployment
aws ecs wait services-stable --cluster <cluster> --services dashboard
이 저장소의 Terraform은 EKS 기준이라 태스크 정의·서비스·ALB는 새로 작성해야 합니다.
반대로 ClickHouse 쪽은 손댈 게 없습니다 — 앱은 ClickHouse가 EKS 위의 오퍼레이터든,
별도 클러스터든, 매니지드든 CH_URL만 봅니다.
환경 변수
| 변수 | 역할 | 기본값 |
|---|---|---|
CH_URL / CH_DB / CH_USER / CH_PASSWORD | ClickHouse 접속(읽기 전용 계정) | — |
BASIC_AUTH_USER / BASIC_AUTH_PASSWORD | 전역 Basic Auth. 둘 다 비면 인증 없음(로컬 개발) | 미설정 |
CHAT_MODEL_ID | Ask Claude 챗이 호출하는 Bedrock inference profile | global.anthropic.claude-sonnet-5 |
BEDROCK_REGION | Bedrock 호출 리전. 인프라 리전과 독립 | AWS_REGION → us-east-1 |
PII_MASK_ENABLED | 이메일 마스킹("1" / "true" = ON) | 앱 기본 OFF · Terraform 기본 ON |
모델·리전 같은 값은 Terraform 변수 한 곳(infra/variables.tf)만 고치면 env와
IAM 정책 ARN이 함께 반영됩니다. kubectl set env로 손으로 바꾸면 다음
terraform apply에서 되돌아갑니다.
흔한 증상과 첫 확인 지점
| 증상 | 먼저 볼 것 |
|---|---|
| 숫자가 비현실적으로 큼(100배 단위) | 누적 카운터를 sum(Value)로 더한 쿼리가 새로 들어왔는지 —
boundary diff를 쓰지 않으면 반드시 이렇게 됩니다. |
| 대시보드는 뜨는데 값이 전부 0 | 수집이 끊겼는지: 시간 버킷별 행 수가 0인 구간을 찾습니다(값의 변화가 아니라 행 도착 여부로 판단). |
| 쿼리가 갑자기 느려짐 | rollup(otel_metrics_sum_hourly) 대신 원본을 읽는 쿼리가
섞였는지, 그리고 materialized view가 살아 있는지. |
그룹이 전부 unknown |
rollup의 has_org 컬럼과 MV 정의 — organization.id는
ResourceAttributes가 아니라 datapoint Attributes에 실립니다. |
| Ask Claude 챗이 답을 못 함 / 느림 | Bedrock 모델 접근 권한과 리전, 그리고 질문 1건이 직렬 호출 3~5회(hop)라는 구조. 체감 지연은 첫 토큰(TTFT)이 지배합니다. |
이 저장소의 관례
-
절대
sum(Value)금지 —incFlat()/incBucketed()를 씁니다. -
프로모션/머티리얼라이즈 컬럼을 건드리면
clickhouse-schema.sql,grafana-ab-queries.sql, 아키텍처 문서를 함께 고칩니다 — 과거 리뷰에서 세 파일이 어긋난 적이 있습니다. -
새 엔드포인트는
index.js의 공용route()래퍼를 통과시킵니다 (범위 파싱 · 오류 처리 · TTL 캐시 + in-flight 중복 제거). -
sanitizeSql()은 LLM이 만든 SQL이 ClickHouse에 닿는 유일한 지점입니다 — 여기 변경은 보안 리뷰 수준의 검토가 필요합니다. -
주석은 "왜"가 비자명할 때만. 이 저장소는 실측 결과(
실측 확인: …)와 의도한 단순화(ponytail: …)를 주석으로 남기는 스타일을 유지합니다.