쿠버네티스 패턴 - 5장 수명주기 관리

👉 수명주기 관리

클라우드 네이티브 플랫폼에서 컨테이너화 된 어플리케이션을 잘 관리하기 위해서는
관리 플랫폼에서 생성되는 이벤트를 통해서 어플리케이션의 수명 주기를 조절해야합니다.

수명 주기 패턴은 쿠버네티스에서 사용하는 파드와 컨테이너의 수명주기를 파악하고
어떻게 관리하는지에 대해 설명합니다.

🍏 문제점

쿠버네티스 패턴 - 4장 정상상태 점검을 통해서 쿠버네티스가 어떻게 컨테이너에 대한 상태를 파악하는지에 대해 설명하였습니다.
또한 Container Probe를 통해서 컨테이너에 대한 조치까지 알아보았습니다.

하지만 파드가 시작할 때 Probe로 상태를 확인하는 것 뿐만아니라 특정 커맨드 작업을 수행해야할 수 도 있므며, 컨테이너에 대한 Probe가 실패할 경우 컨테이너가 정상적으로 종료하기 위한 작업이 필요할 수 있습니다.

클라우드 네이티브 플랫폼에서는 컨테이너화된 어플리케이션을 특정 이벤트로 관리할 수 있어야 하며, 이를 통해서 수명주기를 관리할 수 있어야 합니다.

🍏 해결책

쿠버네티스는 컨테이너화된 어플리케이션을 관리하기 위해 Lifecycle을 나누어 단계를 구분하고 특정 이벤트를 호출합니다.
이를 위해 관리하는 기본적인 단위는 파드이며, 컨테이너들의 집합이라고 할 수 있습니다.

👍 따라서 파드와 컨테이너의 Lifecycle을 파악하여 언제 무엇이 실행되고 언제 어떻게 종료되는지 알아야합니다.

이를 위해서 가장 먼저 파드와 컨테이너의 상태를 알아보도록 하겠습니다.

Pod's phase

Pod는 총 5가지의 단계를 가지고 있습니다.
이 단계는 kubectl get pod 로 알 수 있으며 파드의 상태를 파악할 수 있습니다.

1) pending

  • API 서버가 Pod의 Resource를 생성하여 etcd에 저장 완료
  • 아직 Pod가 Schedule 되지 않았거나, 컨테이너 이미지 다운로드가 완료되지 않은 상태

2) Running

  • Pod가 Node에 Schedule 완료
  • kubelet에 의해 모든 컨테이너 생성 완료
  • 적어도 하나의 컨테이너가 실행 중이거나, 시작 또는 재시작 중에 있음

3) Succeeded

  • Pod의 모든 컨테이너가 성공적으로 종료
  • Pod의 모든 컨테이너가 재시작 되지 않음

4) Failed

  • Pod의 모든 컨테이너가 종료되었으며, 적어도 하나 이상이 실패로 종료
  • 실패한 컨테이너는 non-zero 상태로 나왔거나, 시스템에 의해서 종료 되었음

5) Unknwon

  • 파드의 상태를 알 수 없는 경우
  • 일반적으로 kubelet과 통신하는 중 오류가 발생하여 API Server에서 Pod의 상태를 쿼리할 수 없는 경우가 많음

👌 Terminating : 해당 상태는 Pod의 단계로 포함하지 않으며, gracefully 종료 중임을 나타냅니다.
이를 위해 시간이 부여되며 기본값은 30초입니다. 강제로 파드를 종료하려면 --force 플래그를 설정하면 됩니다.

Container Status

파드의 단계를 알았다면 내부적으로 컨테이너가 어떤 상태인지 알아야합니다.
컨테이너의 상태를 알기 위해서는 kubectl describe pods 를 통해서 파악할 수 있습니다.

1) Wating

  • Running or Terminated 가 아니면 Watining 상태
  • 컨테이너의 시작을 완료하는 데 필요한 작업을 진행하는 상태
  • 예시로 컨테이너 이미지를 다운로드 중이거나, Secret 데이터를 적용하는 작업이 있음
  • kubectl 을 통해서 파드를 쿼리할 때 Wating 상태인 경우 이유를 요약하는 Reason 필드도 표시

2) Running

  • 컨테이너가 문제없이 실행되고 있음을 나타냄
  • kubectl 을 통해서 파드를 쿼리할 때 Running 상태에 진입한 시기를 볼 수 있음

3) Terminated

  • 컨테이너가 실행을 시작한 후 완료되었거나, 어떤 이유로 실패한 상태를 나타냄
  • kubectl 을 통해서 파드를 쿼리할 때 종료 이유 및 종료 코드와 컨테이너의 시작과 종료 시간이 표시됨

Container Lifecycle Hook

쿠버네티스도 컴포넌트 Lifecycle Hook을 가진 프로그래밍 언어 프레임워크와 같이 Lifecycle Hook을 제공합니다.
특히 Hook은 Pod의 Lifecycle 과정에 포함되므로 이 글에서 같이 설명하도록 하겠습니다.

1) Hook Handler

Probe와 같이 Container Lifecycle Hook을 위한 Handler가 존재합니다.
Hook Handler는 두 가지가 있으며 다음 yaml을 통해서 보겠습니다.

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

httpGet
컨테이너의 특정 엔드포인트에 대해서 HTTP 요청을 실행합니다.
해당 예시에서는 컨테이너 IP:8080/postStart 로 HTTP 요청을 실행합니다.

exec
컨테이너의 cgroups와 namespace 안에서, 특정 커맨드를 실행합니다.
해당 예시에서는 컨테이너 내에서 /bin/sh -c nginx -s quit; while killall -0 nginx; do sleep 1; done 을 실행합니다.

2) postStart Hook

개념

  • 컨테이너가 생성된 직후에 실행되는 Hook 으로 메인 컨테이너와 Async 로 실행됨
  • Blocking call이며 완료될 때까지는 컨테이너 상태가 Wating 이며, Pod는 Pending 상태

사용

  • 컨테이너 프로세스의 초기화 시간을 벌기 위해 컨테이너의 시작 상태를 지연시키는 데 사용
  • 파드가 어떤 전제조건을 충족하지 못했을 때 컨테이너가 시작되지 않도록 하기 위해 사용

주의 사항

  • EntrypointAsync 로 동작하며, 파라미터가 Handler에 전달되지 않음

3) preStop Hook

개념

  • 컨테이너가 종료되기 직전에 실행되는 Hook
  • Blocking call이며 Liveness Probe 실패, 선점, 자원 경합의 요인으로 종료될 때 실행

사용

  • 데이터베이스 및 WebSocket 연결 중지, 현재 상태 저장 등을 수행하여 깨끗하게 종료 될 수 있도록 할 때 사용

주의 사항

  • 컨테이너의 상태가 Terminated or Completed 상태인 경우 preStop Hook은 실패 함
  • SIGTERMAsync 로 동작하지 않으며, terminationGracePeriodSeconds 가 만료된 후 SIGKILL 을 통해 종료함

4) Hook delivery guarantees

  • Hook Delivery는 한 번 이상으로 의도되어 있어 여러 번 호출 될 수 있음
  • 일반적으로 한번이지만 Hook을 전송하는 도중에 kubelet이 재시작되는 경우와 같이 재전송 될 가능성이 있음

Activation lifecycle

컨테이너를 안전하게 시작하기 위해서 Activation lifecycle을 알아야합니다.
다음 단계를 통해서 설명하도록 하겠습니다.

1) Init Container

  • 파드가 Schedule 된 후 어플리케이션 컨테이너들이 실행되기 전에 실행되는 특수한 컨테이너
  • 어플리케이션 이미지에 없는 유틸리티 또는 설정 스크립트를 포함할 수 있음
  • 항상 완료되는 것을 목표로 실행되며, 성공적으로 완료되지 못하면 반복적으로 재시작함

👌 Init Container는 쿠버네티스 패턴 - 14장 초기화 컨테이너 에서 자세하게 설명할 예정입니다.

2) Container start & postStart Hook

  • Init Container가 완료되면 어플리케이션 컨테이너가 실행됨
  • 이때 메인 컨테이너와 postStart Hook은 동시에 Async로 실행됨
  • 메인 컨테이너가 잘 실행되어도 postStart Hook이 완료되지 않으면 컨테이너 상태가 Wating 이며, Pod는 Pending 상태

Termination lifecycle

컨테이너를 안전하게 종료하기 위해서 Termination lifecycle을 알아야합니다.
다음 단계를 통해서 설명하도록 하겠습니다.

1) Start terminating

  • Pod의 State를 Terminating 으로 바꿈
  • Endpoint list에서 Pod를 제거하여 새로운 traffic 차단
  • 컨테이너는 여전히 Pod 내에서 실행 중인 상태

2) Grace Period

  • Gracefully Termination을 위해 기본적으로 30초를 기다림
  • preStop Hook, SIGTERM signal과 병렬적으로 수행되어 끝나지 않아도, 시간이 지나면 SIGKILL signal 발생
  • Pod yaml에서 TerminationGracePeriodSeconds 옵션을 설정하여 변경 가능

3) preStop Hook

  • Pod에 구현되어있는 preStop Hook을 실행
  • 컨테이너가 SIGTERM signal을 수신하기 전에 완료되어야 함

4) SIGTERM signal

  • 쿠버네티스가 컨테이너를 멈추기 위해 보내는 신호
  • 해당 신호를 통해 컨테이너가 곧 종료될 것임을 알림
  • 데이터베이스 및 WebSocket 연결 중지, 현재 상태 저장 등을 수행하여 깨끗하게 종료 될 수 있도록 함

5) SIGKILL signal

  • 컨테이너 프로세스를 강제로 종료하는 signal
  • Grace Period 후에도 컨테이너 프로세스가 종료되지 않는다면 해당 signal을 통해서 강제 종료함

🍏 정리

이번 글에서 살펴본 것은 Pod 및 Container의 상태와 단계를 알아보았으며,
Pod가 시작되는 것부터 종료될 때까지의 Lifecycle을 알아보고 특정 이벤트에 대해서 알아보았습니다.

이 내용을 정리하면 다음과 같은 그림이 될 것입니다.

클라우드 네이티브 플랫폼에서 실행되는 어플리케이션을 잘 관리하기 위해서는 Lifecycle을 알고 특정 이벤트를 통해서 관리해야합니다.
이렇게 된다면 어플리케이션의 자동화가 사람을 통해서가 아닌 플랫폼에 의해서 될 것입니다.

👉 Reference

좋은 웹페이지 즐겨찾기