
Intro
안녕하세요. 환이s입니다 👋
지난 글에서는 KEDA를 Harbor + ArgoCD 기반으로 구축하고,
외부 모듈 연동을 위한 RBAC까지 구성하는 과정을 정리해 봤습니다.
이번 글에서는 그렇게 설치한 KEDA를 실제로 활용해서,
이벤트 기반 멀티 트리거 ScaledObject를 설계하는 방법을 정리해보려고 합니다.
실측으로 스케일 값을 계산하고,
성경이 다른 두 신호 (양·지연)를 조합하고,
스케일업·다운을 비대칭으로 설계하는 이 원칙들은 특정 워크로드에 국한되지 않습니다.
다만 개념만 나열하면 와닿지 않으니,
이번 편에서는 Airflow의 Celery Worker를 스케일 대상 예시로 삼아
설계 과정을 처음부터 끝까지 따라갑니다.

지금까지 구축한 파이프라인은 Airflow가 DAG를 돌리고
그 안에서 Spark Job을 K8s에 제출하는 구조라,
Worker(KEDA)와 Spark Executor(DynamicAllocation)를
어떻게 같은 기준으로 움직이게 할지가 핵심 과제였고,
이 사례가 멀티 트리거 설계의 필요성을 잘 보여주기 때문입니다.
이번 글에서는
- Spark를 KEDA로 직접 스케일할 수 없는 이유와 우회 설계
- statsd extraMappings로 Airflow 메트릭을 표준화하는 방법
- ServiceMonitor로 statsd 메트릭을 Prometheus에 수집시키는 방법
- worker_concurrency 실측으로 스케일 값을 정확히 계산하는 방법
- Redis + Prometheus 멀티 트리거 ScaledObject 설계 (v1 → v2)
- task_id 명명규칙으로 정규식 쿼리의 전제를 강제하는 방법
- 실제 스케일 테스트에서 마주친 "너무 빨리 줄어드는" 현상의 정체
까지 순서대로 확인해 보겠습니다.
1. 오토스케일링 설계 방향 - "왜 Spark는 KEDA로 직접 못 하나"
구축 편에서 KEDA 설치를 마쳤으니, 이번 편은 본론인 오토스케일링입니다.
지금까지 구축한 파이프라인은 Airflow가 DAG을 돌리고,
그 안에서 Spark Job을 K8s에 제출하는 구조입니다.
(궁금하신 분들은 아래 링크 참고해 보시면 도움이 될 거 같습니다.)
[Data Platform] KEDA 구축 가이드(Operator 설치부터 API 연동용 RBAC까지)
Intro 안녕하세요. 환이s입니다 👋 지난 글에서는 데이터 레이크하우스 플랫폼을 GitOps 방식으로 관리하기 위해ArgoCD를 Kubernetes 위에 구축하고 App of Apps 패턴으로 전체 스택을 운영하는 과정을 정
drg2524.tistory.com
[Data Platform] Airflow 구축 가이드 (feat. Spark on Kubernetes)
Intro 안녕하세요. 환이s입니다 👋 지난 글에서는 데이터 레이크하우스 플랫폼의 네 번째 스택으로 Trino + Hive Metastore + PostgreSQL 3계층 구조로 Delta Lake SQL 조회 환경을 구축하는 과정을 정리해 봤습
drg2524.tistory.com
이상적으로는 KEDA 하나로 Worker와 Spark Executor를 모두 제어하고 싶었습니다.
이 방향을 KEDA 단일 제어로 검토했지만,
SparkApplication 리소스가 /scale 서브리소스를 지원하지 않아
KEDA가 직접 스케일하는 것은 기술적으로 불가능했습니다.
그래서 채택한 것이 메트릭 표준화입니다.

즉, Worker와 Executor가 서로 다른 메커니즘으로 움직이더라도,
같은 메트릭 기준에 맞춰 동작하도록 통일하는 절충안입니다.
💡 참고
공식 Airflow Helm chart에는 workers.celery.keda.enabled=true 한 줄로
Airflow metadata DB(task_instance 테이블)를 직접 쿼리하는
KEDA 통합 기능이 내장돼 있습니다.
다만 지금까지 구축한 파이프라인이 그동안 직접 구축한
ScaledObject의 검증·버그 수정 이력을 보존하기 위해 기존 방식을 유지하고,
공식 기능은 참고만 했습니다.
⚠️ 주의
공식 내장 기능과 직접 만든 ScaledObject를 동시에 켜면 절대 안 됩니다.
HPA 두 개가 같은 StatefulSet을 두고 경쟁하게 됩니다.
즉, 여기서 확인할 수 있는 핵심은
모든 것을 KEDA로 단일 제어하려 하지 말고,
기술적 제약(Spark /scale 미지원)을 인정한 뒤,
"메트릭 기준을 통일"하는 방향으로 우회했다는 점입니다.
2. 파일 구조 - "오토스케일링 설정은 어디에 있나"
본격적인 설정에 들어가기 전에,
파일이 어디에 있는지 부터 짚고 가겠습니다.
오토스케일링 관련 설정은 KEDA 디렉토리가 아니라
스케일 대상인 Airflow 쪽 manifests에 모여 있습니다.
services/airflow/manifests/
├── 00_rbac
├── 10_pvc
├── 20_ingress
├── 30_filebrowser
├── 40_monitoring
│ └── 10_servicemonitor-airflow-statsd.yaml # Prometheus 수집 (섹션 4)
└── 50_autoscaling
└── 10_scaledobject-airflow-worker.yaml # ScaledObject 본체 (섹션 6)
구축편에서 본 KEDA 엔진(services/keda/)과 대비하면 역할이 이렇게 나뉩니다.
- KEDA 엔진 (services/keda/) — Operator·CRD·RBAC 등 "스케일을 수행하는 주체"
- 스케일 규칙 (services/airflow/manifests/50_autoscaling/) — ScaledObject 등 "무엇을 어떻게 스케일 할지"
- 메트릭 수집 (services/airflow/manifests/40_monitoring/) — ServiceMonitor 등 "판단 근거가 될 메트릭 파이프라인"
즉, 여기서 확인할 수 있는 핵심은 "스케일 하는 주체(KEDA)"와 "스케일 당하는 대상의 규칙(Airflow ScaledObject)"을 경로상으로 분리해서, 각각 독립적으로 관리했다는 점입니다.
3. 메트릭 표준화 - statsd extraMappings
멀티 트리거를 만들려면 Prometheus 쿼리가 필요한데,
기존 Airflow 메트릭은 DAG 이름별로 메트릭명 자체가 갈라져 있는 게 문제였습니다.
airflow_dag_<dag_name_a>_submit_spark_job_queued_duration_sum
airflow_dag_<dag_name_b>_submit_spark_job_queued_duration_sum
이러면 신규 DAG를 추가할 때마다 쿼리를 고쳐야 합니다.
services/airflow/helm/values.yaml에 statsd.extraMappings를 추가해 메트릭명을 통일했습니다.
statsd:
extraMappings:
- match: airflow.dag.*.*.queued_duration
name: "airflow_task_queued_duration"
labels:
dag_id: "$1"
task_id: "$2"
적용 결과, 메트릭명이 하나로 통일되고 dag_id/task_id가 레이블로 분리됐습니다.
airflow_task_queued_duration_sum{dag_id="<dag_name_a>", task_id="submit_spark_job"}
airflow_task_queued_duration_sum{dag_id="<dag_name_b>", task_id="submit_spark_job"}
이제 sum() 합산 쿼리 하나로 전체 DAG를 커버할 수 있습니다.
💡 참고
match 패턴(airflow.dag.*.*.queued_duration)의
와일드카드 두 개가 각각 dag_id($1)·task_id($2)로 매핑됩니다.
적용 전에 실제 statsd 메트릭 경로가
airflow.dag.<dag>.<task>.queued_duration 형태가
맞는지(중간에 다른 세그먼트가 끼지 않는지) 한 번 확인하세요.
세그먼트 수가 어긋나면 레이블이 엉뚱한 값으로 잡힙니다.
⚠️ 주의
이 ConfigMap을 kubectl edit으로 직접 고치면 안 됩니다.
Helm이 관리하는 리소스라 ArgoCD sync 시 원복됩니다.
즉, 여기서 확인할 수 있는 핵심은 메트릭명을 값(레이블)으로 빼내면,
신규 DAG가 추가돼도 쿼리를 고칠 필요가 없어진다는 점입니다.
4. Prometheus 수집 연결 - ServiceMonitor
statsd로 메트릭명을 표준화했어도,
그 메트릭이 Prometheus에 실제로 수집되어야 KEDA 트리거가 값을 읽을 수 있습니다.
Airflow의 statsd exporter가 노출하는 /metrics를 Prometheus가 긁어가도록
ServiceMonitor를 구성했습니다.
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: airflow-statsd
namespace: monitoring
labels:
release: prometheus-helm # prometheus의 serviceMonitorSelector와 일치해야 함
spec:
namespaceSelector:
matchNames:
- airflow
selector:
matchLabels:
component: statsd
release: airflow-helm
endpoints:
- port: statsd-scrape # 9102/TCP — Prometheus metrics 포트
interval: 15s
path: /metrics
💡 참고
metadata.labels.release: prometheus-helm이 가장 자주 실수하는 부분입니다.
Prometheus Operator는 serviceMonitorSelector에
매칭되는 레이블을 가진 ServiceMonitor만 인식합니다.
이 값이 안 맞으면 ServiceMonitor를 만들어도
Prometheus가 무시해서 메트릭이 안 들어옵니다.
kubectl get prometheus -n monitoring -o yaml | grep -A5 serviceMonitorSelector로 실제 셀렉터를 먼저 확인하세요.
⚠️ 주의
statsd exporter는 포트가 두 개입니다.
수집(scrape)은 9102/TCP statsd-scrape 이고,
Airflow가 메트릭을 보내는 ingest는 9125/UDP입니다.
ServiceMonitor의 port는 반드시 TCP metrics 포트를 가리켜야 합니다.
즉, 여기서 확인할 수 있는 핵심은
statsd 표준화(생산) → ServiceMonitor 수집(Prometheus) → KEDA 트리거(소비)로 이어지는 파이프라인이 전부 연결돼야 비로소 Prometheus 트리거가 동작한다는 점입니다.
5. worker_concurrency 실측 - "추정치를 실측값으로"
스케일 파라미터를 정하려면
Worker 하나가 동시에 처리하는 task 수(worker_concurrency)을 알아야 합니다.
추정하지 않고 직접 조회했습니다.
kubectl exec -n airflow airflow-helm-worker-0 -c worker -- \
airflow config get-value celery worker_concurrency
# → 16
운영 예상 동시 트리거 규모(상한 300 기준)로 재계산했습니다.
300 / 16 ≈ 18.75 → maxReplicaCount: 19
listLength: 16 (worker_concurrency와 동일하게 맞춤)
즉, 여기서 확인할 수 있는 핵심은
maxReplicaCount나 listLength 같은 값은 감이 아니라 실측된 worker_concurrency를 기준으로 계산해야 한다는 점입니다.
6. ScaledObject v1 → v2 변경 요약
초기 버전(v1)에서 운영 규모(v2)로 재설계한 내용입니다.
| 항목 | v1 | v2 |
| minReplicaCount | 1 | 2 |
| maxReplicaCount | 5 | 19 (실측 기반) |
| listLength | 2 | 16 (실측 기반) |
| scaleUp stabilization | 30s | 15s |
| scaleUp policy | +2/30s | +4 또는 +100%/30s (Max) |
| restoreToOriginalReplicaCount | true | false |
| trigger | Redis 단일 | Redis + Prometheus 멀티 트리거 |
대상 워크로드를 원래 replica 수로 되돌릴지를 정하는 옵션입니다.
v1은 true(원래값 복귀)였지만,
v2에서는 false로 두어 삭제 시점에 강제 복귀시키지 않고
HPA의 자율 판단에 맡기도록 변경했습니다.
멀티 트리거를 포함한 ScaledObject 실물 전체는 다음과 같습니다.
TriggerAuthentication과 Redis 비밀번호 Secret도 같은 파일에 함께 정의했습니다.
# ── Redis 접근 비밀번호 Secret ──
apiVersion: v1
kind: Secret
metadata:
name: airflow-redis-secret
namespace: airflow
type: Opaque
stringData:
redis-password: "<REDIS_PASSWORD>" # 실제 비밀번호로 교체
---
# ── KEDA가 Secret을 참조하기 위한 TriggerAuthentication ──
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: airflow-redis-auth
namespace: airflow
spec:
secretTargetRef:
- parameter: password
name: airflow-redis-secret
key: redis-password
---
# ── 본체: ScaledObject ──
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: airflow-worker-scaler
namespace: airflow
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: StatefulSet
name: airflow-helm-worker
minReplicaCount: 2 # 기본 가용성 확보 (단일 장애점 방지)
maxReplicaCount: 19 # worker_concurrency=16 기준 실측 재계산 (300/16≈19)
cooldownPeriod: 60
advanced:
restoreToOriginalReplicaCount: false # 운영에선 원래값 강제 복귀 X, HPA 자율 판단
horizontalPodAutoscalerConfig:
behavior:
scaleUp:
stabilizationWindowSeconds: 15 # 폭주 대응 위해 빠르게 반응
policies:
- type: Pods
value: 4 # 한 번에 4개씩 확장
periodSeconds: 30
- type: Percent
value: 100 # 또는 현재 replica의 100%
periodSeconds: 30
selectPolicy: Max # 둘 중 큰 값 적용
scaleDown:
stabilizationWindowSeconds: 600 # 축소는 신중하게 (10분)
policies:
- type: Pods
value: 2
periodSeconds: 120
triggers:
# Trigger 1: Redis Celery 큐 길이 — 즉각적인 폭주 감지
- type: redis
authenticationRef:
name: airflow-redis-auth
metadata:
address: airflow-helm-redis.airflow.svc.cluster.local:6379
listName: celery
listLength: "16" # worker_concurrency(16)와 동일 (실측값)
databaseIndex: "0"
enableTLS: "false"
# Trigger 2: Prometheus 큐 대기시간 — 후행 추세 감지
# 순간적으로 큐가 비어도 누적 지연이 길었다면 스케일 유지
- type: prometheus
metadata:
serverAddress: http://prometheus-helm-kube-prome-prometheus.monitoring:80
query: |
sum(rate(airflow_task_queued_duration_sum{task_id=~"submit_spark.*"}[5m]))
/
sum(rate(airflow_task_queued_duration_count{task_id=~"submit_spark.*"}[5m]))
threshold: "3" # 평균 큐 대기시간 3초 이상이면 스케일업 신호
activationThreshold: "1" # 이 값(1초)을 넘어야 트리거가 '활성'으로 잡힘
설계 의도를 정리하면 다음과 같습니다.
- 두 트리거의 역할 분담
- Redis(큐 길이)는 "지금 당장 쌓인 양"을 보는 선행 지표, Prometheus(대기시간)는 "누적된 지연 추세"를 보는 후행 지표입니다.
- 큐가 순간적으로 비어도 대기시간이 길었다면 스케일을 유지합니다.
- 비대칭 스케일 정책
- scaleUp은 15초 창 + 4개/100%로 공격적, scaleDown은 600초 창 + 2개로 보수적입니다.
- 폭주엔 빠르게 대응하되, 축소는 천천히 해서 플래핑(flapping)을 막습니다.
- 인증 분리
- Redis 비밀번호를 ScaledObject에 직접 넣지 않고 Secret + TriggerAuthentication으로 분리해, 여러 트리거가 같은 인증을 재사용할 수 있게 했습니다.
💡 참고
threshold와 activationThreshold의 차이: threshold(3초)는
"몇 개로 스케일 할지" 계산에 쓰는 목표값이고, activationThreshold(1초)는
"이 트리거를 활성으로 볼지 말지"를 가르는 경계입니다.
지표가 1초 이하이면 이 Prometheus 트리거는 비활성으로 간주됩니다.
다만 minReplicaCount: 2라서 실제로 0까지 내려가진 않고, 최소 2개는 유지됩니다.
Prometheus 트리거의 쿼리는 "submit_spark로 시작하는
태스크들의 평균 큐 대기시간(대기시간 합 ÷ 건수)"을 계산합니다.
결과적으로 Redis 큐 길이(양)와 Prometheus 대기시간(지연)을 함께 보게 되므로,
큐가 짧아도 처리가 밀리면 스케일 업되는 구조입니다.
즉, 여기서 확인할 수 있는 핵심은
"양(Redis)"과 "지연(Prometheus)"이라는 성격이 다른 두 신호를 조합하고, 스케일업·다운을 비대칭으로 설계해 폭주 대응력과 안정성을 동시에 잡았다는 점입니다.
7. 명명규칙 수립 - task_id 표준화
위 쿼리의 task_id=~"submit_spark.*" 정규식이 동작하려면 운영 규칙이 전제되어야 합니다.
SparkKubernetesOperator를 사용하는 모든 태스크는
task_id를 submit_spark_로 시작해야 KEDA가 누락 없이 감지합니다.
- ✅ submit_spark_job → 감지됨
- ✅ submit_spark_daily → 감지됨
- ⬜ 모니터링/PythonOperator 등 비-Spark 태스크 → 패턴 밖 (정상, 규칙 대상 아님)
⚠️ 주의
쿼리에서 task_id="submit_spark.*"처럼 =(등호)를 쓰면 안 됩니다.
=는 리터럴 매칭이라 정규식으로 동작하지 않아 데이터가 영구 누락될 수 있습니다. 정규식 연산자 =~를 사용해야 합니다.
즉, 여기서 확인할 수 있는 핵심은
KEDA 쿼리가 정규식에 의존한다면, 그 정규식이 성립하도록 하는 "명명규칙"이 반드시 팀 차원에서 강제되어야 한다는 점입니다.
8. 스케일 테스트 - Worker 5개 규모 검증
v2 적용 후 실제 동작을 검증했습니다.
전체 19개를 한 번에 돌리기 전에, 1단계로 5개 규모부터 확인했습니다.
listLength=16 기준으로 Worker 5개를 목표로 큐 길이 80(= 16 x 5)을 밀어 넣었습니다.
kubectl exec -n airflow airflow-helm-redis-0 -- \
redis-cli -a '<REDIS_PASSWORD>' -n 0 rpush celery $(seq 1 80 | sed 's/^/dummy/')

위 이미지를 확인해 보시면 정상적으로 스케일업에 성공했습니다.
⚠️ 주의
Airflow values.yaml에서 worker의 podAntiAffinity는
requiredDuringSchedulingIgnoredDuringExecution, 즉 "같은 노드에 worker Pod 두 개 금지"를 강제하는 설정입니다. 이 때문에 worker replica 수는 사실상 노드 수를 넘을 수 없습니다. maxReplicaCount: 19를 채우려면 그만큼의 노드가 필요하다는 뜻이고, 이 제약이 "풀스케일 테스트를 못 한 이유"와도 직결됩니다.
9. 예상치 못한 현상 - 5에서 곧바로 줄어듦
진행하면서 겪은 문제를 발견했습니다.
그건 바로 5/5에 도달하자마자 곧바로 줄어든 사례입니다.
5/5 → 5/1 → 4/1 → 3/1 ...
스케일다운 안정화 기간(stabilizationWindowSeconds: 600, 10분)을 설정했는데도
너무 빨리 줄어드는 것처럼 보여 원인을 조사했습니다.
1차 의심 — KEDA operator 에러 로그
ERROR scale_handler error getting metric spec for the scaler
error: "scaler with id 0 not found. Len = 0"
처음엔 멀티 트리거 구조 결함으로 의심했지만,
전체 로그를 다시 보니 이 에러는 단 1회만 발생하고 재발이 없었습니다.
같은 grep 결과에 섞여 있던 다른 에러들은 과거 날짜의 무관한 기존 리소스 에러였고,
grep 결과를 잘못 해석한 것이었습니다.
2차 확인 — HPA current 값
"s0-redis-celery" (target average value): 0 / 16
스케일다운 시점의 current 값이 0이었습니다.
KEDA가 잘못 읽은 게 아니라 실제로 큐가 비어 있었던 겁니다.
3차 확인 — Redis 직접 조회
kubectl exec -n airflow airflow-helm-redis-0 -- redis-cli -a '<REDIS_PASSWORD>' -n 0 llen celery
# → 0
더미 데이터 80개가 실제로 큐에서 사라진 것을 직접 확인했습니다.
KEDA 설정(주소, DB index)과 Celery 실제 broker_url도 정확히 일치했습니다.
즉, 여기서 확인할 수 있는 핵심은 "stabilizationWindow가 안 먹은 것"이 아니라, 더미 데이터가 Worker에 의해 소비되어 큐가 예상보다 빨리 비워졌고, KEDA는 그 변화를 정확히 감지해 최솟값(2)으로 정상 축소한 것이라는 점입니다.
현상은 정상이었습니다.
💡 참고
더미 문자열은 Celery Worker가 처리 시도 후 실패/폐기하면서 곧바로 큐에서 사라집니다. 그래서 실제 부하와 달리 큐가 순식간에 비워진 것입니다. 더 정밀한 검증이 필요하다면 더미 문자열이 아닌 실제 Celery 태스크로 재테스트하는 것을 권장합니다.
10. 검증 완료 항목
1~5개 규모 기준으로 검증이 끝난 항목입니다.
| 항목 | 결과 |
| 스케일업 (2→5) | 정상 |
| podAntiAffinity 노드 분산 | 정상 |
| 스케일다운 (5→2) | 정상 (큐 소진에 따른 정당한 반응) |
| KEDA 멀티 트리거(Redis+Prometheus) 구조 안정성 | 결함 없음 확인 |
| Spark DynamicAllocation 동시 다중 실행 | 3개 SparkApplication 동시 RUNNING → 충돌 없이 COMPLETED |
| statsd extraMappings 메트릭 표준화 | 단일 메트릭 통합 완료 |
| Prometheus 멀티 트리거 쿼리 실측 | 평균 큐 대기시간 0.66초 확인 |
최종 검증 결과 요약입니다.
Max Replica Count: 19
Min Replica Count: 2
List Length: 16
External Metric Names: s0-redis-celery, s1-prometheus
Triggers Types: redis, prometheus
Triggers Activity: 둘 다 Is Active: false (현재 부하 낮아 정상, 에러 없음)
메트릭 표준화 목표를 달성했고,
Worker(KEDA, Redis+Prometheus 멀티 트리거)와 Executor(Spark DynamicAllocation)가
동일 기준 메트릭(airflow_task_queued_duration)에 정렬되어 동작합니다.
11. 오토스케일링 트러블슈팅 정리
지금까지 오토스케일링 작업 진행하면서 트러블슈팅 내용을 공유하고자 합니다.
| 증상 | 원인 | 해결 |
| rate() 쿼리만 빈 응답, sum()은 정상 | curl URL의 {, [ 특수문자가 셸에서 깨짐 | --data-urlencode 사용 |
| Prometheus 쿼리 결과 NaN | 5분 윈도우 내 활동 없어 0/0 (정상 idle) | DAG 재트리거 후 정상값(0.6초대) 확인 |
| task_id="submit_spark.*" (등호) 사용 | =는 리터럴 매칭, 정규식 아님 — 데이터 영구 누락 위험 | =~(정규식 연산자)로 수정 |
| describe 결과가 v1 값(max=5) 그대로 | sync 완료 직전 타이밍에 조회 | 1~2분 후 재확인 시 v2 값(max=19) 정상 |
| KEDAScalerFailed: scaler with id 0 not found | 트리거 재구성 시 1회성 과도기 메시지 | 이후 미반복, 무해 판정 |
📝 마무리
이번 글에서는 1편에서 구축한 KEDA 위에,
Redis + Prometheus 멀티 트리거 ScaledObject를 설계하는 과정을 정리해 봤습니다.
스케일 대상으로는 Airflow Celery Worker를 예시로 삼았고,
Spark Executor는 /scale 미지원 제약 때문에 DynamicAllocation으로 우회하되,
statsd → ServiceMonitor → KEDA로 이어지는 파이프라인을 통해
Worker와 같은 메트릭 기준에 정렬시키는 "메트릭 표준화" 전략을 택했습니다.
특히 여기서 정리한 세 가지 설계 원칙은 Airflow가 아닌 다른 워크로드에도 그대로 적용됩니다.
- maxReplicaCount·listLength 같은 값은 감이 아니라 실측(worker_concurrency=16)을 기준으로 계산한다
- Redis(선행: 큐 길이) + Prometheus(후행: 대기시간) 멀티 트리거로, 스케일업은 공격적·다운은 보수적으로 비대칭 설계한다
- 정규식 쿼리(=~"submit_spark.*")에 의존한다면, 그 전제가 되는 명명규칙을 팀 차원에서 강제한다
정도가 되겠습니다.
참고로 이번에 남은 과제였던 maxReplicaCount=19 풀스케일 테스트는,
노드 자원 포화와 podAntiAffinity(required) 제약 때문에 자원 여유를 확보한 뒤로 미뤄둔 상태입니다.
이 부분은 자원 확보 후 별도로 정리하겠습니다.
다음 글에서는 플랫폼의 다음 스택으로,
시크릿(Secret)을 안전하게 관리하기 위한 Sealed Secrets와 Infisical 구축 과정을 다뤄보려고 합니다.
이번 글에서 Redis 비밀번호를 매니페스트에 평문으로 넣었던 부분(마스킹 처리한 그 값)을,
다음 편에서 제대로 된 시크릿 관리 체계로 옮기는 이야기를 이어가겠습니다.
궁금한 점이나 추가로 다뤄줬으면 하는 내용이 있다면 언제든지 편하게 말씀해 주세요! 😊
'[ Infra ] > Data Platform' 카테고리의 다른 글
| [Data Platform] KEDA 구축 가이드(Operator 설치부터 API 연동용 RBAC까지) (0) | 2026.07.10 |
|---|---|
| [Data Platform] ArgoCD GitOps 운영 가이드(App of Apps 패턴으로 플랫폼 관리) (0) | 2026.07.07 |
| [Data Platform] ArgoCD 구축 가이드 (Helm + Private Registry + Ingress 구성) (0) | 2026.07.06 |
| [Data Platform] Superset 구축 가이드 (feat. Trino 연동) (0) | 2026.06.10 |
| [Data Platform] Prometheus + Grafana 구축 가이드 (feat. kube-prometheus-stack) (0) | 2026.06.09 |