[kubernetes] 쿠버네티스 패턴 - 수명주기 관리

박원균·2021년 11월 13일
1

Kubernetes

목록 보기
14/24
post-thumbnail

클라우드 네이티브 플랫폼으로 관리되는 컨테이너화된 애플리케이션은 자기 자신의 수명주기를 제어할 수 없으며, 좋은 클라우드 네이티브 일원으로서 자격을 갖추려면 관리 플랫폼에 의해 생성된 이벤트를 받아서 그에 맞춰 수명주기를 조절해야합니다.

수명주기 관리 패턴은 애플리케이션이 수명주기 이벤트에 어떻게 반응해야 하며 반응할 수 있느지를 설명합니다.

문제

정상상태 확인 API는 플랙폼이 애플리케이션에 대한 통찰력을 얻기 위해 지속적으로 점검하는 읽기 전용 종단점입니다.

통찰력 : 플랫폼이 애플리케이션으로부터 정보를 추출하기 위한 메커니즘

컨테이너 상태를 모니터링하는 것 외에도 플랫폼은 때때로 애플리케이션에 명령어를 보내고 애플리케이션이 그 명령어에 반응할 것을 기대합니다. 정책 및 외부 요인에 따라 클라우드 네이티브 플랫폼은 자신이 관리하는 애플리케이션에 대해 언제든지 시작이나 중지를 결정할 수 있습니다.

어떤 이벤트가 중요하고 그 이벤트에 어떻게 반응해야 하는지를 결정하느 것은 컨테이너화 된 애플리케이션의 몫입니다. 하지만 실제로 이 일은 플랫폼이 애플리케이션에 명령어를 보내고 통신 하는데 사용하는 API가 수행합니다. 또한 애플리케이션은 수명주기 관리로부터 혜택을 얻거나, 이런 서비스가 필요하지 않은 경우엔 수명주기 관리를 무시하기도 합니다.

해결책

프로세스에 관한 조정은 프로세스 모델만으로 충분치 않다.

프로세스 상태 확인만으로는 애플리케이션의 정상상태를 나타내는 데 충분하지 않습니다. 그렇기 대문에 컨테이너 정상상태를 모니터링하려면 다른 API가 있어야합니다. 이와 마찬가지로 프로세스를 실행하고 중지하는 데에 프로세스 모델만 사용하는 것은 충분치 않습니다.현실 세계에서의 애플리케이션은 좀 더 세분화된 상호작용과 수명주기 관리 기능이 필요합니다.

파드 레벨에는 다른 구조체로 컨테이너 수명주기 관리에 도움을 주는 초기화 컨테이너가 있습니다. 그리고 제안 단계에 머물러 있는 지연 컨테이너(defer-container)도 있습니다.

  • 여기서 나오는 이벤트와 hook은 모두 파드 레벨보다는 개별 컨테이너 레벨에 적용됩니다.

시그텀 신호

컨테이너가 속한 파드가 종료 중이기 때문에 단순히 라이브니스 점검이 실패해 컨테이너가 재시작되든 간에 쿠버네티스가 컨테이너를 멈추기로 결정할 때 마다 컨테이너는 시그텀(SIGTERM) 신호를 수신합니다.

  • SIGTERM이란 ?
    쿠버네티스가 갑작스러운 SIGKILL신호를 보내기 전에 컨테이너가 깨끗하게 종료될 수 있도록 컨테이너를 종료시켜보는 것입니다.

시그널 신호를 받으면 애플리케이션은 가능한 빨리 멈춰야합니다. 입루 애플리케이션의 경우 SIGTERM신호를 받으면 빨리 종료될 수 있습니다.

한편, 일부 애플리케이션에서는 진행 중인 요청을 완료하고 연결을 해제한 다음 임시 파일을 깨끗이 지워야할 수도 있는데 이는 좀 오래걸릴 수도 있습니다.

시그킬 신호

시그텀 신호 수신 후에도 컨테이너 프로세스가 종료되지 않는다면 다음에 따라오는 SIGKILL 신호에 의해 강제로 종료됩니다. 쿠버네티스는 SIGKILL신호를 즉시 보내지는 않고 SIGTERM신호가 발생한 후 기본적으로 유예 시간인 30초를 기다립니다. 이 유예 시간은 .spec.terminationGracePeriodSeconds 필드를 사용해 개별 파드마다 정의할 수 있지만, 쿠버네티스 명령이 실행되는 동안 재정의될 수도 있으므로 보장할 순 없습니다.

여기서의 목적은 프로세스를 빠르게 시작하고 멈출 수 있는 컨테이너화된 애플리케이션을 임시로 설계하고 구현하는 것입니다.

시작 후 훅

수명주기 관리를 위해 프로세스 신호만 사용한 것은 다소 제한적입니다. 그렇기 때문에 쿠버네티스에서 postStartpreStop같은 추가적인 수명주기 훅을 제공합니다. postStart(시작 후) 훅이 포함된 파드 매니페스트 아래와 같습니다.

apiVersion: v1
kind: Pod
metadata:
  name: post-start-hook
spec:
  containers:
    - image: k8spatterns/random-generator:1.0
      name: random-generator
      lifecycle:
        postStart:
          exec:
            command: 	# <- postStart 명령은 여기서 30초를 기다립니다. sleep은 긴 시간 실행된느 시작
              - sh	# 코드가 있을 수 있으므로 이에 대한 시뮬레이션일 뿐입니다.
              - -c	# 또한 여기서는 병렬로 시작하는 주 애플리케이션과 동기화하기 위해 트리거 파일을 사용합니다.
              - sleep 30 && echo "Wake up!" > /tmp/postStart_done

postStart 명령은 컨테이너가 생성된 후 주 컨테이너 프로세스와 비동기적으로 실행됩니다. 많은 애플리케이션 초기화와 준비 로직이 컨테이너 시작 단계의 한 부분으로 구현될 수 있는데도, postStart는 여전히 일부 사용 예에 활용되고있습니다. postStart 동작은 블록킹 호출(blocking call)이며 postStart핸들러가 완료될 때까지는 컨테이너 상태가 대기 상태로 남아 있고 파드 상태는 보류 상태를 유지합니다.

postStart의 특성은 주 컨테이너 프로세스의 초기화 시작을 벌기 위해 컨테이너의 시작 상태를 지연시키는 데 사용됩니다.

postStart의 또 다른 용도는 파드가 어떤 전제조건을 충족하지 못했을 때 컨테이너가 시작되지 않게 하는 것입니다.

  • postStart 훅이 0이 아닌 종료 코드를 리턴해 에러를 나타내면 주 컨테이너 프로세스는 쿠버네티스에 의해 죽습니다.

postStartpreStop훅이 호축되는 메커니즘은 정상상태 점검 패턴과 유사하며 exec,httpdGet 같은 핸들러 타입을 지원합니다.

  • exec : 컨테이너 안에서 직접적으로 명령어를 실행합니다.
  • httpGet : 하나의 파드 컨테이너에 의해 공개된 포트로 HTTP GET 요청을 수행합니다.

postStart의 실행이 보장되지 않으므로 postStart 훅에서 중요한 로직을 실행할 때는 매우 주의해야합니다. 훅은 컨테이너 프로세스와 병렬로 실행되기 때문에 컨테이너가 시작되기 전에 훅이 실행될 수도 있습니다. 또한, 훅은 최소 한 번 실행의 의미로 설계되었으므로 구현 시에 중복 실행될 수 있음을 염두에 둬야 합니다.

플랫폼은 핸들러에 도달하지 못하고 실패한 HTTP 요청에 대해선 재시도 수행을 하지 않습니다.

종료 전 훅

preStop 훅은 컨테이너가 종료되기 전에 컨테이너로 전송되는 블록킹 호출입니다. SIGTERM 신호와 동일한 의미를 지니며 컨테이너가 SIGTERM 신호와 동일한 의미를 지니며 컨테이너가 SIGTERM에 응답하는 것이 불가능할 때 컨테이너를 정상적으로 종료하기 위해 사용해야합니다.

밑 구문에서 preStop 동작은 SIGTERM 알림에 의해 컨테이너 런타임이 컨테이너 삭제를 호출하여 SIGTERM 알림을 트리거 하기 전에 완료해야합니다.

apiVersion: v1
kind: Pod
metadata:
  name: pre-stop-hook
spec:
  containers:
    - name: random-generator
      image: k8spatterns/random-generator:1.0
      lifecycle:
        preStop:
          httpGet:	# 애플리케이션 내에서 실행중인 /shutdown 종단점을 호출합니다.
            port: 8080
            path: /shutdown

preStop이 블록킹 되거나 계속 진행중이거나 실패한 결괄르 리턴되더라도 컨테이너가 삭제되거나 프로세스가 종료되는 상황을 막을 수는 없습니다. 그저 preStop은 정상적인 애플리케이션 종료를 위한 시그텀 신호의 편리한 대안일 뿐입니다. 앞서 설명한 postStart 훅과 동일한 핸드러 유형 및 동작을 제공합니다.

그 밖의 수명주기 제어

위의 설명은 컨테이너 레벨의 메커니즘을 소개했지만 파드 레벨에서 또 다른 메커니즘으로 초기화 명령을 수행할 수 있습니다.

일반 애플리케이션 컨테이너와는 달리 초기화 컨테이너는 순차적으로 실행되고 완료될 때까지 실행되며 파드 내의 애플리케이션 컨테이너가 시작되기 전에 실행됩니다. 이런 특성을 활용하여 파드 레벨 초기화 작업에 초기화 컨테이너를 사용할 수 있습니다.

수명주기 훅과 초기화 컨테이너는 각각 컨테이너 레벨과 파드 레벨에서 서로 다른 세분성(granularity)으로 작동하며 서로 바꿔서 사용하거나 혹은 서로 보완해 사용할 수 도 있습니다.

측면수명주기 훅초기화 컨테이너
활성화 단계컨테이너 수명주기 단계파드 수명주기 단계
시작 단계 동작postSTart 명령어실행될 초기화 컨테이너 목록
종료 단계 작업preStop 명령어상응하는 기능이 아직은 없습니다.
타이밍 보장postStart 명령은 컨테이너의
ENTRYPOINT와 동시에 실행됩니다.
애플리케이션 컨테이너가 시작되기 전에
모든 초기화 컨테이너는 성공적으로 종료가 완료되어야합니다.
사용 사례컨테이너별로 특화된 중요하지 않은 시작/정리 종료를 실행컨테이너를 사용해 워크플로우 같은 순차적 작업을 수행
작업실행을 위해 컨테이너를 재사용
profile
함바라기

0개의 댓글