컨테이너 라이프사이클 훅
컨테이너 라이프사이클 훅 (Container Lifecycle Hooks)
이 페이지는 kubelet이 관리하는 컨테이너가 컨테이너 라이프사이클 훅 프레임워크를 이용해, 관리 라이프사이클 중 발생하는 이벤트로 트리거되는 코드를 실행하는 방법을 설명해요.
개요
많은 언어 프레임워크(Angular 같은)가 컴포넌트 라이프사이클 훅을 갖는 것처럼, Kubernetes도 컨테이너에 라이프사이클 훅을 제공해요. 이 훅 덕분에 컨테이너는 자신의 관리 라이프사이클에서 발생하는 이벤트를 인지하고, 해당 훅이 실행될 때 핸들러에 구현된 코드를 실행할 수 있어요.
컨테이너 훅
컨테이너에 노출되는 훅은 다음과 같아요.
-
PostStart: 컨테이너가 생성된 직후 실행돼요. 컨테이너의ENTRYPOINT(메인 프로세스)와 동시에 실행되므로, 메인 프로세스가 시작되기 전·중·후 어느 때든 실행될 수 있어요. 핸들러에 전달되는 파라미터는 없어요. 훅이 컨테이너 프로세스와 동시에 실행되는 동안 컨테이너 상태 업데이트를 지연시킬 수 있고, 훅이 끝날 때까지Running상태로 전환되지 않을 수 있어요. -
PreStop: API 요청이나 관리 이벤트(예: liveness/startup probe 실패, preemption, 리소스 경합)로 컨테이너가 종료되기 직전에 호출돼요. 훅이 완료돼야 컨테이너를 멈추는 TERM 신호를 보낼 수 있어요. Pod의 termination grace period 카운트다운은PreStop훅 실행 전에 시작되므로, 핸들러 결과와 무관하게 컨테이너는 결국 그 기간 안에 종료돼요. -
StopSignal: 컨테이너가 멈출 때 보낼 종료 신호를 정의할 수 있어요. 설정하면 컨테이너 이미지에 정의된STOPSIGNAL지시문을 덮어써요.
훅 핸들러 구현
컨테이너는 훅에 대한 핸들러를 구현·등록해 접근할 수 있어요. 세 가지 유형이 있어요.
- Exec: 컨테이너의 cgroups와 네임스페이스 안에서 특정 명령(예:
pre-stop.sh)을 실행해요. - HTTP: 컨테이너의 특정 엔드포인트에 HTTP 요청을 실행해요.
- Sleep: 컨테이너를 지정된 시간 동안 일시 중지해요.
훅 핸들러 실행
라이프사이클 훅이 호출되면 httpGet, tcpSocket, sleep은 kubelet 프로세스가 실행하고, exec는 컨테이너 안에서 실행돼요.
PostStart 훅은 컨테이너 생성 시 ENTRYPOINT와 동시에 트리거돼요. PostStart 훅이 너무 오래 걸리거나 멈추면 컨테이너가 running 상태로 전환되지 못할 수 있어요.
PreStop 훅은 컨테이너 중지 신호와 비동기로 실행되지 않아요. 훅이 멈추면 Pod는 Terminating 상태에 머물다가 terminationGracePeriodSeconds가 만료된 뒤 종료돼요. 예를 들어 terminationGracePeriodSeconds가 60이고 훅이 55초 걸리고 컨테이너가 정상 종료에 10초 걸린다면, 총 65초가 필요하므로 컨테이너는 정상 종료 전에 강제 종료돼요.
PostStart 또는 PreStop 훅이 실패하면 컨테이너를 종료해요. 훅 핸들러는 가능한 한 가볍게 만드는 게 좋아요.
훅 전달 보장
훅 전달은 최소 한 번(at least once) 을 목표로 해요. 즉 어떤 이벤트에 대해 훅이 여러 번 호출될 수 있으니, 구현에서 이를 올바르게 처리해야 해요. 대개는 한 번만 전달되지만, kubelet이 훅 전송 중 재시작하면 드물게 다시 전송될 수 있어요.
훅 핸들러 디버깅
훅 핸들러 로그는 Pod 이벤트에 노출되지 않아요. 실패하면 FailedPostStartHook 또는 FailedPreStopHook 이벤트가 발생해요. kubectl describe pod lifecycle-demo로 그 이벤트를 확인할 수 있어요.
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 7s default-scheduler Successfully assigned default/lifecycle-demo to ip-XXX...
Normal Pulled 6s kubelet Successfully pulled image "nginx" in 229.604315ms
Warning FailedPostStartHook 4s (x2 over 5s) kubelet Exec lifecycle hook ([badcommand]) ... failed - error: ...
Normal Killing 4s (x2 over 5s) kubelet FailedPostStartHook
Warning BackOff 2s (x2 over 3s) kubelet Back-off restarting failed container