spring boot/actuator in spring boot

spring boot 3.x + actuator 파헤치기. 3. endpoints 설정

Hello World Study 2023. 3. 24. 12:09

 

https://youtu.be/Ap_vrMyvya8

 

이전 시간에 actuator 를 통해 http://localhost:8080/actuator 로 접속시 아래와 같은 json 이 나오고, json 내의 링크들에 들어가면 또 다시 json 이 나오는 구조라고 설명을 했습니다. ( 이걸 HATEOAS 라고 부른다고 했었죠? )

이런식으로 정보를 얻을수 있는 링크. 정확히는 url 을 actuator 에서는 endpoint 라고 부릅니다. 

즉 http://localhost:8080/actuator/health <-- 이런 url 이 각각 endpoint 가 됩니다. 

 

의존성 라이브러리의 소스코드를 봤을때는 엄청 많은 정보들을 지원해주는 것 같았는데, 막상 실행해서 결과를 보면 위와 같이 몇 개 안보여주는것으로 되어 있습니다. actuator 에서는 java version, OS 버전 과 같은 다양한 정보를 제공해주는데 이런 정보는 누구에게나 open 되면 보안상 좋지 않기에, spring boot 에서는 default 설정으로는 위와 같이 2~3개로 제한시켜져 있기 때문입니다. 

이제 설정을 변경해서 더 많은 정보를 보여주도록 해보겠습니다.

 

기본 제공되는 endpoints

우선 spring 이 제공하는 endpoint 가 어떤게 있는지 알아봅시다.

아래에 주요 endpoint 에 대해 적어봤습니다. 이 보다 더 많은 endpoint가 있으며

더 자세한것은 아래 링크에서 확인해보세요.

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints

beans 등록된 bean 목록 제공
caches cache 사용중이라면 cache 관련 정보 제공
conditions spring auto configuration 에 의해 bean으로 등록된것과 그렇지 않은 것의 상세 이유를 제공
health application이 구동중인지, application과 연동되는 다른 서비스(DB, message queue)가 구동중인지 여부 제공
info application 의 대략적인 정보
metrics cpu, mem, thread count 등의 모니터링용 메트릭 정보
logger 로거 설정 확인 실시간 로그 레벨 변경 제공
quartz quartz 라는 스케줄링 관련 라이브러리를 사용하고 있다면, quartz 관련 정보를 상세히 제공

위 설명만 보고서는 정확히 어떤 정보를 보여주는지 알기 어렵습니다. 중요한 endpoint 들에 대해 좀 더 세부적으로 포스팅을 하도록 하겠습니다.  일단 이런식으로 많은 정보들을 제공한다.. 라고만 알면 됩니다. 

 

endpont 들이 많다는건 알겠고, 눈으로 직접 어떤 정보들이 보여지는지 확인하고 싶을 겁니다. 자 이제 눈으로 확인해봅시다~

 

endpoint 활성화설정, 노출 설정

먼저 알아야 할것은 각 endpoint 는 enable/disable (활성화 여부)과 expose ( 노출 여부 ) 라는 2가지 설정을 할 수 있으며 2가지 모두 켜진 상태여야 외부로 노출이 됩니다.

즉 enable/disable 을 통해 spring boot 내부적으로 특정 endpoint 의 정보를 수집하는걸 설정할 수 있으며,

expose 설정을 통해 최종적으로 web 이나 jmx ( = java 모니터링 관련 프로토콜/스펙) 에 해당 정보가 보이는걸(=노출) 설정할 수 있습니다.

 

둘 중 하나라도 off 이면 노출이 되지 않습니다. 

 

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints

 

default 설정으로 활성화된 endpoint 는 shutdown 이라는 endpoint 를 제외하고 모두 활성화 되어 있습니다.

특정 endpoint 를 enable / disable 하는 방법은 

application.yml 에서 아래처럼 managment.endpoint 하위에 endpoint 명을 적고 enabled 에 true, false 를 지정해주면 됩니다.  아래 설정은 활성화, 비활성화 할수 있다는걸 보여주기 위함일 뿐이니 endpoint 명과 true, false 는 여러분 마음대로 지정해도 됩니다.

management:
  endpoint:
    shutdown:
      enabled: true
    beans:
      enabled: false
    loggers:
      enabled: true
    quartz:
      enabled: false

intellij 에서 spring boot assistent 라는 플러그인을 설치하면 yml 파일에 대해 자동 완성이 지원됩니다. 그래서 아래처럼 철자 하나하나 외우지 않아도 쉽게 설정이 가능합니다. 주의할 것은 management.endpoint 도 있고 management.endpoints 도 있다는 겁니다. 서로 역할이 다르니 오타에 유의하세요.

 

위 설정을 통해 endpoint 를 활성화/ 비활성화 했으니, 노출(expose) 설정을 해봅시다.

 

아래처럼 default 로 web과 jmx 에 대해 health 라는 endpoint 만 노출되도록 되어 있습니다.

include는 노출에 포함할 endpoint,

exclude 는 노출에 제외할 endpoint 라는 뜻입니다. 

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.exposing

만약 include 와 exclude 에 둘다 적으면 어떻게 되나요? 라고 궁금할수도 있겠네요. exclude 가 우선순위가 높다고 위 가이드에 적혀있습니다. 동작 우선순위가 명확히 지정되어 있더라도 애매하게 양쪽다 동일 endpoint 를 적으면 오해의 소지 및 버그의 씨앗이 될 수있으니 하지 말아야 겠습니다. 

 

노출방법은 아래처럼 management.endpoints.web.exposure 하위에 include 와 exclude 에 endpoint 를 적어주면 됩니다.

management:
  endpoints:
    web:
      exposure:
        include: "*"
        exclude: logger

이 또한 아래처럼 자동완성 기능을 통해 쉽게 설정 가능합니다.

아래처럼 include 필드는 Set<String> 으로 되어 있습니다. 따라서 콤마를 구분자로 해서 적으면 여러개를 넣을 수 있습니다. 

이제 활성화/비활성화, 노출 여부도 설정을 했으니 spring boot 재구동을 해봅시다.

 

아래처럼 이전보다 훨씬 많은 항목들이 나오네요.

shutdown endpoint 를 명시적으로 enable 시켰기에 shutdown 항목도 보입니다. logger, caches 는 노출 제외 시켰으므로 나오지 않습니다.  

 

주의할 점은 활성화 설정, 노출 설정을 모두 on 했더라도 추가 설정이 더 필요한 endpoint 들이 종종 있습니다.

아래 auditevents 라는 endpoint 는 AuditEventRepository 타입의 bean이 등록되어 있어야 동작을 한다고 적혀있습니다.

우린 AuditEventRepository 관련 코드가 하나도 없으니 auditevents 라는 endpoint 는 보이지 않게 됩니다.

각 endpoint 별 상세 요건은

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints 에서 확인하면 됩니다.

 

위 예제에서는 web 으로 노출 설정을 했었는데, jmx 로도 노출 설정이 아래처럼 가능합니다. 그러나 jmx 는 http, web 프로토콜이 아니어서 웹브라우저가 아닌 jmx 관련 별도 프로그램이 필요합니다. 따라서 아래처럼 설정이 가능하다 정도만 이해하고 , 실습은 web 으로만 진행하도록 하겠습니다. 그리고 web 으로 진행하는게 개발, 디버깅 등이 편리하므로, jmx 를 반드시 사용해야할 이유가 있는게 아니라면 실무에서도 web 으로 설정하길 권장합니다.

 

 

또 한가지 주의할 사항은 별표(*) 입니다.

yml 에서 * 는 특별한 의미를 가지기에 * 라고 적으면 안되고 "*" 와 같이 따옴표로 묶어줘야 에러가 나지 않습니다.

그러나 properties 에서는 * 는 특별한 의미가 아닙니다.

 

그래서 application.properties 를 사용할때는 아래처럼 별표만 넣어도 잘 동작합니다.

management.endpoints.web.exposure.include=*

그러나 yml 로 포맷 변경해서 사용시에는 "*" 와 같이 넣어야 합니다. 

management:
  endpoints:
    web:
      exposure:
        include: "*"

이건 actuator 설정시에만 적용되는게 아니라, 모든 yml 포맷에 공통적인 사항이므로 반드시 기억해둡시다.

 

보안 문제

actuator 를 통해 application의 다양한 정보를 확인할 수 있고 , 특정 endpoint 에서는 실시간 변경도 가능하게 해줍니다. ( e.g. thread dump ) 따라서 보안상 문제가 있을 수 있으므로 spring security 혹은 이와 유사한 방법으로 보안 위험을 해결하도록 해야합니다.  가장 쉬운 방법은 spring security 를 통해 /actuator url 에 대해 http basic auth 을 적용해서 id, pw 가 맞아야만 pass 되도록 하면 되며, 본 포스팅에서는 security 설정은 다루지 않습니다. ( spring security http basic auth 라고 구글링 하면 많은 정보가 나오니 참고하세요 )

 

endpoint cache

http에 etag 와 같은 캐시 방법이 존재하듯이, endpoint 에도 cache 방법이 있습니다.

endpoint 마다 캐시값을 설정해주고 싶다면 아래처럼 management.endpoint.<endpoint명>.cache.time-to-live 에 값을 적어주면 됩니다.

아래 그림처럼 time-to-live 는 java.time.Duration 타입입니다. 따라서 1s, 1ms, 10h, 20d 와 같이 값과 단위를 함께 적으면 됩니다.  각 단위는 여러분이 상상하는 바로 그 값입니다. s -> 초, ms -> 밀리초, h -> 시간, d -> 일

 

CORS support

일반적으로는 모니터링 서버에서 endpoint 를 호출합니다. 즉 actuator 입장에서의 client 는 일반적으로는 다른 서버입니다. 그러나 간혹 web 화면에서 endpoint 를 호출해야 할 수도 있습니다. 이 경우 client 는 web 이 되며, http 요청은 일반적으로 javascript 를 이용할겁니다. 웹브라우저에서는 자신의 도메인이 아닌 도메인으로 javascript 가 http 요청을 보내면 CORS 체크를 하게 되며, 서버단에 CORS 허용 설정이 없다면 http 요청이 실패하게 됩니다. 

spring 의 @RestController 를 이용한 클래스라면 @CrossOrigin 어노테이션 한줄 적어주면 끝나는데, actuator 에서도 뭔가 해결책이 있지 않을까요?

아래처럼 cors 설정을 통해 가능합니다.  CORS가 뭔지 모르겠다면 CORS 라고 구글링해서 추가 학습을 해주세요. :)

management:
  endpoints:
    web:
      cors:
        allowed-origins: http://test.com
        allowed-methods: GET

 

다음 포스팅에서는 기본 제공되는 endpoint 외에 직접 endpoint 를 만들고 등록하는 방법에 대해 알아보겠습니다.

 

이제까지 코딩없이 설정파일만 건드려서 손이 근질근질하지 않았나요? 다음 파트부터 심심하지 않을 겁니다.