왜 배포 전에 카오스 실험이 필요한가
스테이징에서 통합 테스트가 모두 통과해도, 실제 장애는 네트워크 지연·의존 서비스 타임아웃·파드 강제 종료 같은 비정상 조건에서 발생한다. 이런 조건은 일반 테스트가 재현하지 않기 때문에 문제가 프로덕션에서 처음 드러난다. 카오스 실험을 CI/CD 파이프라인의 게이트로 넣으면, 회복탄력성을 배포 승인 조건으로 강제할 수 있다. 핵심은 "실험을 돌린다"가 아니라 "정상 상태(steady state) 가설이 깨지면 배포를 막는다"는 것이다.
정상 상태 가설을 먼저 정의한다
게이트의 판단 기준은 임의의 감이 아니라 측정 가능한 SLI여야 한다. 예를 들어 "주입 중에도 p99 지연 < 500ms, 에러율 < 1%"처럼 명시한다. 이 가설이 실험 전·중·후 모두 유지되면 통과, 아니면 실패로 처리한다.
| 실험 유형 | 주입 대상 | 정상 상태 SLI |
|---|---|---|
| 지연 주입 | DB 커넥션 | p99 < 500ms |
| 파드 종료 | 서비스 레플리카 1개 | 에러율 < 1% |
| 의존성 차단 | 외부 API | 폴백 응답률 > 99% |
실험 명세를 코드로 관리한다
실험은 선언형으로 리포지토리에 두어 리뷰·버전관리 대상으로 만든다. 아래는 LitmusChaos 스타일의 파드 삭제 실험 예시다.
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: checkout-pod-delete
spec:
appinfo:
appns: prod-canary
applabel: "app=checkout"
experiments:
- name: pod-delete
spec:
components:
env:
- name: TOTAL_CHAOS_DURATION
value: "60"
- name: PODS_AFFECTED_PERC
value: "50"
probe:
- name: latency-check
type: httpProbe
httpProbe/inputs:
url: http://checkout/healthz
responseTimeout: 500
runProperties:
probeTimeout: 5
interval: 2
retry: 3
probe가 정상 상태 가설의 역할을 한다. probe가 실패하면 실험 결과가 Fail로 기록된다.
파이프라인 게이트로 연결한다
실험을 캐너리 환경에 적용한 뒤 결과를 폴링해서 승인 여부를 결정한다. 결과가 Pass가 아니면 파이프라인을 실패시켜 배포를 중단한다.
#!/usr/bin/env bash
set -euo pipefail
kubectl apply -f chaos/checkout-pod-delete.yaml
for i in $(seq 1 30); do
verdict=$(kubectl get chaosresult checkout-pod-delete-pod-delete \
-n prod-canary -o jsonpath='{.status.experimentStatus.verdict}' 2>/dev/null || echo "")
case "$verdict" in
Pass) echo "chaos gate passed"; exit 0 ;;
Fail) echo "chaos gate FAILED - blocking deploy"; exit 1 ;;
*) echo "waiting... ($i)"; sleep 10 ;;
esac
done
echo "timeout: verdict not resolved"; exit 1
어디에 게이트를 둘 것인가
모든 병합마다 카오스를 돌리면 파이프라인이 느려지고 비용이 커진다. 실무에서는 프로덕션 트래픽의 일부만 받는 캐너리 단계에 게이트를 두는 것이 효과적이다. 전체 승격 직전, 캐너리에서 실험을 돌려 통과해야만 100% 롤아웃을 진행한다. PR 단계에서는 가벼운 지연 주입만, 릴리스 후보에는 파드 종료·의존성 차단까지 단계적으로 확대한다.
블라스트 반경을 통제한다
게이트 자동화의 최대 리스크는 실험 자체가 사고를 내는 것이다. 반드시 지켜야 할 안전장치는 세 가지다. 첫째, PODS_AFFECTED_PERC나 대상 네임스페이스로 블라스트 반경을 명시적으로 제한한다. 둘째, probe가 임계치를 넘으면 실험 프레임워크가 스스로 중단하도록 abort 조건을 건다. 셋째, 게이트 스크립트에 타임아웃과 반드시 실행되는 정리(cleanup) 단계를 넣어 실험 리소스가 캐너리에 남지 않게 한다. 프로덕션 100% 트래픽에는 자동 게이트를 걸지 않고, 사전 승인된 게임데이로만 실행하는 것이 안전하다.
결과를 신호로 축적한다
게이트의 통과/실패는 일회성 판단으로 끝내지 말고 저장해 추세를 본다. 반복 실패하는 실험은 아키텍처 약점을 가리킨다.
SELECT experiment,
COUNT(*) AS runs,
ROUND(100.0 * SUM(CASE WHEN verdict='Fail' THEN 1 ELSE 0 END) / COUNT(*), 1) AS fail_pct
FROM chaos_gate_results
WHERE ts >= NOW() - INTERVAL '30 days'
GROUP BY experiment
ORDER BY fail_pct DESC;
실패율이 높은 실험을 우선순위로 폴백·타임아웃·리트라이 설계를 보강하면, 게이트는 배포 차단 장치를 넘어 회복탄력성 개선의 백로그 생성기가 된다.