내가 부순다 — 가설을 먼저 쓰는 카오스 실험실 · 「정상」을 숫자로 적지 않으면 그냥 사고다 · 이론
「정상」을 숫자로 적지 않으면 그냥 사고다
한 줄 요약
부수기 전에 「정상」이 숫자로 적혀 있어야 한다. 그 숫자가 없으면 실험은 사고와 구별되지 않는다.
왜 이게 필요했나
운영 회고에서 가장 자주 나오는 말이 "그때는 좀 느렸어요" 다. 좀 느렸다는 것이
얼마나 느린 것인지, 평소에는 얼마였는지 아무도 말하지 못한다. 그 상태에서
장애를 하나 주입하면 무슨 일이 벌어질까. 화면이 빨개지고, 사람들이 몰려오고,
누군가 롤백을 누르고, 그리고 아무도 무엇을 배웠는지 말하지 못한다. 그것은
실험이 아니라 그냥 사고다.
카오스 엔지니어링이 다른 점은 부순다는 데 있지 않다. **부수기 전에 무엇을 재고
있을지, 무엇이 일어날 것이라 믿는지, 언제 멈출지를 먼저 글로 적어 둔다**는 데
있다. [카오스 엔지니어링 원칙](https://principlesofchaos.org/)이 첫 항목으로
"시스템의 정상 동작을 측정 가능한 출력으로 정의하라" 를 두는 이유가 이것이다.
내부 상태(CPU 사용률, 힙 크기)가 아니라 바깥에서 보이는 출력 — 요청이
성공하는 비율, 응답이 돌아오는 시간 — 으로 정의하라고 못 박는다. 내부 지표는
장애가 아닌데도 흔들리고, 진짜 장애인데도 멀쩡해 보일 때가 있기 때문이다.
어떻게 동작하나
정상 상태는 보통 두 축으로 적는다. 가용성과 지연이다. 이 둘은 서로
다른 축이라 함께 적어야 한다. 요청의 99.9%가 성공해도 p95 응답이 3초면 사용자는
고장이라고 느끼고, 반대로 응답은 20밀리초인데 스무 번에 한 번 실패하면 그것도
고장이다. 한 축만 보면 실험 결과의 절반을 못 본다.
지연은 평균이 아니라 분위수로 적는다. 평균은 느린 꼬리를 희석해 버린다.
요청 백 건 중 다섯 건이 2초, 나머지가 20밀리초면 평균은 120밀리초라 멀쩡해
보이지만, p95 는 2초라 문제가 그대로 드러난다. 사용자는 평균을 겪지 않는다.
자기 요청 하나를 겪는다.
정상 상태 기술의 예 (이 코스의 실습에서 실제로 쓰는 형식) availability_ratio_min : 0.98 20초 동안 정적 경로 200회 중 196회 이상 성공 p95_ms_max : 70 CPU 를 쓰는 경로의 95분위 응답이 70밀리초 이하그리고 중단 조건을 함께 적는다. "성공률이 절반 밑으로 내려가면 즉시
되돌린다" 같은 문장이다. 실험 도중에는 판단이 흐려진다. 조금만 더 보면 원인이
보일 것 같고, 되돌리면 다시 세팅하기가 귀찮다. 그 순간을 대비해 **차분할 때
써 둔 문장**이 필요하다.
마지막으로 폭발 반경(blast radius) 을 정한다. 복제본 하나만, 한 네임스페이스
안에서만, 트래픽의 1%만. 실험은 가설을 확인할 만큼만 크면 되고, 그보다 크면
얻는 것 없이 위험만 커진다.
측정 창의 길이와 표본 수도 미리 정해 둔다. 창이 너무 짧으면 복구가 빠른 장애를
통째로 놓치고, 표본이 너무 적으면 한 건의 실패가 성공률을 5%씩 흔들어 무엇을
봐도 유의해 보인다. 이 코스의 실습은 20초 창에 초당 10회의 가용성 요청을 보내
200건을 모은다. 한 건 실패가 0.5%에 해당하니, 0.98 이라는 경계가 "네 건까지는
괜찮다" 는 뜻이 되어 해석이 분명해진다. **경계의 숫자보다 그 숫자가 몇 건에
해당하는지를 아는 것**이 실험을 읽는 감각을 만든다.
현장에서 만나는 모습
쿠버네티스에서는 「정상」이 여러 겹으로 갈라져 있어서 더 조심해야 한다. Pod 가Running 인 것과 Ready 인 것은 다른 사실이고, Ready 인 것과 Service 의
엔드포인트에 실려 트래픽을 받는 것도 또 다른 사실이다. 컨테이너의 준비 상태는
readinessProbe 가 정하고, 그 결과는
[Pod 의 컨디션](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/)으로
드러난다. 초록불 세 개가 켜져 있어도 사용자의 요청은 실패할 수 있다.
그래서 실전에서는 클러스터 상태를 "정상 상태" 로 삼지 않는다. **바깥에서 실제
요청을 보내 본 결과**를 정상 상태로 삼고, 클러스터 상태는 그것을 설명하는
보조 증거로 쓴다. 이 순서를 뒤집으면, 대시보드는 전부 초록인데 고객센터만
바빠지는 익숙한 장면이 만들어진다.
기준선을 잴 때 흔히 저지르는 실수가 하나 더 있다. **아직 안정되지 않은 상태를
기준선으로 잡는 것**이다. 방금 배포한 직후에는 캐시가 비어 있고 이미지가 막
내려온 참이라 응답이 평소보다 느리다. 그 숫자를 기준선으로 삼으면 뒤에 하는
모든 비교가 헐거워진다. 롤아웃이 끝나고 프로브가 안정된 뒤에 재는 것, 그리고
기준선을 재는 동안에는 아무것도 건드리지 않는 것 두 가지를 지켜야 한다.
이 실습의 기록 도구가 기준선 측정 창 안에서 새 Pod 가 생기면 기록을 거절하는
이유도 같다.
한 가지 더 덧붙이면, 정상 상태는 팀이 합의한 문장이어야 한다. 혼자 정한
기준은 사건이 났을 때 반드시 흔들린다. "p95 70밀리초" 라는 숫자가 어디서
나왔는지, 왜 60도 100도 아닌지 설명할 수 있어야 하고, 그 설명은 대개 "평소에
재 보니 33밀리초였고 두 배까지는 사용자가 못 느낀다" 같은 **실측과 판단의
조합**이다. 숫자만 있고 근거가 없는 기준은 다음 분기에 아무 이유 없이 바뀐다.
다음 퀴즈에서 확인할 것
정상 상태를 왜 바깥에서 보이는 출력으로 정의하는지, 지연을 왜 평균이 아니라
분위수로 적는지, 중단 조건과 폭발 반경이 실험에서 각각 어떤 역할을 하는지
확인한다.