본문 바로가기
Orchestration/Kubernetes

Kubernetes Pod의 Graceful 한 종료

by wlsdn3004 2023. 4. 15.
728x90
반응형

 

쿠버네티스에서 Pod의 Graceful 한 종료는 컨테이너와 애플리케이션의 안정성과 데이터 일관성을 보장하는 중요한 요소이다. 만약 Graceful 한 종료를 하지 않는다면, 강제로 컨테이너를 종료하는 것이기 때문에 실행 중인 작업을 완료하지 못하고 중단될 수 있고, 종료 전 Pod에서 일어나는 작업이 불완전한 상태로 남아 데이터 일관성과 안정성을 잃을 수 있다.

 

따라서, Graceful 한 종료는 Pod을 안정적으로 관리하고 운영상의 이슈를 방지하는 데 매우 중요하다.

이를 위해서는 Pod의 종료 과정을 이해하고, 필요한 설정을 적용하여 Graceful 한 종료를 할 수 있도록 해야 한다.

Graceful 한 종료란?
Pod가 종료되기 전에 현재 진행 중인 작업들을 완료하고, 요청을 처리하는데 필요한 시간을 확보하여 다른 Pod나 컴포넌트들에게 영향을 주지 않는 상태로 정상 종료되는 것을 말한다.

 

Pod의 종료 과정에서, kubelet은 컨테이너에게 SIGTERM 시그널을 보내어 Graceful 한 종료를 유도한다.

이때, 컨테이너는 SIGTERM 시그널을 받으면 프로세스를 정리하고 종료를 준비한다. 이를 통해, 컨테이너가 종료되기 전에 실행 중인 작업을 완료하고 데이터 일관성을 유지할 수 있다.

 

그러나, 일부 컨테이너는 SIGTERM 시그널을 무시하거나 처리하지 않을 수 있다. 이 경우, kubelet은 SIGTERM 시그널을 보낸 후 terminationGracePeriodSeconds에 지정된 시간 동안 대기하며, 이 시간 내에 컨테이너가 종료되지 않으면 SIGKILL 시그널을 보내어 강제 종료시킨다. 

 

본 글에 설명 순서는 다음과 같다.

1. terminationGracePeriodSeconds
2. preStop
3. 예외 사항

 

 


1. terminationGracePeriodSeconds 

 

terminationGracePeriodSeconds는 Kubernetes에서 pod를 안전하게 종료하기 위해 사용하는 설정 값으로, kubelet이 SIGTERM 시그널을 보낸 후부터 완전히 종료될 때까지 기다리는 시간(초)이다. 기본값은 30초이다.

 

실제로 30초에 종료되는지 확인해 보자.

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - args:
    - sleep
    - infinity
    image: busybox
    name: busybox

위 Pod를 배포하고 실제 종료 과정을 시스템 콜 추적을 통해 확인해 보자.

$ strace -t -p $(docker ps | grep 'busybox' | cut -f 1 -d ' ' | xargs docker inspect | jq .[0].State.Pid)
strace: Process 7075 attached
03:34:01 restart_syscall(<... resuming interrupted read ...>) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
03:34:08 --- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=0, si_uid=0} ---
03:34:08 restart_syscall(<... resuming interrupted restart_syscall ...>) = ?
03:34:38 +++ killed by SIGKILL +++

kubectl delete 명령을 내리 34:08에 SIGTERM 시그널을 받게 된다. 그리고 30초 후인 34:38에 SIGKILL 시그널을 받아 종료되는 것을 볼 수 있다.

 

이번엔 40초로 변경하고 테스트해 보자.

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - args:
    - sleep
    - infinity
    image: busybox
    name: busybox
  terminationGracePeriodSeconds: 40  ## 40초 설정

 

$ strace -t -p $(docker ps | grep 'busybox' | cut -f 1 -d ' ' | xargs docker inspect | jq .[0].State.Pid)
strace: Process 10115 attached
03:38:14 restart_syscall(<... resuming interrupted read ...>) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
03:38:22 --- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=0, si_uid=0} ---
03:38:22 restart_syscall(<... resuming interrupted restart_syscall ...>) = ?
03:39:02 +++ killed by SIGKILL +++

38:22에 SIGTERM 시그널을 받고, 40초 후인 39:02에 종료된 것을 확인할 수 있다.

 

terminationGracePeriodSeconds 설정 값을 적절히 설정하는 것은 Pod의 안정성과 데이터 일관성을 유지하기 위해 매우 중요하다. 만약 설정 값이 짧으면 컨테이너가 Graceful 한 종료를 마치기 전에 SIGKILL 시그널이 보내져서 데이터 일관성을 유지하지 못할 수 있고, 반대로 설정 값이 너무 길면 Pod의 종료가 지연되어 운영상의 이슈를 야기할 수 있다. 따라서 terminationGracePeriodSeconds 설정 값을 애플리케이션의 특성에 맞게 조정하여 Pod의 안정성과 데이터 일관성을 유지할 수 있도록 해야 한다.

 


2. preStop

 

pod가 종료될 때 종료 로직을 제대로 구현하지 않아 Graceful 한 종료를 하지 못하는 경우가 있는데, 예를 들면 종료 전 데이터베이스와의 연결을 종료하고 트랜잭션을 완료하여 종료해야 하는 상황이거나, 파일 시스템을 정리하고 필요한 데이터와 상태를 저장하고 종료해야 하는 상황 등이 있을 수 있다.

이때는 terminationGracePeriodSeconds만으로 Graceful 한 종료를 보장할 수 없다.

 

이를 위해 Kubernetes에서는 preStop이라는 기능을 제공한다.

 

preStop은 Kubernetes에서 제공하는 Lifecycle hook 중 하나로, pod가 종료되기 전에 실행되는 훅이다. preStop은 terminationGracePeriodSeconds 값이 설정된 시간 내에 실행을 완료해야 하며, pod가 종료되기 전 마지막 작업을 처리하도록 해준다.

 

preStop은 pod가 종료 명령을 받으면 바로 실행되고, preStop이 완료되면 SIGTERM 시그널을 받게 되는데, 여기서 주의해야 할 점은 terminationGracePeriodSeconds값을 고려해서 설정해야 한다는 것이다.

 

pod가 종료되면 terminationGracePeriodSeconds과 preStop이 동시에 진행되는데, preStop이 끝나지 않은 상태에서 terminationGracePeriodSeconds 시간에 도달하여 SIGKILL 시그널이 발생하면 Graceful 한 종료가 되지 않는다.

 

preStop은 컨테이너 이미지나 애플리케이션 코드를 수정할 필요 없이 pod의 YAML 파일에서 간단히 설정할 수 있다. preStop은 다양한 종류의 애플리케이션에 적용할 수 있으며, 애플리케이션 종료 전에 반드시 처리해야 하는 작업을 수행할 수 있다.

 

terminationGracePeriodSeconds값과 preStop을 동작 관계를 아래 Pod의 예시를 통해 알아보자.

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    lifecycle:
      preStop:
        exec:
          command:
          - sh
          - -c
          -  |
            curl localhost:80
            sleep 30
            curl localhost:80
  terminationGracePeriodSeconds: 10

 

$ kubectl logs nginx -f
127.0.0.1 - - [15/Apr/2023:06:00:41 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.74.0" "-"
2023/04/15 06:00:51 [notice] 1#1: signal 3 (SIGQUIT) received, shutting down
2023/04/15 06:00:51 [notice] 29#29: gracefully shutting down
2023/04/15 06:00:51 [notice] 29#29: exiting
2023/04/15 06:00:51 [notice] 29#29: exit
2023/04/15 06:00:51 [notice] 30#30: gracefully shutting down
2023/04/15 06:00:51 [notice] 30#30: exiting
2023/04/15 06:00:51 [notice] 30#30: exit
2023/04/15 06:00:51 [notice] 1#1: signal 17 (SIGCHLD) received from 30
2023/04/15 06:00:51 [notice] 1#1: worker process 29 exited with code 0
2023/04/15 06:00:51 [notice] 1#1: worker process 30 exited with code 0
2023/04/15 06:00:51 [notice] 1#1: exit
  1. pod 종료 명령을 내린다.
  2. 컨테이너는 preStop을 실행하여 locahost 호출하고 30초 후에 다시 localhost를 호출한다.
    (이때 pod 상태는 Terminating으로 변하고, Endpoint에서 제거된다.)
  3. preStop이 진행되는 중 10초가 지나면 종료 시그널을 받고 즉시 종료한다.

 

위 상황은 preStop동작이 마치기 전 pod가 종료되는 상황이다.

즉, preStop동작을 충분히 수행하고 SIGTERM 시그널에 의해 정상 종료될 수 있게 terminationGracePeriodSeconds의 값을 충분히 설정해야 한다.

 

한 가지 예시를 더 들어보겠다.

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    lifecycle:
      preStop:
        exec:
          command:
          - sh
          - -c
          -  |
            curl localhost:80
            sleep 10
            curl localhost:80
  terminationGracePeriodSeconds: 15

 

## <<-- preStop 시작 -->>
127.0.0.1 - - [15/Apr/2023:06:06:58 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.74.0" "-"
127.0.0.1 - - [15/Apr/2023:06:07:08 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.74.0" "-"
## <<-- preStop 종료 -->>

2023/04/15 06:07:08 [notice] 1#1: signal 3 (SIGQUIT) received, shutting down
2023/04/15 06:07:08 [notice] 29#29: gracefully shutting down
2023/04/15 06:07:08 [notice] 29#29: exiting
2023/04/15 06:07:08 [notice] 29#29: exit
2023/04/15 06:07:08 [notice] 30#30: gracefully shutting down
2023/04/15 06:07:08 [notice] 30#30: exiting
2023/04/15 06:07:08 [notice] 30#30: exit
2023/04/15 06:07:08 [notice] 1#1: signal 17 (SIGCHLD) received from 29
2023/04/15 06:07:08 [notice] 1#1: worker process 29 exited with code 0
2023/04/15 06:07:08 [notice] 1#1: worker process 30 exited with code 0
2023/04/15 06:07:08 [notice] 1#1: exit

위 상황은 preStop동작을 완료한 후 pod가 종료되는 상황이다. 앞전에 설정한 nginx Pod보다는 잘 설정한 것 같아 보인다.

 

 

하지만 한 가지 생각해야 할 점이 있다.

 

위 Pod는 종료 시 preStop이 10초간 동작하고 SIGTERM 시그널을 받아 5초의 유예기간을 확보하게 된다. SIGTERM 신호를 받은 후 정상적으로 종료하기까지 걸리는 시간이 10초라고 가정한다면 10 + 10 = 20 초가 되어야 하는데, 15초에 종료가 되어 결국 Graceful 한 종료가 되지 않는 상황이 발생할 수 있다.

 

 아래 그림을 보고 동작에 참고하자.

 

 

실제 preStop을 사용해 에러 발생 여부를 비교해 보자.

아래 그림과 같이 LB에 연결되어 있는 nginx pod 5개를 대상으로 요청을 날리는데, 중간에 pod 3개를 종료해 보겠다.

 

아래는 nginx의 preStop이 설정되지 않은 상태로 3개 pod를 종료했을 때의 상황을 캡처한 사진이다.

아래는 ELB Access Log에서 발생한 메세지 이다.

 

AWS Athena를 통해 s3로그 중 502 메세지만 필터링 해보자.

쿼리를 위한 테이블을 만들자.

CREATE EXTERNAL TABLE IF NOT EXISTS alb_access_logs (
  `timestamp` string,
  `elb` string,
  `client_ip` string,
  `backend_ip` string,
  `request_processing_time` double,
  `backend_processing_time` double,
  `response_processing_time` double,
  `elb_status_code` string,
  `backend_status_code` string,
  `received_bytes` bigint,
  `sent_bytes` bigint,
  `request_method` string,
  `request_url` string,
  `request_proto` string,
  `user_agent` string,
  `ssl_cipher` string,
  `ssl_protocol` string,
  `target_group_arn` string,
  `trace_id` string,
  `domain_name` string,
  `chosen_cert_arn` string,
  `matched_rule_priority` string,
  `request_creation_time` string,
  `actions_executed` string,
  `redirect_url` string,
  `error_reason` string
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ' '
LINES TERMINATED BY '\n'
LOCATION 's3://test-s3/acclog/AWSLogs/000982191218/elasticloadbalancing/ap-northeast-2/2023/04';

 

만들어진 테이블을 통해 502 에러를 필터링 해보자.

SELECT *
FROM alb_access_logs
WHERE backend_status_code = '502';

 

 

 

다음은 preStop에 sleep 10초를 넣어서 위 상황과 동일하게 pod 3개를 종료하는 테스트를 해보자.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
        lifecycle:
          preStop:
            exec:
              command:
                - sh
                - -c
                - sleep 10
      terminationGracePeriodSeconds: 20

아무 이상없이 Graceful한 종료를 확인할 수 있다.

 

 


3. 예외 사항

 

일반적으로 앞서 설명한 것처럼 preStop과 terminationGracePeriodSeconds이 설정된 값에 의해 동작한다.

 

하지만 무한루프로 실행되는 pod에 preStop과 terminationGracePeriodSeconds 값을 사용하면 위 설명처럼 동작하지 않는 예외가 발생한다.

 

아래와 같이 1초마다 "hello world" 명령을 무한으로 실행하는 Pod가 있다.

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    command: [ "/bin/sh", "-c", "echo 'Starting up'; trap 'echo Received Terminating signal' QUIT ;trap 'echo Received TERM signal' TERM ; while true; do echo $(date) 'Hello, world!'; sleep 1; done" ]
    lifecycle:
      preStop:
        exec:
          command:
          - sh
          - -c
          -  |
            kill -15 1
            sleep 10
            kill -15 1
  terminationGracePeriodSeconds: 20

위 Pod의 종료 동작은 다음과 같다.

  1. Pod 종료 명령을 내린다.
  2. preStop이 동작하여 "kill -15 1" 명령에 의해 "Received TERM signal" 메세지를 출력하고, 10초 대기한다.
  3. 총 10초가 지나면 preStop의 마지막 명령 "kill -15 1"이 동작하여 "Received TERM signal" 메세지를 출력한다.
    이때 nginx의 종료 시그널을 받아 "Received Terminating signal" 메세지를 출력하고 terminationGracePeriodSeconds 시간 20초를 다시 진행한다.
  4. 총 30초가 지나면 SIGKILL 시그널을 받아 Pod는 종료한다.

 

로그와 시스템 콜 메세지를 통해 확인해 보자.

$ kubectl logs nginx -f

Sat Apr 15 06:43:06 UTC 2023 Hello, world!
## <<-- preStop 시작 -->>
Received TERM signal
Sat Apr 15 06:43:07 UTC 2023 Hello, world!
Sat Apr 15 06:43:08 UTC 2023 Hello, world!
Sat Apr 15 06:43:09 UTC 2023 Hello, world!
Sat Apr 15 06:43:10 UTC 2023 Hello, world!
Sat Apr 15 06:43:11 UTC 2023 Hello, world!
Sat Apr 15 06:43:12 UTC 2023 Hello, world!
Sat Apr 15 06:43:13 UTC 2023 Hello, world!
Sat Apr 15 06:43:14 UTC 2023 Hello, world!
Sat Apr 15 06:43:15 UTC 2023 Hello, world!
Sat Apr 15 06:43:16 UTC 2023 Hello, world!

Received Terminating signal
Received TERM signal
## <<-- preStop 종료, terminationGracePeriodSeconds 시작 -->>

Sat Apr 15 06:43:17 UTC 2023 Hello, world!
Sat Apr 15 06:43:18 UTC 2023 Hello, world!
Sat Apr 15 06:43:19 UTC 2023 Hello, world!
Sat Apr 15 06:43:20 UTC 2023 Hello, world!
Sat Apr 15 06:43:21 UTC 2023 Hello, world!
Sat Apr 15 06:43:22 UTC 2023 Hello, world!
Sat Apr 15 06:43:23 UTC 2023 Hello, world!
Sat Apr 15 06:43:24 UTC 2023 Hello, world!
Sat Apr 15 06:43:25 UTC 2023 Hello, world!
Sat Apr 15 06:43:26 UTC 2023 Hello, world!
Sat Apr 15 06:43:27 UTC 2023 Hello, world!
Sat Apr 15 06:43:28 UTC 2023 Hello, world!
Sat Apr 15 06:43:29 UTC 2023 Hello, world!
Sat Apr 15 06:43:30 UTC 2023 Hello, world!
Sat Apr 15 06:43:31 UTC 2023 Hello, world!
Sat Apr 15 06:43:32 UTC 2023 Hello, world!
Sat Apr 15 06:43:33 UTC 2023 Hello, world!
Sat Apr 15 06:43:34 UTC 2023 Hello, world!
Sat Apr 15 06:43:35 UTC 2023 Hello, world!
Sat Apr 15 06:43:36 UTC 2023 Hello, world!
## <<-- End -->>

 

## strace 
$ strace -t -p $(docker ps | grep 'nginx' | cut -f 1 -d ' ' | xargs docker inspect | jq .[0].State.Pid)

## SIGQUIT -> Interrupted (preStop이 끝나고 TerminationGracePeriodSeconds 시작)
--- SIGQUIT {si_signo=SIGQUIT, si_code=SI_USER, si_pid=0, si_uid=0} ---
rt_sigreturn({mask=[]})        = -1 EINTR (Interrupted system call)

## SIGKILL (TerminationGracePeriodSeconds 시간이 지나면 종료)
 <unfinished ...>)   = ?
+++ killed by SIGKILL +++

 

일반적으로 위 preStop값과 terminationGracePeriodSeconds값을 보았을 때 20초가 경과하면 종료되어야 한다.

하지만 위 Pod를 종료하면 10 + 20 = 30 초가 걸리게 된다.

 

 

 

 

예외 동작의 한 가지 예시를 더 보자.

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    command: [ "/bin/sh", "-c", "echo 'Starting up'; trap 'echo Received Terminating signal' QUIT ;trap 'echo Received TERM signal' TERM ; while true; do echo $(date) 'Hello, world!'; sleep 1; done" ]
    lifecycle:
      preStop:
        exec:
          command:
          - sh
          - -c
          -  |
            kill -15 1
            sleep 30
            kill -15 1
  terminationGracePeriodSeconds: 20

위 Pod의 종료 동작은 다음과 같다.

  1. Pod 종료 명령을 내린다.
  2. preStop이 동작하여 "Received TERM signal" 메세지를 출력하고, 30초 대기한다.
  3. 총 20초가 지나면 nginx의 종료 시그널을 받아 "Received Terminating signal" 메세지를 출력한다.
    이때 다시 terminationGracePeriodSeconds 시간을 진행한다.
  4. 총 30초가 지나면 preStop 마지막 동작으로 "Received TERM signal" 메세지를 출력하고 preStop은 종료된다.
  5. 총 40초가 지나면 SIGKILL 시그널을 받아 Pod는 종료한다.

 

로그와 시스템 콜 메세지를 확인해 보자.

$ kubectl logs nginx -f

Sat Apr 15 06:53:41 UTC 2023 Hello, world!
## <<-- preStop 시작 -->>
Received TERM signal
Sat Apr 15 06:53:42 UTC 2023 Hello, world!
Sat Apr 15 06:53:43 UTC 2023 Hello, world!
Sat Apr 15 06:53:44 UTC 2023 Hello, world!
Sat Apr 15 06:53:45 UTC 2023 Hello, world!
Sat Apr 15 06:53:46 UTC 2023 Hello, world!
Sat Apr 15 06:53:47 UTC 2023 Hello, world!
Sat Apr 15 06:53:48 UTC 2023 Hello, world!
Sat Apr 15 06:53:49 UTC 2023 Hello, world!
Sat Apr 15 06:53:50 UTC 2023 Hello, world!
Sat Apr 15 06:53:51 UTC 2023 Hello, world!
Sat Apr 15 06:53:52 UTC 2023 Hello, world!
Sat Apr 15 06:53:53 UTC 2023 Hello, world!
Sat Apr 15 06:53:54 UTC 2023 Hello, world!
Sat Apr 15 06:53:55 UTC 2023 Hello, world!
Sat Apr 15 06:53:56 UTC 2023 Hello, world!
Sat Apr 15 06:53:57 UTC 2023 Hello, world!
Sat Apr 15 06:53:58 UTC 2023 Hello, world!
Sat Apr 15 06:53:59 UTC 2023 Hello, world!
Sat Apr 15 06:54:00 UTC 2023 Hello, world!
Sat Apr 15 06:54:01 UTC 2023 Hello, world!

Received Terminating signal
## <<-- terminationGracePeriodSeconds 다시 시작 -->>

Sat Apr 15 06:54:02 UTC 2023 Hello, world!
Sat Apr 15 06:54:03 UTC 2023 Hello, world!
Sat Apr 15 06:54:04 UTC 2023 Hello, world!
Sat Apr 15 06:54:05 UTC 2023 Hello, world!
Sat Apr 15 06:54:06 UTC 2023 Hello, world!
Sat Apr 15 06:54:07 UTC 2023 Hello, world!
Sat Apr 15 06:54:08 UTC 2023 Hello, world!
Sat Apr 15 06:54:09 UTC 2023 Hello, world!
Sat Apr 15 06:54:10 UTC 2023 Hello, world!
Sat Apr 15 06:54:11 UTC 2023 Hello, world!

Received TERM signal
## <<-- preStop 종료 -->>

Sat Apr 15 06:54:12 UTC 2023 Hello, world!
Sat Apr 15 06:54:13 UTC 2023 Hello, world!
Sat Apr 15 06:54:14 UTC 2023 Hello, world!
Sat Apr 15 06:54:15 UTC 2023 Hello, world!
Sat Apr 15 06:54:16 UTC 2023 Hello, world!
Sat Apr 15 06:54:17 UTC 2023 Hello, world!
Sat Apr 15 06:54:18 UTC 2023 Hello, world!
Sat Apr 15 06:54:19 UTC 2023 Hello, world!
Sat Apr 15 06:54:20 UTC 2023 Hello, world!
Sat Apr 15 06:54:21 UTC 2023 Hello, world!
## <<-- End -->>

 

## strace 
$ strace -t -p $(docker ps | grep 'nginx' | cut -f 1 -d ' ' | xargs docker inspect | jq .[0].State.Pid)

## SIGQUIT -> Interrupted (TerminationGracePeriodSeconds이 끝나고 TerminationGracePeriodSeconds 시작)
--- SIGQUIT {si_signo=SIGQUIT, si_code=SI_USER, si_pid=0, si_uid=0} ---
rt_sigreturn({mask=[]})        = -1 EINTR (Interrupted system call)

## SIGKILL (TerminationGracePeriodSeconds 시간이 지나면 종료)
 <unfinished ...>)   = ?
+++ killed by SIGKILL +++

일반적으로 위 preStop값과 terminationGracePeriodSeconds값을 보았을 때 20초가 경과하면 종료되어야 한다.

하지만 위 Pod를 종료하면 terminationGracePeriodSeconds X 2 = 40초가 걸리게 된다.

 

 

정리하자면 무한 루프를 실행하는 Pod를 종료할 때 preStop을 사용하면 소요되는 시간은 아래와 같다.

  • preStop < terminationGracePeriodSeconds
    -> preStop + terminationGracePeriodSeconds로 종료
  • preStop > terminationGracePeriodSeconds
    -> terminationGracePeriodSeconds X 2로 종료

 

위와 같이 동작하는 이유는 무한루프를 실행하는 Pod는 첫 종료 시그널을 처리하지 못하기 때문에 인터럽트 후 한번 더 terminationGracePeriodSeconds 시간을 체크하여 강제종료 하게 된다.

 

그러므로 무한루프를 실행하는 Pod를 사용할 때는 preStop값은 넣지 말고 terminationGracePeriodSeconds값만 넣어 종료 시간을 컨트롤해야 한다.

 

 


마치며

Kubernetes에서 terminationGracePeriodSeconds 설정 값과 preStop Lifecycle hook 설정을 통해 안전하게 종료할 수 있는 방법을 알아보았다. 쿠버네티스의 종료 동작은 간단한 거 같지만 그 동작을 정확히 이해해야만 Pod의 Graceful 한 종료를 구현할 수 있을 것이다.

반응형

댓글