K8s 망가뜨리기 — 범인은 내 YAML · 살아 있음과 받을 준비가 됨 · 이론
살아 있음과 받을 준비가 됨
한 줄 요약
readiness 실패는 트래픽을 받을 자격을 잃는 것이며, 컨테이너 프로세스가 종료됐다는 뜻은 아닙니다.
왜 이게 필요했나
서비스가 시작할 때 데이터나 캐시를 읽는 데 시간이 걸린다고 합시다. 프로세스는 살아 있지만 아직 정상 요청을 처리할 준비가 안 됐습니다. 이 상태에서 계속 요청을 보내면 고객에게 오류를 돌려주고, 무조건 재시작하면 준비 작업을 처음부터 다시 시작할 수 있습니다. 그래서 프로세스의 생존, 초기 기동 완료, 트래픽 수신 가능 여부를 구분할 필요가 있습니다.
쿠버네티스의 liveness·startup·readiness 프로브는 그 구분을 표현하는 도구입니다. liveness는 재시작 판단에, startup은 느린 기동 구간을 보호하는 데, readiness는 서비스 트래픽을 받을 수 있는지 판단하는 데 사용합니다. 프로브 이름만 외우는 것보다 “실패했을 때 무엇이 바뀌는가”를 물어야 합니다. 이 실습에는 readiness만 있으므로 실패를 liveness에 의한 재시작으로 설명하면 관측과 모순됩니다.
어떻게 동작하나
실습 앱은 8080번의 / 경로에서 정해진 본문을 반환합니다. 정상 readiness도 같은 /를 검사합니다. readiness의 path만 /missing으로 바꾸면 앱 자체는 여전히 / 요청을 처리하지만, 프로브는 존재하지 않는 경로의 HTTP 404를 받습니다. Pod는 Running일 수 있어도 컨테이너 ready는 false가 됩니다. Service의 EndpointSlice에 주소가 남아 있더라도 ready 조건이 false인 대상은 일반적인 서비스 트래픽의 준비된 대상이 아닙니다.
GET PodIP:8080/ → 200, 앱은 살아 있다readiness /missing → 404, 수신 준비 조건은 실패한다Pod phase → Running일 수 있다container ready → falseService의 Ready 대상 → 0이 다섯 줄이 함께 있으면 “앱이 죽어서 서비스가 멈췄다”보다 “프로브 계약이 실제 경로와 달라 트래픽 대상에서 빠졌다”가 더 잘 맞는 설명입니다. 그러나 과거 Pod의 404 이벤트를 현재 Pod의 원인으로 가져오면 안 됩니다. 템플릿 변경으로 Pod가 교체되므로 이름과 UID를 함께 보고 현재 Pod의 이벤트인지 확인합니다. 오래된 이벤트는 장애가 있었다는 참고 자료이지 현재 원인을 자동으로 증명하지 않습니다.
readiness 실패만으로 같은 컨테이너가 재시작되지는 않습니다. 이 실습은 현재 Pod의 restartCount가 0인 상태와 직접 HTTP 성공을 함께 관측합니다. 템플릿의 readiness 경로를 바꾸는 동작 자체가 새로운 Pod를 만드는 것과, 프로브 실패가 컨테이너를 반복 재시작하는 것을 혼동하지 마세요. 새 Pod UID가 생긴 것은 Deployment 변경의 결과이고, 그 새 Pod 안의 restartCount는 컨테이너 재시작의 기록입니다.
일반적인 Deployment는 RollingUpdate를 사용합니다. 새 파드가 준비되지 않으면 이전의 정상 파드가 남아 요청을 계속 처리할 수 있습니다. 이것은 장애가 없다는 뜻이 아니라 롤아웃이 막혔지만 기존 버전이 서비스를 지키는 상황입니다. 이 코스에서는 단일 replica와 Recreate를 사용해 이전 파드가 실험의 증상을 가리지 않게 했습니다. 무중단 운영을 위한 권장 설정이 아니라 인과관계를 관찰하기 위한 통제 조건입니다.
다른 설정을 모두 같은 상태로 두고 한 가지를 바꾸는 이유도 여기에 있습니다. readiness 경로와 Service 선택자를 동시에 틀리게 하면 Ready 대상이 0인 이유가 두 개가 됩니다. 하나만 복구해도 요청이 돌아오지 않아 학습자가 복구 명령 자체를 의심할 수 있습니다. 먼저 선택자 실험을 완전히 복구한 뒤 readiness 실험으로 넘어가세요. 복합 장애는 각각의 단일 장애를 구별할 수 있게 된 다음의 과제입니다.
현장에서 만나는 모습
새 버전에서 건강 확인 경로가 /health에서 /ready로 바뀌었는데 배포 설정이 예전 경로를 유지할 수 있습니다. 앱의 주 업무 요청은 정상인데 새 파드만 Ready가 되지 않습니다. 이때 프로브를 지워 초록색으로 만드는 것은 원인 해결이 아닐 수 있습니다. 실제로 트래픽 수신 가능 여부를 판단하던 보호 장치를 없앤 것이기 때문입니다. 앱과 배포 설정이 합의한 경로를 맞추고 상태가 바뀌는지 확인해야 합니다.
반대로 프로브가 실제 의존성의 장애를 정직하게 드러내는 경우도 있습니다. 데이터베이스를 사용할 수 없는데 readiness만 무조건 200을 반환하도록 고치면, 체크는 통과하지만 고객 요청은 계속 실패합니다. 프로브는 서비스 계약의 축약판입니다. 어떤 의존성을 포함할지, 일시적인 오류에 얼마나 민감하게 반응할지, 검사 비용이 얼마나 드는지는 서비스 특성에 따라 설계해야 합니다. 한 실습의 /를 모든 서비스에 복사하는 것은 답이 아닙니다.
readiness와 liveness가 같은 무거운 업무 API를 호출하면 부하가 커지고, 의존 서비스가 잠깐 느려졌을 뿐인데 여러 파드가 함께 재시작되는 악순환을 만들 수 있습니다. 이 코스는 그런 연쇄 장애를 운영 클러스터에 주입하지 않습니다. 다만 두 프로브가 다른 판단을 담당한다는 것을 배워야 이후에 임계값과 실패 정책을 논의할 수 있습니다. 검사 주기를 짧게 했다는 이유만으로 장애 대응이 항상 빨라지거나 안전해지는 것도 아닙니다.
관측을 보고 문장을 쓰는 연습을 해 보세요. “쿠버네티스가 고장났다” 대신 “현재 Pod는 Running이고 직접 / 요청은 성공하지만, 해당 Pod의 readiness /missing이 404이며 Ready Endpoint는 0개다”라고 기록합니다. 후자의 문장은 다음 사람이 같은 요청을 해 보고 반박하거나 확인할 수 있습니다. 원인을 서둘러 단정하지 않으면서도 다음 확인의 범위를 줄입니다.
다음 확인에서 할 것
퀴즈에서 Pod 교체와 컨테이너 재시작, 프로브의 목적과 결과를 분리합니다. 실습 4~5단계에서는 잘못된 readiness 경로와 복구를 각각 저장합니다. 관측 도구의 성공은 해당 실험 조건이 재현됐다는 뜻이며, 그 도구가 프로브를 자동으로 고쳐 주었다는 뜻이 아닙니다. 마지막에는 원인과 예방책을 보고서에서 연결합니다.