Part 2. 백엔드 개발과 Kubernetes

Ch 3. Healthcheck Probe를 위한 엔드포인트 만들기

Ch 3. Healthcheck Probe를 위한 엔드포인트 만들기


01. Kubernetes Probe와 Healthcheck

Kubernetes Probe와 Health Check

Kubernetes는 컨테이너를 자동으로 실행하고 관리하는 플랫폼이다. 하지만 단순히 컨테이너 프로세스가 살아 있다는 사실만으로 애플리케이션이 정상이라고 판단하기는 어렵다.

예를 들어 Spring Boot 서버가 실행 중이더라도 다음과 같은 상황이 발생할 수 있다.

  • 모든 요청 처리 스레드가 고갈된 상태
  • 데이터베이스 연결이 모두 끊어진 상태
  • 데드락(Deadlock)에 빠진 상태
  • 무한 루프에 빠진 상태
  • 응답 시간이 지나치게 느려진 상태

이 경우 프로세스는 살아 있지만 실제 서비스는 정상적으로 동작하지 않는다.

Probe는 Kubernetes가 컨테이너의 상태를 확인하기 위해 사용하는 메커니즘이며, 애플리케이션이 스스로 자신의 상태를 알려주는 Health Check와 함께 사용된다.


Health Check란?

가장 단순한 형태의 Health Check는 특정 URL에 요청을 보냈을 때 정상 응답을 반환하는 것이다.

예를 들어 다음과 같은 API를 제공할 수 있다.

@GetMapping("/check")
public String healthCheck() {
    return "OK";
}

정상 상태라면

GET /check

200 OK

응답을 반환한다.

반대로

404 Not Found

또는

Timeout

이 발생하면 Kubernetes는 애플리케이션에 문제가 있다고 판단할 수 있다.


Kubernetes의 컨테이너 상태 체크

Kubernetes는 주기적으로 컨테이너 상태를 확인한다.

지원하는 방식은 다음과 같다.

  • HTTP Probe
  • TCP Probe
  • gRPC Probe
  • Exec Probe

상태 확인은 각 노드에서 실행되는 kubelet이 수행한다.

graph LR
    Kubelet --> Probe
    Probe --> Container

    Container -->|200 OK| Probe

Probe 공통 설정

모든 Probe는 비슷한 설정값을 가진다.

readinessProbe:
  httpGet:
    path: /health
    port: 8080

  initialDelaySeconds: 10
  periodSeconds: 5
  timeoutSeconds: 2
  successThreshold: 1
  failureThreshold: 3

initialDelaySeconds

컨테이너 시작 후 첫 번째 Probe를 실행하기 전에 기다리는 시간이다.

initialDelaySeconds: 10

의미

Container Start
      ↓
10초 대기
      ↓
첫 Probe 실행

Spring Boot 애플리케이션은 기동 시간이 필요하기 때문에 보통 몇 초 정도의 여유를 둔다.


periodSeconds

Probe 실행 주기이다.

periodSeconds: 5

의미

Probe
 ↓ 5초
Probe
 ↓ 5초
Probe

주기를 짧게 하면 장애를 빠르게 감지할 수 있다.

반대로 너무 짧으면 불필요한 요청이 많이 발생할 수 있다.


timeoutSeconds

응답을 기다리는 최대 시간이다.

timeoutSeconds: 2

2초 안에 응답이 없으면 실패로 판단한다.

Request
   ↓
2초 초과
   ↓
Failure

successThreshold

몇 번 연속 성공해야 정상으로 판단할지 지정한다.

successThreshold: 2

의미

Success
Success
↓
Ready

Readiness Probe에서 주로 사용된다.


failureThreshold

몇 번 연속 실패해야 비정상으로 판단할지 지정한다.

failureThreshold: 3

의미

Fail
Fail
Fail
↓
Unhealthy

값이 너무 작으면 일시적인 장애에도 민감하게 반응할 수 있다.


terminationGracePeriodSeconds

Probe 실패 후 컨테이너 종료 시 주어지는 유예 시간이다.

terminationGracePeriodSeconds: 30

의미

Probe Failure
      ↓
SIGTERM
      ↓
30초 대기
      ↓
강제 종료

최근 Kubernetes에서는 Probe 단위로도 설정할 수 있다.


Probe 종류

Kubernetes는 세 가지 Probe를 제공한다.

Startup Probe
     ↓
Readiness Probe
     ↓
Liveness Probe

Startup Probe

애플리케이션이 정상적으로 기동되었는지 확인한다.

Startup Probe가 성공하기 전까지는

  • Readiness Probe 실행 안 함
  • Liveness Probe 실행 안 함
graph LR
    StartupProbe --> Success
    Success --> ReadinessProbe
    Success --> LivenessProbe

Startup Probe 예시

startupProbe:
  httpGet:
    path: /actuator/health
    port: 8080

  periodSeconds: 5
  failureThreshold: 20

의미

5초마다 확인
20번 실패 가능

최대 대기 시간

5 × 20 = 100초

100초 안에 기동하지 못하면 컨테이너를 재시작한다.


Readiness Probe

컨테이너가 트래픽을 받을 준비가 되었는지 확인한다.

가장 중요한 특징은

컨테이너를 종료시키지 않는다.

이다.

대신 Service의 Endpoint 목록에서 제거한다.


정상 상태

graph LR
    Service --> Pod1
    Service --> Pod2
    Service --> Pod3

Readiness 실패

graph LR
    Service --> Pod1
    Service --> Pod3

    Pod2["Pod2 (Not Ready)"]

Pod2는 살아 있지만 트래픽을 받지 않는다.


Readiness Probe 예시

readinessProbe:
  httpGet:
    path: /actuator/health/readiness
    port: 8080

  periodSeconds: 5
  failureThreshold: 2

사용 목적

애플리케이션 초기 기동
Container Start
      ↓
Readiness Success
      ↓
Service 연결
      ↓
트래픽 수신

실행 중 장애 감지
Ready 상태
      ↓
Readiness Failure
      ↓
Endpoint 제거
      ↓
트래픽 차단
      ↓
Readiness Success
      ↓
Endpoint 재등록

일시적으로 과부하가 발생했을 때 매우 유용하다.


Liveness Probe

컨테이너가 정상 동작 중인지 확인한다.

Readiness와 가장 큰 차이는

실패 시 컨테이너를 재시작한다.

는 점이다.


Liveness Probe 예시

livenessProbe:
  httpGet:
    path: /actuator/health/liveness
    port: 8080

  periodSeconds: 10
  failureThreshold: 3

동작 과정

Liveness Fail
      ↓
Failure Threshold 초과
      ↓
Container Stop
      ↓
Container Restart

해결 가능한 문제

  • 무한 루프
  • 데드락
  • 스레드 고갈
  • 메모리 누수 후 응답 불가 상태
  • 내부 로직 오류

주의사항

Liveness Probe 실패는 생각보다 비용이 크다.

Container 종료
↓
Container 재생성
↓
Startup Probe
↓
Readiness Probe
↓
서비스 복귀

Spring Boot 기준으로 수 초에서 수십 초가 걸릴 수도 있다.

따라서 지나치게 민감하게 설정하면 오히려 서비스 품질이 떨어질 수 있다.


Spring Boot 권장 설정

Spring Boot Actuator를 사용하는 경우 일반적으로 다음과 같이 구성한다.

startupProbe:
  httpGet:
    path: /actuator/health
    port: 8080

readinessProbe:
  httpGet:
    path: /actuator/health/readiness
    port: 8080

livenessProbe:
  httpGet:
    path: /actuator/health/liveness
    port: 8080

Spring Boot 2.3 이상에서는 Readiness와 Liveness Endpoint를 기본 제공한다.


Probe 설정 시 고려사항

Readiness가 Liveness보다 더 민감해야 한다

일반적으로 다음 순서가 좋다.

Readiness 실패
↓
트래픽 차단

(복구 시도)

↓

Liveness 실패
↓
재시작

즉, 먼저 트래픽을 차단하고 최후의 수단으로 재시작하는 것이 좋다.


Health Check는 가벼워야 한다

좋은 예

메모리 확인
스레드 상태 확인
애플리케이션 상태 확인

나쁜 예

복잡한 DB 조회
외부 API 호출
대용량 데이터 조회

Probe는 수 초마다 호출되므로 반드시 빠르게 처리되어야 한다.


Probe 설정은 배포 시간에도 영향을 준다

예를 들어

startupProbe:
  periodSeconds: 10
  failureThreshold: 30

이라면

최대 300초

동안 Startup Probe가 수행될 수 있다.

따라서 Probe 설정은 단순한 상태 체크를 넘어 배포 속도와 서비스 가용성에도 직접적인 영향을 준다.


정리

Probe는 Kubernetes의 자가 복구(Self-Healing) 기능을 가능하게 만드는 핵심 기능이다.

Startup Probe
↓
애플리케이션 기동 확인

Readiness Probe
↓
트래픽 수신 가능 여부 판단

Liveness Probe
↓
컨테이너 재시작 여부 판단

실무에서는 보통

  • Startup Probe → 느슨하게
  • Readiness Probe → 민감하게
  • Liveness Probe → 신중하게

설정하는 것이 일반적이며, 특히 Liveness Probe는 컨테이너 재시작이라는 큰 비용을 동반하기 때문에 충분한 검토 후 적용하는 것이 좋다.


© 2020. All rights reserved.

SIKSIK