쿠버네티스

쿠버네티스 pod graceful shutdown

알쓸개잡 2023. 8. 6.
pod 내의 container를 종료 시 남아있는 처리를 모두 완료 후에 종료하는 처리가 있다.
물론 application 내에서 종료시 남아있는 처리를 프로그래밍으로 처리할 수도 있겠지만 pod 정의 명세서 상에서 lifecycle.preStop을 활용하여 gracefully  shutdown을 구현할 수 있다.
쿠버네티스의 pod 가 종료될 시 kubelet 에서 SIGTERM 시그널을 container application에 전송한다.

 

참고링크

https://learnk8s.io/graceful-shutdown

https://blog.gruntwork.io/gracefully-shutting-down-pods-in-a-kubernetes-cluster-328aecec90d

 

application을 개발하면서 마주했던 문제는 아래와 같았다.
쿠버네티스에서는 pod를 종료할 때 기본적으로 pod application에 SIGTERM 시그널을 보내고 디폴트 30초를 기다린다. (30초를 변경하려면 pod 정의에서 terminationGracePeriodSeconds를 설정하면 된다) 이 후에도 application 이 종료되지 않는다면 강제로 종료(SIGKILL) 하게 되는데 나의 경우에는 SIGTERM 시그널을 받고 남은 작업 처리를 하는 도중에 terminationGracePeriodSeconds 를 설정한 시간만 큼이 지나지 않았음에도 SIGKILL 시그널이 발생하는 현상이었다. 아직까지도 정확한 원인을 못 찾았지만 pod 정의의 lifecycle.preStop 설정으로 우선 해결할 수 있었다.

 

pod spec의 lifecycle.preStop

https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination 

https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/ 을 참조

 

lifecycle handler에 대한 정의는 아래 링크를 참고한다.

https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#LifecycleHandler

파드의 컨테이너 중 하나에 preStop 훅이 정의되어 있고 파드 스펙의 terminationGracePeriodSeconds(유예기간)가 0으로 설정되어 있지 않은 경우, kubelet은 컨테이너 내부에서 해당 훅을 실행한다. 유예 기간이 만료된 후에도 preStop 훅이 계속 실행 중인 경우, kubelet은 2초의 짧은 일회성 유예 기간 연장을 요청한다. preStop 훅 동작이 기본 유예 기간이 허용하는 것보다 완료하는 데 시간이 더 오래 걸리는 경우, 이에 맞게 terminationGracePeriodSeconds를 수정하는 것이 좋다.
이 유예 기간은 preStop 훅이 실행되고 컨테이너가 정상적으로 중지되는 데 걸리는 총시간에 적용된다. 예를 들어, terminationGracePeriodSeconds가 60이고 훅이 완료되는 데 55초가 걸리고 SIGTERM 신호를 수신한 후 컨테이너가 정상적으로 중지되는 데 10초가 걸리는 경우, terminationGracePeriodSeconds가 이 두 가지가 발생하는 데 걸리는 총 시간(55+10) 보다 작으므로 컨테이너는 정상적으로 중지되기 전에 종료됩니다. 이 경우에는 총 시간보다 조금 더 여유 있게 설정하는 것이 좋다.

 

사용 예시는 아래와 같다

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    lifecycle:
      preStop:
        exec:
          command: ["/bin/sh","-c","nginx -s quit; while killall -0 nginx; do sleep 1; done"]

lifecycle-demo pod를 종료 시 preStop에 정의된 exec.command 에 정의된 shell command 가 실행된다. terminationGracePeriodSeconds 를 별도로 정의하지 않았기 때문에 디폴트 30초가 유예기간이 된다.

 

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: my-container
    image: my-container:latest
    lifecycle:
      preStop:
        httpGet:
          port: 8080
          path: preStopShutdown
  terminationGracePeriodSeconds: 120

lifecycle-demo pod 를 종료시 preStop 에 정의된 container의 8080 포트로 접속하여 GET /preStopShutdown API를 호출한다.

/preStopShutdown에서는 container 가 종료되기 전에 필요한 작업들을 처리하도록 한다.

/preStopShutdown API 응답 후에 kubelet 은 container에 SIGTERM 전송 후 container 종료의 처리를 수행한다.

댓글

💲 추천 글