내가 부순다 — 가설을 먼저 쓰는 카오스 실험실 · 가설·측정·결론을 각각 다른 시점에 남긴다 · 실습
망가뜨리기 실험실 — 다섯 번 부수고 한 번 고친다
목표
임시 VM 안의 진짜 k3s 위에서 다섯 번의 카오스 실험을 합니다. 정상 기준선을 재고,
다섯 실험의 가설을 부수기 전에 한꺼번에 적고, Pod 를 죽이고 CPU 를 조이고
메모리를 말린 뒤, 배운 것을 설계에 반영해 같은 공격을 다시 받습니다. kubectl 의
기본 조회와 Deployment 구조를 아는 중급 학습자를 위한 65분 실험입니다.
왜 중요한가
장애를 주입하는 일 자체는 명령 한 줄입니다. 어려운 것은 그 실험이 **다음 주에도
남는 무언가**를 만들게 하는 일입니다. 그래서 이 실습의 산출물은 고장이 아니라
노트입니다. 가설은 실험 전에 적고, 측정은 실험 창 안에서 하고, 결론은 둘을 견준
결과로 적습니다. 예상이 빗나가는 것은 실패가 아닙니다 — 반증된 가설이야말로
그 실험이 벌 수 있는 가장 비싼 정보이고, 그것을 refuted 라고 적는 것이 정답입니다.
판정 표 (결론에서 쓸 이름)
같은 숫자를 사람마다 다르게 읽지 않도록 이름 붙이는 규칙을 먼저 정해 둡니다.
- 가용성: 성공률 0.98 이상이면
ok, 0.5 이상이면degraded, 그 아래면down - 지연: 성공한 지연 표본이 5건 미만이면
unmeasured, - 판정: 가설의 두 값이 관측한 두 값과 모두 같으면
confirmed, 하나라도 다르면refuted
p95 가 기준선 p95 의 2배 이상이면 slower, 아니면 same
측정 도구
python3 /opt/fixtures/chaos_lab.py 는 세 가지만 합니다. **고장을 대신 내주지도,
고쳐 주지도 않습니다.**
load <초> <원시.json>— Service 로 두 갈래 부하를 보냅니다. 가용성은 정적 경로/에record <국면> <원시.json> <기록.json>— 부하 결과와 그 순간의 클러스터를 묶어 남깁니다.grade— 채점기가 씁니다.
초당 10회, 지연은 CPU 를 쓰는 /cgi-bin/work 에 초당 2회. 배경으로 띄워 두고 그 창
안에서 고장을 내세요.
요청한 국면의 구조 조건이 실제로 성립하지 않으면 기록을 거절합니다.
안전 범위
임시 VM 안의 API https://127.0.0.1:6443 과 labhub-chaos 네임스페이스만 씁니다.
운영 클러스터나 다른 사람의 환경에서는 절대 실행하지 마세요. 제공 앱은 원인을 하나만
남기기 위해 Recreate 전략을 씁니다 — 무중단 운영 권장값이라는 뜻이 아닙니다.
앱 이미지는 digest 로 고정되어 있습니다.
이 실습은 65분으로 잡혀 있어 기본 세션(60분)보다 깁니다. 시작할 때 미리 시간을
연장하세요. 세션이 끝나면 VM 과 기록 파일은 사라지고 되살릴 수 없습니다.
기록 파일은 편집 가능한 실험 노트이지 위조 불가능한 증거가 아닙니다.
단계
1. /opt/fixtures/chaos-lab-app.json 을 적용하고 롤아웃이 끝나기를 기다린 뒤, 아무것도 건드리지 않은 상태로 20초 부하를 걸어 기준선을 기록하세요. python3 /opt/fixtures/chaos_lab.py load 20 /root/chaos-lab/raw-01.json 으로 재고 python3 /opt/fixtures/chaos_lab.py record steady /root/chaos-lab/raw-01.json /root/chaos-lab/01-steady.json 으로 남깁니다.
2. 기준선 파일에서 성공률과 p95 를 읽어 steady_state 에 정상 상태를 적고, 다섯 실험(kill-one · kill-ha · cpu-squeeze · mem-squeeze · hardened)의 가설을 /root/chaos-lab/hypothesis.json 에 쓰세요. 실험마다 availability, latency, 왜 그렇게 예상하는지(why), 언제 멈출지(abort_if) 네 가지가 필요합니다. availability_ratio_min 은 0.95 이상이면서 기준선 측정값 이하, p95_ms_max 는 기준선 p95 이상 그 3배 이하로 잡습니다.
3. 복제본이 1인 상태에서 부하를 배경으로 띄우고, 측정 창 안에서 그 하나뿐인 Pod 를 지우세요. 창이 닫히면 python3 /opt/fixtures/chaos_lab.py record kill-one /root/chaos-lab/raw-03.json /root/chaos-lab/03-kill-one.json 으로 남깁니다. 자원 한계와 preStop 은 기준선 그대로 두세요.
4. 복제본을 3으로 늘려 셋이 모두 Ready 가 된 뒤, 같은 방식으로 부하 창 안에서 Pod 를 정확히 하나만 지우세요. python3 /opt/fixtures/chaos_lab.py record kill-ha /root/chaos-lab/raw-04.json /root/chaos-lab/04-kill-ha.json 으로 남깁니다. 복제본 수 말고는 아무것도 바꾸지 않습니다.
5. shop 컨테이너의 cpu 한계만 100m 으로 낮추세요(memory 는 96Mi, 복제본은 3 그대로). 롤아웃이 끝나고 셋이 모두 Ready 가 된 뒤에 20초 부하를 걸고 python3 /opt/fixtures/chaos_lab.py record cpu-squeeze /root/chaos-lab/raw-05.json /root/chaos-lab/05-cpu-squeeze.json 으로 남깁니다.
6. cpu 한계를 500m 으로 되돌리면서 memory 한계를 40Mi 로 낮추세요. 앱은 기동할 때 48MiB 를 한 번에 잡으므로 컨테이너가 OOM 으로 죽습니다. 재시작이 잡히면 20초 부하를 걸고 python3 /opt/fixtures/chaos_lab.py record mem-squeeze /root/chaos-lab/raw-06.json /root/chaos-lab/06-mem-squeeze.json 으로 남깁니다.
7. 자원 한계를 정상값(cpu 500m · memory 96Mi)으로 되돌리면서, 이번에는 종료 처리를 더하세요. preStop 훅으로 최소 3초를 벌고 terminationGracePeriodSeconds 를 10 이상으로 올립니다. 롤아웃이 끝나면 3단계·4단계와 같은 공격을 다시 하고 python3 /opt/fixtures/chaos_lab.py record hardened /root/chaos-lab/raw-07.json /root/chaos-lab/07-hardened.json 으로 남깁니다.
8. 다섯 기록의 숫자에 지시문의 판정 표대로 이름을 붙여 /root/chaos-lab/conclusion.json 에 쓰세요. 실험마다 observed_availability, observed_latency, 가설과 견준 verdict(confirmed 또는 refuted), 그리고 이 결과로 무엇을 바꿀지(action)가 필요합니다. 마지막 채점은 앞선 기록과 지금 클러스터를 함께 봅니다 — 고친 설계가 살아 있어야 합니다.
참고
kubectl -n labhub-chaos get pods,svc,endpointslices -o wide로 대상과 상태를 나누어 보세요.kubectl -n labhub-chaos get rs는 지나간 배포의 흔적입니다. 마지막 채점이 이것을 봅니다.kubectl -n labhub-chaos describe pod <이름>의 종료 이유와 종료 코드를 확인하세요.- 부하는 배경으로(
&) 띄우고, 고장을 낸 뒤wait로 창이 닫히기를 기다린 다음 기록합니다. - 기준선을 다시 재야 한다면 앞 단계로 돌아가도 됩니다. 다만
hypothesis.json은 고치지 마세요. - 한계 값은
limits뿐 아니라requests와의 관계도 봅니다. 한계가 요청량보다 작으면 거절됩니다.
단계 8개
- 부수기 전에 「정상」을 숫자로 남긴다
- 다섯 개의 가설을 먼저 적는다
- 복제본 하나짜리 서비스를 죽여 본다
- 복제본을 셋으로 늘리고 같은 공격을 반복한다
- CPU 를 조인다 — 죽지 않고 느려지는 고장
- 메모리를 말린다 — 이번에는 죽는다
- 배운 것을 설계에 반영하고 같은 공격을 다시 받는다
- 가설과 측정을 견주어 실험 노트를 닫는다