컨테이너의 주 프로세스에 crash가 발생한다면 kubelet이 컨테이너를 다시 시작한다. 어플리케이션에 버그가 발생하면 쿠버네티스가 자동으로 다시 시작하기 때문에 어플리케이션 자체에 특별한 작업을 하지 않아도 쿠버네티스에서 실행 중인 어플리케이션을 자동으로 복구할 수 있다.
하지만 어플리케이션이 무한 루프나 교착 상태에 빠져 응답을 멈추는 상황에는 어떨까? Crash 같은 경우에는 프로세스가 강제로 종료되지만 무한루프나 교착 상태라면 아무도 알 수가 없다. 그래서 k8s에서는 라이브니스 프로브를 사용해 컨테이너가 살아있는 지 여부를 확인한다.
라이브니스 프로브를 지정해 k8s가 더 이상 정상적이지 못한 경우 즉시 컨테이너를 재시작하게 할 수 있다.
라이브니스 프로브를 통해 컨테이너가 아직 살아있는지 확인할 수 있다. k8s는 주기적으로 검사를 실행하고 검사가 실패할 경우 컨테이너를 다시 시작한다.
컨테이너 진단은 컨테이너가 구현한 핸들러를 kubelet이 호출해서 실행한다.
라이브니스 프로브 (출처: bcho.tistory.com/1264)
운영 환경에서 실행 중인 파드의 경우, 항상 라이브니스 프로브를 정의해야 한다. 정의되어 있지 않으면 k8s는 어플리케이션이 아직 살아 있는지 여부를 알 수 없다.
k8에는 3가지 방법의 라이브니스 프로브가 있다.
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 (출처: timewizhan.tistory.com/entry/Kubernetes-Liveness-Readiness-Probe)
State
를 통해 컨테이너의 상태를 확인할 수 있으며 Last State
는 지난 컨테이너의 상태를 확인할 수 있다. 지난 컨테이너가 있는 이유는 컨테이너가 문제가 생겨 강제 종료하고 다시 생성했기 때문이다.
또한 Liveness
를 통해 라이브니스 프로브의 정보를 확인할 수 있다. 컨테이너가 실행되고 3초(delay) 이후 프로브를 시작하며 요청시 1초(timeout) 이내에 응답을 해야 한다. 그렇지 않으면 실패한다. 3초 마다(period) HTTP GET 요청을 하며 연속으로 3번 실패(failure)하면 kubelet이 해당 컨테이너를 재시작시킨다.
컨테이너의 지정된 포트에 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 프로브와 비슷하다.
컨테이너 내부에 임의의 명령을 실행하고 명령의 종료 상태 코드를 확인한다. 상태 코드가 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