컨테이너 라이프사이클 훅

컨테이너 라이프사이클 훅 (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

더 알아보기 (Learn more)