본문 바로가기
카테고리 없음

[Kubernetes] Graceful Shutdown - preStop 설정

by haejang 2023. 9. 15.
728x90
728x90

 

 

# Graceful Shutdown이란?

  • 현재 들어온 요청을 모두 수행하고 우아하게 종료한다 ... 는 개념
  • 예를 들어, A deployment가 restart 된다고 할 때 pod B가 죽고 pod C가 새로 떠야한다고 가정해보자
  • service에서 pod B -> pod C 엔드포인트 변경을 해줘야 하는데, 이게 조금 늦을 수 있음
  • 그러면 pod B는 종료되어야 하지만 여전히 pod B로 트래픽이 흘러들어갈 수 있음
  • -> pod B의 Application은 새로운 요청 수락만 먼저 중지하고, 모든 연결이 종료된 다음에 죽어야 함
  • 또 다른 예시로, pod가 특정 DB와 connection을 맺고 있는 경우 해당 연결을 종료하고 죽어야 함

 

# Pod 종료 순서

  1. 사람 또는 시스템 : Pod 종료 API 발생시킴
  2. kube-apiserver : etcd에 저장된 pod의 상태를 Terminating으로 변경
  3. kubelet : pod의 Terminating 상태 감지
  4. kubelet : Terminating pod의 컨테이너에 preStop 훅이 존재한다면 해당 훅 실행
  5. kubelet : preStop 훅 완료 후 각 컨테이너에 SIGTERM 시그널 전송 (정상적인 종료 절차 밟으라고 요청하는 것)
  6. 각 containers : 정리 작업 수행 후 종료
  7. 이 때, 종료기간(terminationGracePeriodSeconds) 내로 종료되지 않은 컨테이너들에겐 SIGKILL 날라감 (강제 종료)
  8. kubelet : 컨테이너들이 모두 종료되면 api-server에 pod 종료 상태 보고
  9. kube-apiserver : etcd에서 해당 pod 삭제

우리가 볼 구간은 4 ~ 7 번이다.

 

## terminationGracePeriodSeconds 란?

  • kubernetes에서 Pod를 안전하게 종료하기 위해 사용하는 설정 값
  • 즉, kubelet이 SIGTERM 신호을 보낸 후부터 완전히 종료될 때까지 기다리는 시간(초)이다.
  • 해당 시간이 끝나면 SIGKILL 신호를 보내 Pod를 종료한다.

## preStop이란?

  • kubectl delete pod 또는 관리 이벤트 등과 같은 종료 명령을 받으면 바로 실행된다.
  • 어플리케이션에서 Graceful Shutdown 로직을 구현하지 않았을 때 Pod의 Yaml파일에서 간단히 설정할 수 있는 방법이다.

## 주의

preStop 은 terminationGracePeriodSeconds 시간보다 짧게 소요되어야 한다.

 

 

# 그래서 작성하는 방법은?

Application단에서 graceful shutdown을 쉽게 구현 가능하다면 (ex, springboot) 그게 제일 좋고,

그게 힘든 경우는 아래처럼 preStop 으로 sleep 커맨드를 넣어주자

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
	lifecycle:
      preStop:
        exec:
          command:
          - sleep
          - 10

 

 

# (추가) SIGTERM & SIGKILL - 유명한 그림

SIGTERM(kill -15) : 종료하기 전 정리할 시간을 준다
SIGKILL(kill -9) : 시간 안주고 걍 죽임

출처 : https://linuxhandbook.com/sigterm-vs-sigkill/

 

 

# Ref

 

끝!

 

 

728x90
728x90

댓글