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

bocopile·2025년 8월 21일

쿠버네티스 패턴

목록 보기
3/28

1. 문제

  • 정상상태 확인 API는 플랫폼이 애플리케이션에 대한 통찰력을 얻기 위해 지속적으로 점검하는 읽기 전용 종단점입니다.
  • 애플리케이션은 수면주기 관리로 부터 혜택을 얻거나 , 수명주기 관리를 무시하는 등의 다양한 상황 발생할 수 있습니다.

2. 해결책

  • 컨테이너 정상상태를 모니터링하기 위해선 다른 API가 필요합니다.
  • 그림과 같이 일부 이벤트는 플랫폼에 의해 발생되며, 원하는 경우 컨테이너가 이벤트를 수신하고 처리할 수 있습니다.
  • 컨테이너 수명주기 롼리에 도움을 주는 초기화 컨테이너 (이벤트, 훅)은 14장에서 다룰 예정 입니다.

1) SIGTERM

  • Liveness 점검이 실해해 컨테이너가 재시작 되던, 쿠버네티스가 컨테이너를 멈추기로 결정할때마나 컨테이너는 SIGTERM 신호를 수신
  • 쿠버네티스가 갑작스러운 SIGKILL 신호를 보내기 전에 컨테이너가 꺠끗하게 종료될 수 있도록 컨테이너에게 미리 신호를 준다.
  • 즉 어떤 경우든 컨테이너를 꺠끗하게 종료하기 위한 방법이다.

2) SIGKILL

  • SIGTERM 신호 수신 후에도 컨테이너 프로세스가 종료되지 않을경우 SIGKILL로 강제 종료 시킨다.
  • SIGTERM 신호가 발생한 후에 기본 30초를 기다리고 실행한다.
    • .spec.terminationGracePeriodSeconds 로 설정하여 개별 파드마다 정의는 가능
    • 쿠버네티스 명령이 실행되는 동안 재정의 될수 있으므로 보장할순 없음

3) Hook

  • 수명 주기 관리를 위해 프로세스 신호만 사용하는 것은 다소 제한적이다
  • 그래서 kubernetes는 postStart, preStop등 추가적인 수명주기 훅을 제공

(1) postStart

  • 컨테이너 생성된 직후 주 컨테이너 프로세스와 비동기적으로 실행
  • postStart 헨들러가 완료될때 까지는 컨테이너 상태가 대기 상태(waiting)로 남아 있고 파드 상태는 보류 상태를 유지
  • 주 컨테이너 프로세스의 초기화 시간을 벌기 위해 컨테이너의 시작 상태를 지연
  • 파드가 어떤 전제조건을 충족하지 못했을 때 컨테이너가 시작되지 않게 하는것
  • 코드
    apiVersion: v1
    kind: Pod
    metadata:
      name: random-generator
    spec:
      containers:
      - image: k8spatterns/random-generator:1.0
        name: random-generator
        env:
        - name: WAIT_FOR_POST_START
          value: "true"
        lifecycle:
          postStart:
            exec:
              command:
              - sh
              - -c
              - sleep 30 && echo "Wake up!" > /tmp/postStart-don
  • 방법
    • exec : 컨테이너 안에서 직접적으로 명령어를 실행
    • httpGet: 하나의 파드 컨테이너에 의해 공개된 포트로 HTTP GET 요청을 수행

(2) PreStop

  • 컨테이너가 종료되기 전에 컨테이너로 전송되는 블록킹 호출
  • SIGTERM 신호와 동일한 의미를 지니며, 컨테이너가 SIGTERM 응답이 불가능 할때 컨테이너를 정상적으로 종료하기 위해 사용
    • 2025년 8월 24일 정정 :예전 글/자료 중엔 preStop·SIGTERM이 병렬로 진행된다고 설명한 것도 있습니다. 하지만 2025년 4월에 갱신된 공식 문서는 “preStop이 끝나야 TERM을 보낼 수 있다”고 명시
  • preStop 블로킹 되거나, 계속 진행중이거나, 실패한 결과를 리턴하더라도 컨테이너가 삭제되거나 종료되는 것을 막을순 없다.
  • 코드
    apiVersion: v1
    kind: Pod
    metadata:
      name: random-generator
    spec:
      containers:
      - image: k8spatterns/random-generator:1.0
        name: random-generator
        env:
        - name: WAIT_FOR_POST_START
          value: "true"
        lifecycle:
          preStop:
            httpGet:
              port: 8080
              path: shutdow

4) 그 밖의 수명 주기 제어

  • 컨테이너 레벨이 아닌 파드 레벨에서도 또 다른 메커니즘으로 초기화를 할수 있다.
  • 해당 내용은 14장 init container 에서 다룰 예정
  • Hook, init Container 비교
    Hookinit container
    활성화 단계컨테이너 수명주기 단계파드 수명주기 단계
    시작 단계 동작postStart 명령어실행될 초기화 컨테이너 목록
    종료 단계 작업preStop 명령어상응하는 기능이 아직 없음
    타이밍 보장postStart 명령어는 컨테이너의 ENTRYPOINT와 동시에 실행애플리케이션 컨테이너가 시작되기 전에 모든 초기화 컨테이너는 성공적으로 종료가 완료되어야함
    사용 사례컨테이너 별로 특화된 중요하지 않은 시작/ 정리 종료를 실행컨테이너를 사용해 워크플로우 같은 순차적 작업 수행, 작업 실행을 위해 컨테이너를 재사용

5) Container 라이프사이클

(1) Start

  • 다이어그램
  • 예제코드
    # 
    apiVersion: v1
    kind: Pod
    metadata:
      name: sidecar-container-demo
    spec:
      containers:
        - image: busybox
          command: ["/bin/sh"]
          args:
            [
              "-c",
              "while true; do echo echo $(date -u) 'Written by busybox sidecar container' >> /var/log/index.html; sleep 5;done",
            ]
          name: sidecar-container
          resources: {}
          volumeMounts:
            - name: var-logs
              mountPath: /var/log
          lifecycle:
            postStart:
              httpGet:
                path: /index.html
                port: 80
                host: localhost
                scheme: HTTP
        - image: nginx
          name: main-container
          resources: {}
          ports:
            - containerPort: 80
          volumeMounts:
            - name: var-logs
              mountPath: /usr/share/nginx/html
      dnsPolicy: Default
      volumes:
        - name: var-logs
          emptyDir: {}
  • 파드 적용 및 확인
    kubectl apply -f ./poststart.yaml
    kubectl describe pod/poststart-demo
  • 확인 결과

(2) Stop

  • 다이어그램
  • 예제 코드
    apiVersion: v1
    kind: Pod
    metadata:
      name: prestop-demo
    spec:
      terminationGracePeriodSeconds: 40
      containers:
        - name: nginx-container
          image: nginx
          ports:
            - containerPort: 80
          lifecycle:
            preStop:
              exec:
                command:
                  - /bin/sh
                  - -c
                  - |
                    echo "[preStop] start $(date)"
                    sleep 15
                    echo "[preStop] sending graceful quit to nginx $(date)"
                    nginx -s quit
      dnsPolicy: Default
    
  • 적용 및 모니터링
    kubectl apply -f ./prestop.yaml
    kubectl logs -f prestop-demo -c nginx-container
  • 타 터미널에서 pod 삭제
    kubectl delete pod prestop-demo
  • 로그 확인

3. 참고

profile
DevOps Engineer

4개의 댓글

comment-user-thumbnail
2025년 8월 23일

사실, 잘 보면, k8s 입장에서는 컨테이너속의 app 이 k8s 에서 요구하는 기능들을 받춰줘야 정상적으로 해결이 되는 건데, 저번주에 다뤘던 probe 와 연관시켜서 말하자면, 만약 probe 에 대응 되는 기능이 컨테이너안의 app 에서 구현되지 않았다면? 그리고, preStop으로 “밖”을 정리할 기회를 만들고, SIGTERM 핸들러로 “앱 안”을 깨끗이 마무리하는 투-스텝 으로 안전하게 마무리 할 수 있도록 하고 있는데 만약 app 에서 이러한 기능을 구현하고 있지않는다면, k8s 에서는 문제가 발생하는 거네요? 현재 컨테이너에서 구동되는 많은 app 들이 컨테이너환경을 고려하지 않고 개발된 app 들도 많을 텐데, 이런 것들은 어떻게 해야 하나요?

1개의 답글
comment-user-thumbnail
2025년 8월 24일

안녕하세요. 글 잘 읽었습니다. 중간에 PreStop 설명하실 때 PreStop와 SIGTERM과 동일한 의미를 지녔다고 하셨는데 이게 어떤 의미일까요? 저는 Pod에 SIGTERM 신호가 보내진 뒤 PreStop이 실행되는걸로 알고있었는데, 혹시 이 내용과 별개로 PreStop이 동작하는 방식이 있는걸까요?

1개의 답글