Prometheus 같은 모니터링 툴 부분 수업은 들으면서 잘 와닿지가 않았다. 그래서 크게 흥미도 못 느끼고 완전히 습득도 안된 느낌이었는데, 이번 프로젝트에서 다른 팀원분과 모니터링을 구상하면서 흐름을 좀 알게된 것 같아 글로 정리를 해보려고 한다.
일단 큰 흐름은 Spring Actuator - Prometheus - Grafana 이러하다.
우선 Spring Actuator에 대해 알아보자.
/actuator/health
): 애플리케이션의 상태를 확인 가능/actuator/metrics
): 애플리케이션의 성능 및 리소스 사용량 측정/actuator/env
): 애플리케이션의 환경 변수 및 설정 정보 제공/actuator/httptrace
): HTTP 요청 및 응답 추적/actuator/metrics
경로에서 메트릭을 제공해주지만 Prometheus 형식이 아니라 Prometheus가 수집할 수 있는 형식으로 메트릭을 출력하기 위해 따로 /actuator/prometheus
엔드포인트도 활성화해주어야 한다./actuator/prometheus
(기본값) 경로에서 메트릭 제공.⇒ Spring Boot 애플리케이션의 성능 데이터를 시각적으로 모니터링 가능
//DevOps
implementation 'org.springframework.boot:spring-boot-starter-actuator'
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'
# Actuator
management.endpoint.prometheus.access=unrestricted
management.endpoint.health.show-details=always
management.endpoints.web.exposure.include=health,info,prometheus,metrics
management.server.port=9090
management.endpoints.web.base-path=/api/management
이때 모니터링용 포트를 9090으로 따로 분리하고, 기본 경로도 /actuator
에서 /api/management
로 변경하였다.AWS 환경, 특히 EKS 같은 Kubernetes 기반 환경에서 Prometheus가 자동으로 어플리케이션의 메트릭 엔드포인트를 스크랩하도록 만들기 위해서는 ServiceMonitor라는 CRD(Custom Resource Definition)를 사용해야 한다.
CRD란 Kubernetes에서 기본적으로 제공하는 리소스 외에, 사용자가 직접 정의하는 새로운 리소스 타입을 만들 수 있도록 해주는 기능이라고 한다.
ServiceMonitor는 Prometheus Operator가 제공하는 CRD 중 하나이다. 기본적으로 Kubernetes는 ServiceMonitor라는 리소스를 모르지만, Prometheus Operator를 설치하면 ServiceMonitor라는 새로운 리소스를 Kubernetes에서 사용할 수 있도록 확장해준다.
더불어, EKS 환경에서는 Pod의 IP가 변경될 수 있기 때문에 정적인 설정이 불가하므로, Kubernetes에서 자동으로 메트릭을 수집하려면 Kubernetes의 서비스 디스커버리 기능을 사용해야 한다. 서비스 디스커버리는 클러스터 내에서 동적으로 생성되고 변경되는 서비스(ex: app-service
)를 자동으로 찾아주는 기능이다.
Prometheus는 이 서비스 디스커버리 기능을 제공하는 ServiceMonitor을 보고 어떤 서비스에서 메트릭을 수집해야 하는지 자동으로 탐색할 수 있게 된다.
⇒ 즉, ServiceMonitor는 Prometheus Operator가 제공하는 CRD(Custom Resource Definition) 중 하나로, Kubernetes의 서비스 디스커버리 기능을 활용해 Prometheus가 자동으로 타겟을 찾고 모니터링하도록 도와주는 리소스이다.
apiVersion: v1
kind: Service
metadata:
name: mv-be-app-service
labels:
app.kubernetes.io/name: mv-be
app.kubernetes.io/instance: mv-be
app.kubernetes.io/version: "1.0.0"
spec:
selector:
app.kubernetes.io/name: mv-be
app.kubernetes.io/instance: mv-be
type: ClusterIP # Service가 노출되는 방식, ClusterIP는 기본값으로 클러스터 내부에서만 접근 가능
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
- name: prometheus
protocol: TCP
port: 9090
targetPort: 9090
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: mv-be-app-servicemonitor
namespace: monitoring
labels:
app.kubernetes.io/name: mv-be
app.kubernetes.io/instance: mv-be
spec:
selector: # mentoview-be 네임스페이스에서 레이블들이 일치하는 서비스 선택
matchLabels:
app.kubernetes.io/name: mv-be
app.kubernetes.io/instance: mv-be
namespaceSelector:
matchNames:
- mentoview-be
endpoints:
- port: prometheus # 위 Service에서 정의한 'prometheus' 포트를 참조 (9090)
path: /api/management/prometheus
scheme: http
interval: 30s
mv-be-app-service
)가 9090 포트로 엔드포인트를 노출/api/management/prometheus
엔드포인트를 주기적으로(30초 간격) 호출하여 메트릭을 가져감/api/management/prometheus
로 요청을 보내 메트릭을 수집이때 어플리케이션의 Ingress에서는 8080포트만 열어놓았기 때문에 외부에서는 9090 포트로 접근이 불가하다. 따라서, Spring Security에서 따로 Actuator 경로에 보안 조치를 취해주지 않아도 클러스터 외부에서는 접근을 할 수 없다. 이게 포트 분리의 또다른 이점~
이렇게 설정을 해주고, 그라파나에서 어플리케이션을 모니터링하기에 적합한 대시보드를 import해주면 된다. 이상으로 글을 마치겠다.