새소식

Recent Study/Kubernetes 학습과정

11. Pod - Lifecycle & (ReadinessProbe, LivenessProbe)

  • -

Lifecycle

 Pod는 해당 라이프사이클 단계에 따라 주요 행동들이 있습니다. 

Pod 생성과정

 

 status 안에 Phase라고 해서 Pod의 전체 상태를 대표하는 속성이 있습니다. 그리고 Pod가 생성되면서 실행하는 단계들이 있는데 그 단계와 상태를 알려주는 것이 Conditions라는 특성입니다. 또한 컨테이너마다도 State라고 해서 각각의 컨테이너를 대표하는 상태가 있습니다. 

 

먼저 Pod를 대표하는 Phase 종류는 아래와 같습니다.

(1) Pending, (2) Running (3) Succeeded, (4) Failed, (5) Unknown

 

Conditions는 4종류가 있고, Reason이라고 해서 Condition의 세부 내용을 알려주는 항목이 있습니다.

(1) Initizlized, (2) ContainerReady, (3) PodScheduled, (4) Ready

(1) ContainersNotReady, (2) PodCompleted

 

containers의 상태는 State,  Reason이라는 세부 내용을 알려주는 항목이 있습니다.

(1) Waiting, (2) Running, (3) Terminated

(1) ContainerCreating, (2) CrashLoopBackOff, (3) Error, (4) Completed

 

 

생성과정

 

1. 먼저 Pod의 최초 상태는 Pending이고, 이 상태일 때 Pod 안에서 일어나는 일들에 대해 알아봅시다. Pod가 어느 노드 위에 올라갈지 직접 노드를 지정했을 때는 지정한 해당 노드에 아니면 k8s가 스스로 자원의 상황을 판단해서 노드를 결정하기도 하는데요.

 이것이 완료되면 (1) PodScheduled : True 로 변합니다. 추후 (2) initContainer 라고 해서 본 컨테이너가 기동되기 전에 초기화 시켜야 하는 내용들이 있을 경우 그 내용을 담는 컨테이너가 있습니다. (볼륨 설정 같은 것)

 

2. 다음으로 컨테이너의 이미지를 다운로드하는 동작이 있고, 이러한 두 과정 동안에 컨테이너의 state는 Waiting이고, reason은 ContainerCreating 입니다. 추후 컨테이너가 기동되면서 Pod와 컨테이너의 상태는 Running이 됩니다. 근데 만약 컨테이너 중 하나가 문제 발생으로 인해 재시작 될 수 있습니다.  이때 컨테이너의 상태는 waiting이 되고, CrashLoopBackOff라는 reason을 보여줍니다.

 Pod는 위의 상태들에 대해 running이라고 간주를 하고, 대신 내부 condition의 ContainerReady 와 Ready는 false 입니다. 그래도 결국 모든 컨테이너가 정상적으로 기동한다면 ContainerReady, Ready는 모두 True가 됩니다.

 

3. 중요한 점은 Pod의 상태가 Running이라도 내부 컨테이너들의 상태가 Running이 아닐 수 있기 때문에, Pod 뿐만 아니라 컨테이너의 상태도 모니터링 해줘야 합니다. 그리고 Job, CronJob으로 생성된 Pod의 경우 자신의 일을 수행했을 때는 Running 중이지만 일을 마치면 Pod는 더이상 일을 하지 않는데, 이때 Pod의 상태는 Failed, Succeeded 2개로 갈릴 수 있습니다. 작업을 하고 있는 컨테이너 중 하나라도 문제가 생겨서 에러가 나면 Pod의 상태는 Failed가 되고, 모든 컨테이너가 Completed라면 Pod의 상태는 Succeeded가 됩니다.

 

이때 또 Pod의 컨디션 값이 변하게 되는데, 성공이건 실패건 간에 ContainerReady, Ready의 값이 false로 바뀌게 됩니다. 

 

 

ReadinessProbe, LivenessProbe

ReadinessProbe, LivenessProbe

 Pod를 만들면 안에 컨테이너가 생기고, Pod와 컨테이너의 상태가 Running이 되면서 안에 있는 앱도 정상적으로 구동이 되고, 있을 겁니다. Pod는 서비스에 연결이 되고, 서비스의 ip가 외부로 알려지고 서비스를 통해 많은 사람들이 실시간으로 접근하게 되는 상황이 됐습니다. 한 서비스에 2개의 Pod가 연결이 되어서, 50%씩 트래픽이 나눠진다고 해보겠습니다. 

 

 이렇게 서비스가 운영되다가 노드2 서버가 다운이 됐어요. 그럼 이 위에 있는 Pod2도 Failed이 되면서 Pod1으로 100% 접속을 하게 될 거에요. Pod1이 트래픽을 견딘다면 앱 서비스를 유지하는데 문제가 없습니다. 이제 죽은 Pod2는 Auto Healing 기능에 의해 다른 노드에 재생성 되려고 할건데 그 과정에서 Pod, Container가 Running 상태가 되면서 서비스와 연결이 되는데 아직 앱이 구동 중인 순간이 발생합니다.

 

1) 서비스가 연결이 되자마자 트래픽이 Pod2로 유입이 되기 때문에 앱이 구동되고 있는 순간에는 사용자는 50% 확률로 Error 페이지를 보게 됩니다. 근데 Pod를 만들 때 ReadinessProbe 설정을 주게 되면 이런 문제를 피할 수 있습니다(앱 구동되기 전까지는 서비스와 연결이 되지 않게 해줍니다.) 그래서 Pod2의 상태는 Running이지만, 트래픽은 Pod1 한테만 계속 가고, 앱이 완전히 준비되면 서비스와 연결이 되면서 트래픽이 다시 50 대 50으로 흐르게 됩니다.

 

2) 만약에 하나의 앱이 장애가 생겼다고 가정했을 때, Pod는 Running 상태입니다. 예로 서비스를 Tomcat으로 돌릴 때 위에 실행되고 있는 앱에 메모리 오버플로우라든지 문제가 생겨서 접속을 하면 500 서버 에러가 나는 경우가 있죠.  이때 앱에 장애 상황을 감지해주는 것이 LivenessProbe인데, 마찬가지로 Pod를 만들 때 이를 달아주면 앱에 문제가 생길시 Pod를 재실행하게 만들어서 잠깐의 트래픽 에러는 발생하겠지만, 지속적 에러 상태 나는 것을 방지해줍니다. 

 즉 ReadinessProbe를 이용해 서비스를 더욱 안정적으로 유지하고, LivenessProbe를 통해 앱 장애시 지속적인 실패를 예방할 수 있기 때문에 Pod 생성시 꼭 사용하는 것을 권장합니다.

 

 

상세 동작 과정

ReadinessProbe

 ReadinessProbe, LivenessProbe는 사용 목적이 다른 것이지, 설정할 수 있는 내용은 같습니다. 공통적인 부분은 httpGet, Exec, tcpSocket으로 해당 앱에 대한 상태를 확인할 수 있습니다. Exec는 특정 명령어를 날려서 그에 따른 결과를 체크하고, tcpSocket은 포트 번호와 호스트명을  체크해서 ReadinessProbe, LivenessProbe의 성공 여부를 확인할 수 있습니다. 이 셋 중에 하나는 꼭 정해야 되는 속성이 있고, 또는 옵션 값이 있습니다.

 

옵션 종류 (아래 모두 설정 안하면 차례대로 (0, 10초, 1초, 1회, 3회) default 값으로 지정이 됩니다.)

initialDelaySeconds: 최초 프로브를 하기 전의 Delay 시간

periodSeconds : 프로브를 체크하는 시간 간격

timeoutSeconds : 이 지정된 시간까지 결과가 와야함

successThreshold : 몇 번 성공 결과를 받아야 성공으로 인정할건지

failureThreshold :  몇 번 실패를 받아야 실패로 인정할건지

 

 ReadinessProbe 설정을 마치고, Pod를 만들 때 노드가 스케줄되고 이미지가 다운받아지면서 Pod와 컨테이너 상태는 Running이 되지만, 프로브가 성공하기 전까지는 Condition의 Container Ready, Ready 상태가 false로 고정됩니다. 그리고 이 상태가 계속 false 된다면 Endpoint에서는 이 Pod의 IP를 NotReadyAddr로 간주하고, 서비스에 연결하지 않습니다.

 

 그럼이제 k8s가 ReadinessProbe에 정의된 내용대로 앱 서비스의 기동 상태를 체크를 해볼 건데 컨테이너 상태가 Running이 되면 최초 5초 동안 지연을 하고 있다가 5초가 지나면 ready.txt 파일이 있는지 체크해보고, 파일이 없다면 10초 후에 다시 체크를 하게 됩니다. 근데 계속해서 데이터가 없다면 이 Pod의 Condition은 false로 유지가 될 것입니다.

 

 이 노드에 ready.txt라는 데이터를 추가하면 컨테이너 볼륨과 연결이 되어 있으니까 다음 readinessProbe를 체크할 때 성공 결과를 받게 됩니다. 그리고 3번 성공을 확인하게 되면 Pod의 Condition의 상태는 true가 되고, Endpoint도 정상적으로 address로 간주하고 서비스와 연결이 되게 됩니다. 

 

 

LivenessProbe

 이번에는 LivenissProbe를 설명하겠습니다. 한 서비스에 2개 Pod가 Running되고 있는 상태입니다. 한 앱의 내용을 보면 /health라는 경로를 날리면 status 200을 주면서 서비스가 정상적으로 운영 중이라는 헬스 체크가 만들어져있습니다. 그리고 이 컨테이너에는 LivenissProbe가 달려있고, 내용으로는 httpGet으로 Path의 /health 경로를 체크합니다.

 

 옵션으로 최초 5초 지연, 10초 간격으로 체크, 3번을 실패하게 되면 Pod가 재시작 되도록 설정되어 있습니다. k8s가 이제 httpGet으로 5초 후에 Path를 체크 해보고 200 OK를 받을 거예요. 그리고 10초 후 다시 체크를 해보지만 마찬가지로 200 OK를 받으면서 서비스가 정상적으로 운영 중이라고 판단을 하게 되는데 어느 순간 장애가 났을 때 이 Path를 호출하면 500 Status를 받습니다. 하지만 Pod는 Running 상태이고, 3회를 상태로 500을 받게 되면 k8s는 문제가 있다고 판단해서 이 Pod를 Restart 해버립니다.

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.