Backend/Docker, Kubernetes

[Kubernetes] Graceful Shutdown

findmypiece 2022. 4. 22. 13:47
728x90

쿠너네티스 환경에서는 Scale in/out 이 빈번하게 발생하기 때문에 Scale in 과정에서 종료되는 pod 들에 대한 관리가 필요하다.

 

예를 들어 pod에서 어떠한 로직을 처리중에 있는데 강제로 종료를 해버리면 당연히 문제가 될 것이고 종료되고 있는 과정에 트래픽이 인입되면 해당 요청을 정상처리할 수 없어 에러를 리턴할 수 밖에 없을 것이다.

 

이에 pod 이 정상적으로 종료될 수 있도록 대기시간을 주고 그 시간동안 트래픽은 막는 방안이 필요하다.

 

쿠버네티스에서는 pod 을 종료할 때 SIGTERM 시그널을 우선 보내고 terminationGracePeriodSeconds에 설정된 시간 이후에는 SIGKILL 시그널을 보내서 프로세스를 강제종료한다. terminationGracePeriodSeconds 기본값은 30초이다. 

 

하지만 이는 단순히 SIGTERM, SIGKILL 요청간 텀을 두는 것 뿐이지 기존에 처리중이던 요청에 대한 처리를 완료하고 새로운 요청을 받지 않도록 하는 것은 아니다. 이에 해당하는 Graceful Shutdown 결국 직접 구현해야 한다.

 

방법은 2가지가 있다.

 

우선 pod이 SpringBoot 2.3.0 이상으로 되어 있다면 SpringBoot 에서 지원하는 Graceful Shutdown 기능을 이용하면 되는데 application.yaml 파일에 아래와 같이 명시하면 간단하게 적용이 가능하다.

 

server:
  shutdown: graceful
spring:
  lifecycle:
    timeout-per-shutdown-phase: 10s

 

주의할 점은 timeout-per-shutdown-phase 는 terminationGracePeriodSeconds 보다 작게 설정하거나 혹시 더 커야 한다면 terminationGracePeriodSeconds 를 변경해야 한다. 그렇지 않으면 해당 pod은 Graceful Shutdown 전에 강제종료될 것이다.

 

만약 pod 이 SpringBoot 를 사용하지 않거나 사용하더라도 2.3.0 미만 버전을 사용한다면 pod 라이프사이클 중 종료직전에 실행되는 prestop hook 을 이용하는 방법이 있다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
spec:
  containers:
  - name: demo-app
    image: xxxx
    lifecycle:
      preStop:
        exec:
          command: [
            "sh", "-c",
            "./shutdown.sh",
            "sleep 10"
          ]

이 경우 preStop, SIGTERM, SIGKILL 이 순차적으로 수행되게 된다.

728x90