CC Usage Dashboard

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 포함
필수 envCH_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_PASSWORDClickHouse 접속(읽기 전용 계정)
BASIC_AUTH_USER / BASIC_AUTH_PASSWORD전역 Basic Auth. 둘 다 비면 인증 없음(로컬 개발)미설정
CHAT_MODEL_IDAsk Claude 챗이 호출하는 Bedrock inference profileglobal.anthropic.claude-sonnet-5
BEDROCK_REGIONBedrock 호출 리전. 인프라 리전과 독립AWS_REGIONus-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)이 지배합니다.

이 저장소의 관례