라이브니스 프로브 (Liveness Probe)

niyu·2022년 7월 22일
0

쿠버네티스 기초

목록 보기
3/15
post-thumbnail

컨테이너의 주 프로세스에 crash가 발생한다면 kubelet이 컨테이너를 다시 시작한다. 어플리케이션에 버그가 발생하면 쿠버네티스가 자동으로 다시 시작하기 때문에 어플리케이션 자체에 특별한 작업을 하지 않아도 쿠버네티스에서 실행 중인 어플리케이션을 자동으로 복구할 수 있다.

하지만 어플리케이션이 무한 루프나 교착 상태에 빠져 응답을 멈추는 상황에는 어떨까? Crash 같은 경우에는 프로세스가 강제로 종료되지만 무한루프나 교착 상태라면 아무도 알 수가 없다. 그래서 k8s에서는 라이브니스 프로브를 사용해 컨테이너가 살아있는 지 여부를 확인한다.

Liveness Probe

라이브니스 프로브를 지정해 k8s가 더 이상 정상적이지 못한 경우 즉시 컨테이너를 재시작하게 할 수 있다.

라이브니스 프로브를 통해 컨테이너가 아직 살아있는지 확인할 수 있다. k8s는 주기적으로 검사를 실행하고 검사가 실패할 경우 컨테이너를 다시 시작한다.

컨테이너 진단은 컨테이너가 구현한 핸들러를 kubelet이 호출해서 실행한다.

라이브니스 프로브
라이브니스 프로브 (출처: bcho.tistory.com/1264)

운영 환경에서 실행 중인 파드의 경우, 항상 라이브니스 프로브를 정의해야 한다. 정의되어 있지 않으면 k8s는 어플리케이션이 아직 살아 있는지 여부를 알 수 없다.

k8에는 3가지 방법의 라이브니스 프로브가 있다.

HTTP Request

HTTP GET 프로브는 지정한 IP 주소, 포트, 경로에 HTTP GET 요청을 수행한다. 응답이 오류를 나타내면 프로브는 실패로 간주하고 컨테이너를 재시작한다.

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe: 
      httpGet:  # HTTP Get을 수행할 라이브니스 프로브
        path: /healthz # 네트워크 포트 HTTP 요청에서 요청할 경로
        port: 8080 # 프로브가 연결해야 하는 네트워크 포트
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3 # 컨테이너가 시작하고 3초 후 프로브 시작
      periodSeconds: 3 # 3초마다 프로브 실행

정의된 프로브는 k8s에게 컨테이너가 여전히 정상적으로 동작하는지 체크하기 위해 '/healthz' 경로의 포트 8080 HTTP GET 요청을 주기적으로 수행하도록 알려준다. 컨테이너 내에서 실행 중인 웹서버가 HTTP 요청에 응답하지 않으면 컨테이너를 다시 시작한다.

동작 중인 라이브니스 프로브 보기

kubectl describe 커맨드를 이용해 라이브니스 프로브를 확인할 수 있다.

kubectl describe po liveness-http
kubectl describe (출처: timewizhan.tistory.com/entry/Kubernetes-Liveness-Readiness-Probe)

State를 통해 컨테이너의 상태를 확인할 수 있으며 Last State는 지난 컨테이너의 상태를 확인할 수 있다. 지난 컨테이너가 있는 이유는 컨테이너가 문제가 생겨 강제 종료하고 다시 생성했기 때문이다.

또한 Liveness를 통해 라이브니스 프로브의 정보를 확인할 수 있다. 컨테이너가 실행되고 3초(delay) 이후 프로브를 시작하며 요청시 1초(timeout) 이내에 응답을 해야 한다. 그렇지 않으면 실패한다. 3초 마다(period) HTTP GET 요청을 하며 연속으로 3번 실패(failure)하면 kubelet이 해당 컨테이너를 재시작시킨다.

TCP Socket

컨테이너의 지정된 포트에 TCP를 연결하려고 시도한다. 성공적으로 연결되면 프로브가 성공한 것이고, 그렇지 않으면 컨테이너가 재시작한다.

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: k8s.gcr.io/goproxy:0.1
    ports:
    - containerPort: 8080
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

TCP Socket을 통한 프로브는 HTTP Request 프로브와 비슷하다.

Exec Command

컨테이너 내부에 임의의 명령을 실행하고 명령의 종료 상태 코드를 확인한다. 상태 코드가 0이면 검사가 성공한 것이고, 다른 모든 코드는 오류로 간주된다.

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

kubelet이 initialDelaySeconds, periodSeconds를 고려해 cat /tmp/healthy 명령어를 수행한다. 컨테이너의 args를 보면 내부적으로 해당 빈 파일을 만들고 삭제하기 때문에 만일 삭제가 되면 라이브니스 프로브는 실패를 의미한다. kubelet은 지속적으로 커맨드를 보내는데 파일이 없으면 컨테이너가 비정상적이라는 것으로 판단한다.


References

0개의 댓글