원래는 지금까지 단순한 헬스체크 API를 만들고 어플리케이션이 살아있는지 용도로만 사용했었는데
쿠버네티스 구축을 해보면서 헬스체크가 startupProbe, readinessProbe, livenessProbe 로 구분되어 헬스체크를 하는데
3단계로 나눈 목적에 대해서 공부하고 나니까 헬스체크를 단순 어플리케이션이 살아있는지 용도로 쓰면 안되겠다라는 생각이 들었습니다.
예를 들어서 단순한 헬스체크 API로 검사를 하고 있다고 가정하고
특정 Zone에 있는 DB에 문제가 생겨 해당 Zone 스프링부트가 DB랑 연결이 안된다는 상황일 때
단순한 헬스체크는 OK를 응답하기 때문에 서비스 트래픽이 해당 Zone 스프링부트로 흐르게 될거고
이는 즉 서비스 장애를 유발할겁니다.
그렇기 때문에 좀 더 특별한 헬스체크를 구성해야겠다 라고 생각이 들어 구글을 뒤지다가 상세한 헬스체크를 공부하게 되었습니다.
기본적으로 SpringBoot Actuator 를 의존성을 받으면
자동으로 헬스체크 엔드포인트가 활성화가 되는데요
/actuator/health
헬스체크 역시 커스텀하여 원하는 용도로 사용할 수 있습니다.
Actuator Health 체크 작동 원리는
헬스체크 API 호출 시
HealthEndpointSupport.class getAggregateContribution
메소드가
HealthContributor
를 반복하면서 상태를 체크하게 되는 로직입니다.
HealthContributor
: HealthIndicator
인터페이스의 부모 인터페이스해당 작동 코드
스프링부트는 4가지 종류의 어플리케이션 상태가 있는데요 밑에와 같습니다.
UP
: 작동 중이고 접근 가능하다.DOWN
: 작동하지 않고나 접근할 수 없다. OUT_OF_SERVICE
: 상태가 분명하지 않다.UNKNOWN
: 접근할 수 있지만, 현재는 사용할 수 없다. HealthIndicator
@Component
public class CustomHealthIndicator implements HealthIndicator {
@Override
public Health health() {
int errorCode = check();
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
private int check() {
// 헬스체크 판단 로직
return ...
}
}
쿠버네티스에서는 3가지 종류의 Probe가 있습니다.
actuator health에는 group이 설정 가능한데요
각 group 별로 특정 HealthIndicator를 제외하거나 포함시킬 수 있기 때문에 원하는 구성이 가능합니다.
# application.yaml
management:
endpoint:
health:
group:
readiness:
show-components: always # API 호출 시 해당 HealthIndicator를 보여주는 설정
liveness:
show-components: always
exclude:
- warmup # 활성 그룹에서 warmup HealthIndicator를 제외합니다.
당연한 이야기인데 단순 헬스체크 API가 아닌 판단로직이 들어가기 때문에
판단로직에 문제가 있는 순간 엄청난 서비스 장애로 이어지겠다라는 생각이 들더라고요.
해당 헬스체크 로직들이 정상적인지 많은 테스트를 거치고 적용하는 것이 좋을 것 같습니다.
지금까지
만을 사용하면서
단순한 헬스체크 API만 구성한게 많이 아쉽긴하네요....
최대한 운영관점에서 계속 생각해보면서 설계를 진행해야겠어요
저 같은 경우는 readiness에는 DB 헬스체크
liveness는 lock걸린 스레드가 많이 있는지(이것도 확인 가능한지 공부해야할 듯)
이렇게 구성할 듯 싶네요.
다른 이야기이긴 한데
웜업을 어떤식으로 진행을 해야할지는 따로 공부를 또 해야할 것 같습니다.