ScaleX Federation child chart — 멀티클러스터 노드 메트릭 파이프라인 POC. 표준 라이브러리만
쓰는 Python 앱 3개를 Helm 차트로 묶고, Karmada 정책으로 member cluster b·c에 확산한다.
| 컴포넌트 | 역할 | 배치 | 서비스 | 주요 엔드포인트 |
|---|---|---|---|---|
metrics-collector |
/proc/stat·/proc/meminfo에서 CPU·메모리 사용률을 읽어 store에 POST |
b + c (동시 확산) |
ClusterIP 없음(아웃바운드) | GET /healthz |
ring-store |
(site, category)별 최근 N개 샘플을 인메모리 ring buffer로 유지 + summary 저장 + HTML 대시보드 |
b |
LoadBalancer | GET·POST /samples, GET·POST /summary, GET / (대시보드), GET /healthz |
stats-analyzer |
store에서 샘플을 GET → site×category별 max/avg/min 계산 → summary POST | c |
ClusterIP 없음(아웃바운드) | GET /healthz |
데이터 흐름: collector(b,c) → ring-store(b) ← analyzer(c). collector·analyzer는
store의 LoadBalancer IP(store.service.loadBalancerIP)로 직접 접속한다. store는 b에만
배치되므로 IP는 site-b의 Cilium LB 풀(10.33.142.0/24)에서 할당된다.
| 키 | 의미 | 기본값 |
|---|---|---|
images.<name>.repository / .tag |
이미지 좌표 (child 소유). digest/sourceRevision은 Federation promotion이 주입 |
.../tower-ci/sample-poc/<name>, v0.2.3 |
collector.intervalSeconds |
수집 주기 초 (COLLECT_INTERVAL) |
5 |
collector.bufferSize |
ring buffer 크기 (ring-store의 BUFFER_SIZE로 주입) |
50 |
analyzer.intervalSeconds |
분석 주기 초 (ANALYZE_INTERVAL) |
10 |
store.service.loadBalancerIP |
store LB IP. collector·analyzer의 STORE_URL = http://<이 값> |
10.33.142.20 |
karmada.enabled |
Propagation/Override 정책 렌더 토글 | true |
karmada.placement.store.clusterNames |
store 배치 클러스터 | [b] |
karmada.placement.analyzer.clusterNames |
analyzer 배치 클러스터 | [c] |
karmada.avoidNodes |
특정 노드 회피 목록 {cluster, hostnames[]}. per-fleet fact라 Federation runtime-values가 채운다 |
— |
nameOverride/fullnameOverride는 비워두면 리소스 이름이 릴리스 이름을 따른다.
- collector:
STORE_URL,COLLECT_INTERVAL,NODE_NAME(spec.nodeNamefieldRef),SITE_NAME(base는unknown; OverridePolicy가 클러스터별로b/c덮어씀) - analyzer:
STORE_URL,ANALYZE_INTERVAL - store:
BUFFER_SIZE
- PropagationPolicy (컴포넌트별):
conflictResolution: Abort,preemption: Never,propagateDeps: true. collector는scalex.io/role=child라벨 +spreadConstraints(cluster 기준 minGroups=maxGroups=2)로b·c동시 확산, store/analyzer는clusterNames로 고정. - OverridePolicy
metrics-collector: 대상 클러스터별로SITE_NAME=b/SITE_NAME=c를 env에 append. - OverridePolicy
avoid-node:karmada.avoidNodes가 있을 때만 렌더. 해당 클러스터 사본에만kubernetes.io/hostname NotIn <hostnames>nodeAffinity를 주입한다(base Deployment는 affinity 없음).
정책은 리소스를 라벨이 아니라 이름으로 셀렉트하므로, 배치되지 않는 클러스터를 가리키는 규칙은 no-op다.
의존성 없음, Python 3.10+.
PORT=8080 BUFFER_SIZE=50 python3 src/store.py
STORE_URL=http://127.0.0.1:8080 SITE_NAME=b python3 src/collector.py
STORE_URL=http://127.0.0.1:8080 python3 src/analyzer.py브라우저로 http://127.0.0.1:8080/ 열면 대시보드(사이트별 CPU·메모리 라인 차트 + 버퍼/요약 테이블)를 확인한다.
빌드 컨텍스트는 레포 루트 (Tekton derive-targets가 .으로 설정).
docker build -f images/ring-store/Dockerfile -t <registry>/sample-poc/ring-store:<tag> .이미지는 python:3.13-alpine 기반, non-root(65532) + read-only rootfs로 실행된다.
차트는 직접 배포하지 않는다. scalex-federation이 이 차트를 release로 승인하면
Tower Argo CD → Karmada API → member cluster(b·c) 순으로 push된다. 이미지 digest와
sourceRevision은 Federation promotion(releases/<child>/values.yaml)이 주입한다.