쿠버네티스 패턴 - 4장 정상상태 점검

오정재·2021년 4월 21일
5

쿠버네티스 패턴

목록 보기
5/12
post-thumbnail

👉 정상상태 점검

정상상태 점검 패턴은 쿠버네티스를 통해서 어플리케이션의 정상상태를 파악하기 위한 패턴입니다.
클라우드 네이티브에서 원하는 완전 자동화에 도달하기 위해서는
어플리케이션의 상태를 빠르게 파악하고 장애가 있다면 회복해야합니다.

따라서 이번 글에서는 쿠버네티스가 지원하는 정상상태 점검에 대해 얘기하겠습니다.

🍏 문제점

쿠버네티스는 컨테이너 프로세스 상태를 주기적으로 확인하고 문제가 감지되면 다시 시작합니다.
하지만 프로세스 상태만으로 어플리케이션이 정상적인지를 판단하는 것은 충분하지 않습니다.

실제로 어플리케이션이 OOM이 생겨도 여전히 JVM 프로세스는 실행중일 수 있으며,
무한 루프, Deadlock 상태와 같이 실제 동작을 하지 않고 있는 것일 수 있습니다.

결과적으로 어플리케이션이 예상대로 작동중이며 사용자에게 제공할 수 있는지에 대한 여부를 확인할 필요가 있습니다.

🍏 해결책

소프트웨어를 만들면서 오류가 없는 코드를 작성하는 것은 거의 불가능합니다.
따라서 현재는 소프트웨어를 완벽하게 만드는 것보다 장애를 감지하고 복구하는 방법을 주로 사용하고 있습니다.

이번 글에서는 장애를 감지하기위해 쿠버네티스에서 제공하는 Probe에 대해서 설명할 것입니다.
Probe란 kubelet에 의해 주기적으로 수행되는 진단입니다.

이를 통해서 Process health check 부터 디테일한 Probe까지 설명하겠습니다.

Process health check

쿠버네티스의 모든 노드는 kubelet을 가지고 있으며 POD를 관리하는 역할을 담당하고있습니다.

특히 kubelet은 POD의 Process health check를 통해 Process가 실행중이 아니라면 재시작 하도록 합니다.

하지만 Process가 실행중이라고 해도 무한 루프, Deadlock 상태와 같이 실제 동작을 하지 않고 있는 경우가 있습니다.
이를 위해서 kubelet은 다양한 Probe를 통해서 철저하게 POD의 장애를 감지합니다.

Probe Type을 설명하기에 앞서 POD의 장애를 감지하기 위한 Probe Handler에 대해 설명하겠습니다.

Probe Handler

Container Probe는 kubelet에 의해 주기적으로 수행되며 Process health check를 통해 확인하지 못한 장애를 감지합니다.
이를 위해 kubelet은 컨테이너에 의해 구현된 세 가지 타입의 핸들러로 Probe를 수행합니다.

1) Exec Action

Exec Action은 컨테이너 내에서 지정된 명령어를 실행하고 상태 코드가 0으로 종료되면 성공한 것으로 간주합니다.

yaml 예시는 다음과 같습니다.

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 -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

위의 예시를 보면 Probe를 수행하기 위해 kubelet은 cat /tmp/healthy 를 수행하며
명령이 성공하면 0을 반환하고 정상 상태로 간주합니다.

여기서 periodSeconds 는 Probe를 수행하는 간격으로 5초마다 수행하는 것을 나타내며
initialDelaySeconds 는 첫 번째 Probe를 수행하기 전 5초 동안 기다려야한다는 것을 나타냅니다.

2) TCP Socket Action

TCP Socket Action은 지정된 포트컨테이너의 IP 주소에 대해 TCP 연결을 맺어 검사를 수행합니다.
만약 포트가 활성화되어 있고 연결이 잘 된다면 성공한 것으로 간주합니다.

yaml 예시는 다음과 같습니다.

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

위의 예시를 보면 IP:PortTCP 연결을 맺어 검사를 수행합니다.
periodSecondsinitialDelaySeconds 는 Exec Action 에서 설명한 것과 같습니다.

3) HTTP Get Action

HTTP Get Action은 지정된 포트 및 경로컨테이너의 IP 주소에 대한 HTTP GET 요청을 수행합니다.
만약 200 ~ 399에 해당하는 Status Code가 반환되면 성공한 것으로 간주합니다.

yaml 예시는 다음과 같습니다.

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3
      periodSeconds: 3

위의 예시를 보면 IP:8080/healthz 로 HTTP GET 요청을 보냅니다.
만약 200 ~ 399에 해당하는 Status Code가 반환되면 성공한 것으로 간주합니다.
periodSecondsinitialDelaySeconds 는 Exec Action 에서 설명한 것과 같습니다.

4) Probe Result

지금까지 컨테이너에 의해 구현된 세 가지 타입의 핸들러를 알아보았는데요.
핸들러를 통해서 컨테이너는 세 가지의 중 하나의 결과를 가질 수 있습니다.

  • Success : 컨테이너가 진단을 통과함.
  • Failure : 컨테이너가 진단에 실패함.
  • Unknown : 진단 자체가 실패하였으므로 아무런 액션도 수행되면 안됨.

이를 통해서 우리는 어플리케이션의 특성에 따라 가장 적합한 Probe Handler를 선택하고
Probe를 통해서 컨테이너의 상태를 파악할 수 있습니다.

Container Probe

kubelet은 실행 중인 컨테이너들에 대해서 선택적으로 세 가지 종류의 Probe를 수행하고 조치를 취할 수 있습니다.

따라서 세 가지 종류의 Probe의 역할과 조치를 알아보도록 하겠습니다.

1) Liveness Probe

Liveness Probe는 컨테이너가 동작 중인지에 대한 여부를 자세하게 판단하기 위해 사용합니다.

예를 들어 컨테이너 프로세스가 무한 루프, Deadlock 상태 때문에 진행할 수 없는 경우
Process health check로 잡아낼 수 없는 장애를 Liveness Probe를 통해서 판단할 수 있습니다.

만약 Probe에 실패한다면, 비정상적인 컨테이너를 제거하고 새로운 컨테이너로 대체합니다.
또한 컨테이너에 Liveness Probe가 명시되어있지 않다면 기본 상태는 Success 입니다.

👍 따라서 컨테이너 프로세스의 상태를 자세하게 판단할 때 유용합니다.

2) Readiness Probe

Readiness Probe는 어플리케이션이 언제 작업을 수행할 준비가 되었는지를 판별할 때 사용합니다.

예를 들어 하나의 파드가 압축 해제 및 데이터베이스 테이블을 채우는 초기화 작업을 수행해야 할 수 있습니다.
이 경우 Readiness Probe는 컨테이너의 준비가 완료될 때까지 트래픽을 받지 않고 Probe가 성공하기 시작한 이후에만 트래픽을 받을 수 있습니다.

만약 Probe에 실패한다면 Endpoint controller는 파드에 연관된 모든 서비스들의 Endpoint에서 파드의 IP 주소를 제거하며 컨테이너를 재시작하지 않습니다.
또한 컨테이너에 Readiness Probe가 명시되어있지 않다면 기본 상태는 Success 입니다.

👍 따라서 컨테이너가 대량의 데이터, 설정 파일들, 마이그레이션을 처리해야할 때 유용합니다.

3) Startup Probe

Startup Probe는 컨테이너를 실행하고 준비하는 데 오래 걸리는 파드에 사용합니다.

예를 들어 어플리케이션의 기동이 오래 걸리는 상황에서 Liveness Probe가 체크되면 조치에 맞게 계속해서 파드를 재시작합니다.
그리고 Readiness Probe도 마찬가지로 어플리케이션이 기동되기 전에 Probe가 진행되면 트래픽이 실패가 됩니다.

따라서 Startup Probe를 같이 쓴다면 컨테이너를 실행하고 준비하는 동안에
Liveness와 Readiness Probe를 하지 않기 때문에 더 안정적으로 컨테이너를 준비시킬 수 있습니다.

Startup Probe는 Liveness Probe와 마찬가지로 Probe가 실패하면 컨테이너를 재시작 하며,
컨테이너에 Startup Probe가 명시되어있지 않다면 기본 상태는 Success 입니다.

👍 따라서 서비스를 시작하는 데 오랜 시간이 걸리는 컨테이너에 Livenes Probe와 Readiness Probe를 같이 사용할 때 유용합니다.

🍏 정리

클라우드 네이티브에서 원하는 완전한 자동화를 위해서는 어플리케이션의 장애를 빠르게 감지하고 해결할 수 있는 것이 필요합니다.
정상상태 확인 패턴은 어플리케이션의 장애를 감지하고 조치하기 위한 여러가지 방법을 제공합니다.

하지만 쿠버네티스는 컨테이너를 블랙박스로 취급하기 때문에 장애를 판별하고 나서 내부의 오류를 직접적으로 해결할 수 없습니다.
따라서 어플리케이션 내부의 오류를 해결하기 위한 다양한 방법들을 지원해야합니다.
대표적으로 로깅을 통해서 파악하는 것이 있으며 쿠버네티스가 더 정밀한 관찰을 할 수 있도록 어플리케이션 내에서 API를 제공하는 것도 좋은 방법이 될 것입니다.

👉 Reference

profile
ohhong

0개의 댓글