어느날 나의 배치가 멈췄습니다. - K8S Command line Health Check 방식 적용기

들어가며
OS EOS된 장비를 최근에 이전 했습니다.
이전 후 문제가 없었으나, 사실 그건 폭풍전야 였습니다.
이전이 끝나고 약 일주일 뒤, 관제센터에서 연락이 옵니다.
"XXX 데이터가 적용되지 않았습니다. 확인 부탁드립니다."
뭔가 처리 중에 꼬였나 싶어서, Sentry나 에러 로그를 봐도 특이사항이 없었습니다.
그리고 전체 로그를 보는데, "처음에는 03:00"에 멈춰있었고 그때 당시 시간이 "09시" 쯤 이었다보니, "UTC로 바뀌면서 문제가 생겼나?" 하고 살펴 보는데 시간대는 죄가 없었습니다 10분 마다 시작 하는 배치 였거든요.

등에 땀이 주루룩 흐르면서 아차 싶었습니다. 바로 **배치가 작업중에 멈춘(행) 것이었습니다. **
이상했습니다. 컨테이너는 살아 있고, 리소스 사용량도 정상이었으며 로그도 더 이상 출력되지 않았습니다. 겉보기엔 멀쩡하지만, 안에서는 루프가 멈춰 있는 상태였던 것이죠.
근본적인 원인은 다른 방안을 통해 해결 하는데, 일단 이 문제에 대해 모니터링이 미흡 했던 부분을 해소 해보려고 했습니다.
이번 글에서는 무한 루프 기반 작업이 멈췄는지 감지하는 방법과, Kubernetes의 livenessProbe를 활용한 자동 복구 방법을 소개합니다.
🎯 문제 정의
- 무한 루프를 돌며 배치 작업을 수행하는 Python 워커
- 하지만 작업이 멈추거나 예외로 루프가 정지해도, 컨테이너는 정상 상태로 간주됨
- Kubernetes의 기본 헬스 체크로는 이런 문제 감지가 어려움
💡 해결 아이디어
- 정상적으로 루프가 동작 중이라면, 주기적으로 현재 시간(timestamp) 을 특정 파일에 기록
- Kubernetes는 주기적으로 해당 타임스탬프와 현재 시간의 차이를 계산해, 일정 시간 이상 멈춰 있으면 컨테이너를 재시작
🔧 구현 방법
1. Python에서 heartbeat 기록
import time
def write_heartbeat(path="/tmp/heartbeat"):
with open(path, "w") as f:
f.write(str(int(time.time())))
def main():
while True:
# 실제 작업 로직
process_job()
# 헬스 체크를 위한 heartbeat 기록
write_heartbeat()
# 주기 설정 (예: 30초)
time.sleep(30)
def process_job():
# 여기에 작업 로직 작성
print("작업 실행 중...")
if __name__ == "__main__":
main()
- /tmp/heartbeat에 현재 시간을 기록합니다.
- 기록 주기는 Kubernetes에서 체크하는 주기보다 짧거나 같게 유지해야 합니다.
2. Kubernetes livenessProbe 설정
livenessProbe:
exec:
command:
- /bin/sh
- -c
- test $(($(date +%s) - $(cat /tmp/heartbeat))) -lt 90
initialDelaySeconds: 10
periodSeconds: 30
- 현재 시간과 heartbeat 파일의 시간 차가 90초 미만이면 정상
- 90초 이상 heartbeat가 갱신되지 않으면 비정상 → 컨테이너 재시작
⚠️ 주의 사항
- write_heartbeat() 호출이 작업 실패나 예외 등으로 인해 실행되지 않을 경우, Kubernetes가 자동으로 감지하고 재시작합니다.
- /tmp/heartbeat는 컨테이너 내부 경로이므로, Pod 내 다른 컨테이너와는 공유되지 않습니다.
- 실제 배치 주기보다 heartbeat 기록 주기를 조금 더 짧게 설정하는 것이 좋습니다.
🧩 맺음말

비교적, API 서비스에 대해서만 pod health check를 신경 쓰고, 당연히 배치는 누락 되었다는 점을 다시 한번 반성하게 되는 사건이 됩니다.
다행히도 좋은 방법론을 찾아 모니터링을 통해 빠르게 감지 및 복구가 가능하도록 도와주었습니다.
복잡한 방식이 아니더라도 간단한 파일 기록을 통해, 서비스 장애에 대해 모니터링 할 수 있는 방법 입니다.
비슷한 형태 (K8S + 무한 루프 배치)로 운영중이시라면, 꼭 이 방법을 적용 해보시길 바라고,
그 외에도 배치의 헬스체크를 소월하게 한것은 아닌지 돌아보시면 좋을 것 같습니다.