카테고리 없음

[k8s] pod 의 상태에 관하여

daniel_lab 2024. 2. 25. 17:06

Pod의 상태는 서비스 운영에서 중요한 모든 타이밍들과 깊이 연관되어있어, 상세한 이해가 중요하다. 예를 들어, 서비스에서 트래픽을 받게되는 시작타이밍은 Pod의 Readiness Probe가 통과되어 Pod의 Ready 컨디션이 True가 되는 순간이다. Pod에 이상이 감지되는 원리, 트러블슈팅시 진단하는 상황 등등 여러경우에서 Pod의 상태에 대한 이해가 요구된다.

우선, pod의 상태는 PodStatus 오브젝트에 기술되어 있고, PodStatus 오브젝트에는 상태와 관련된 여러 필드들이 존재한다.

PodStatus 오브젝트

### phase 필드

pod의 현재 라이프사이클을 나타내며, pending, running succeeded, failed, unknown 등의 상태가 존재한다.

  • pending: Pod의 모든 Containers가 Ready 되기까지 과정(pod 가 scheduled 되고, container 실행을 위해 container runtime 이 image를 다운로드하는 등등 모든과정포함)
  • running: Pod 가 Node에 bound되어 모든 containers 가 생성되었을때
  • succeeded: 모든 컨테이너가 성공적으로 종료 되었을때
  • failed: 적어도 1개의 컨테이너가 실패로 종료되었을때(container exited with non-zero status or terminated by system)
  • unknown: 알 수 없는 이유로 Pod 상태 조회가 안될때(노드와 파드 통신 안될때..)

-> 참고로, 위 상태는 Pod가 서비스에서 트래픽을 받게 되는 타이밍과 직접적인 관련이 없다. 이것은 아래 나오는 conditions 필드중 "Ready" 필드와 관련이 있다.

conditions 필드

pod의 특정조건들에 대한 상태를 나타낸다. PodScheduled, PodReadyToStartContainers, ContainersReady, Initialized, Ready 등의 조건이 있다.

  • PodScheduled: pod가 노드에 scheduled 됨
  • PodReadyToStartContainers: Pod sandbox가 생성되었고, networking 설정이 완료되었음
  • ContainersReady: 모든 컨테이너가 ready
  • Initialized: 모든 init containers가 완료
  • Ready: pod가 service로부터 request받을 수 있음(Service의 Endpoint Object에 Pod가 편입되냐마냐의 조건으로도 사용됨)

Message, Reason 필드

Pod 의 상태에 대한 추가적인 세부정보 존재

HostIp와 PodIp

실행중인 Pod의 호스트머신 Ip와 Pod의 자체 IP 주소

ContainerStatuses

Pod내의 각 컨테이너에 대한 상태정보를 갖는다. Waiting, Running, Terminated 상태를 갖을 수 있다. container 상태를 알기 위해서 kubectl describe pod 로 조회해볼 수 있다

Container 의 상태

Waiting:
Running:
Terminated: 파드가 제거요청을 받게 되면, 컨테이너들에 바로 SIG KILL 신호가 전달되지 않는다. termination of pods https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination 를 참고하자. kubelet은 graceful shutdown 을 먼저 시도한다.

별다른 설정이 없으면, kubelet은 각 컨테이너의 메인 프로세스들에게, SIG TERM 신호를 전송하고 terminationGracePeriodSeconds(디폴트 30초) 시간을 기다린다. 이 시간이 지나면 강제종료시킨다. 만약 pod의 yaml파일에 컨테이너의 preStop 훅이 기술되어 있다면, SIG TERM 신호를 받기 전 이 hook 이 동기적으로 수행시킨다. 그 이후 SIG TERM 신호전송한다. preStop 훅이 수행되고 있을때부터 pod 의 phase는 Terminating 상태로 변경된다.

PreStop 시작시간부터, terminationGracePeriodSeconds 시간이후에 컨테이너는 강제종료 시그널을 받게 된다. 만약 그 전에 정상종료를 시키고 싶다면 아래 조건이 만족되면 된다.

preStop 소요시간 + TERM signal 수신 및 정상종료 소요시간 < terminationGracePeriodSeconds(default 30)

Container가 PreStop 훅이 없으면, SigTerm 신호를 받게됨과 동시에 Terminating 상태로 변경되게 된다. 문서에서 약간 애매하게 읽히긴 하지만(https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination) SigTerm을 받으면서 바로 service endpoint 에서 빠지는게 아닌 것 같다. 이경우에 종료중인 프로세스에 트래픽이 전달되는 유실사태가 벌어지므로 PreStop 훅으로 sleep을 주어 Terminating 상태에서 프로세스가 죽지않고 기동되는 충분한 시간을 주어 service endpoint에서 빠질 시간을 충분히 주도록 하여 트래픽유실을 없앨 수 있었다

At the same time as the kubelet is starting graceful shutdown of the Pod, the control plane evaluates whether to remove that shutting-down Pod from EndpointSlice (and Endpoints) objects, where those objects represent a Service with a configured selector.

참고

pod phase
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
container states
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-states
container livecycle hooks
https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/
사람인 기술 블로그
https://saramin.github.io/2022-05-17-kubernetes-autoscaling/