들어가기
AWS EC2와 같은 클라우드 서버를 이용해서 배포를 한 경우 로그를 확인하려면 번거롭게 SSH 접속을 해서 확인해야 했다. 이를 개선하기 위해 모니터링을 도입하기로 결정했다.
Prometheus
프로메테우스는 시계열 기반의 오픈소스 모니터링 시스템으로, 애플리케이션에서 발생하는 메트릭 데이터를 수집, 저장, 분석, 알림까지 전반적으로 처리해주는 도구이다. 주로 애플리케이션의 성능, 상태, 트래픽 등을 수치로 수집해 시각화하거나 문제가 발생했을 때 경고를 보내주는 데 사용된다.
Loki
로키는 Grafana Labs에서 만든 로그 수집 및 검색 시스템으로, 프로메테우스처럼 시계열 기반의 데이터를 기반으로 로그를 저장하지만, 숫자 기반의 메트릭을 저장하는 프로메테우스와 달리 로키는 문자열 기반의 로그 데이터를 처리한다.
Grafana
그라파나는 프로메테우스, 로키 등 다양한 데이터 소스에서 수집된 정보를 시각화하고 대시보드로 구성할 수 있는 오픈소스 툴이다.
모니터링 도입
의존성 추가(build.gradle)
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation 'com.github.loki4j:loki-logback-appender:1.4.1'
환경변수 설정(application.yml)
Spring Actuator를 통해서 프로메테우스가 필요한 메트릭 정보를 제공한다.
management:
endpoints:
web:
exposure:
include: prometheus
프로메테우스 설정(prometheus.yml)
global:
scrape_interval: 15s
scrape_configs:
- job_name: prometheus
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['host.docker.internal:8080']
로그 설정(logback.xml)
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<springProperty scope="context" name="LOKI_SERVICE" source="LOKI_SERVICE" defaultValue="{서비스명}"/>
<springProperty scope="context" name="LOKI_ENV" source="LOKI_ENV" defaultValue="dev"/>
<springProperty scope="context" name="HOSTNAME" source="HOSTNAME" defaultValue="localhost"/>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) [%X{requestId:-SYSTEM}] [%thread] %cyan(%logger{35}) : %msg%n</pattern>
</encoder>
</appender>
<!-- prod : host.docker.internal -->
<springProfile name="prod">
<appender name="LOKI" class="com.github.loki4j.logback.Loki4jAppender">
<http>
<url>http://host.docker.internal:3100/loki/api/v1/push</url>
</http>
<format>
<label>
<pattern>app=${LOKI_SERVICE},host=${HOSTNAME},level=%level</pattern>
</label>
<message>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{requestId:-SYSTEM}] l=%level h=${HOSTNAME} c=%logger{20} t=%thread | %msg %ex</pattern>
</message>
</format>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="LOKI"/>
</root>
</springProfile>
<!-- dev : localhost -->
<springProfile name="dev">
<appender name="LOKI" class="com.github.loki4j.logback.Loki4jAppender">
<http>
<url>http://localhost:3100/loki/api/v1/push</url>
</http>
<format>
<label>
<pattern>app=${LOKI_SERVICE},host=${HOSTNAME},level=%level</pattern>
</label>
<message>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{requestId:-SYSTEM}] l=%level h=${HOSTNAME} c=%logger{20} t=%thread | %msg %ex</pattern>
</message>
</format>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="LOKI"/>
</root>
</springProfile>
</configuration>
프로메테우스 + 로키 + 그라파나 도커로 실행(docker-compose.yml)
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
ports:
- "9090:9090"
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- grafana-network
loki:
image: grafana/loki:latest
container_name: loki
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
volumes:
- loki_data:/loki
networks:
- grafana-network
grafana:
image: grafana/grafana:latest
container_name: grafana
environment:
- GF_SERVER_ROOT_URL={서버주소}/grafana
- GF_SERVER_SERVE_FROM_SUB_PATH=true
- GF_SECURITY_ADMIN_USER={초기 어드민 아이디}
- GF_SECURITY_ADMIN_PASSWORD={초기 어드민 비밀번호}
ports:
- "3000:3000"
networks:
- grafana-network
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
grafana-network:
driver: bridge
volumes:
loki_data:
Nginx 설정
...
location /grafana {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
...
그라파나 설정(서버주소/grafana)
docker-compose.yml에서 설정한 초기 아이디, 비밀번호로 접속
왼쪽 사이드바에서 Data sources로 이동
Prometheus 아래와 같이 입력 후 Save & test
Loki 아래와 같이 입력 후 Save & test
등록한 프로메테우스의 Build a dashboard 클릭
이미 잘 만들어진 대시보드를 사용하기 위해서 Import dashboard 클릭
19004 입력 후 Load 클릭
등록한 Prometheus 선택 후 Import 클릭
시스템 정보가 잘 나오는지 확인 후 로키 연동을 위해 Edit 클릭
Add -> Visualization 클릭
Logs 설정 후 등록한 로키를 설정하고 Code 적는 부분에 {app=서비스명} 입력한다. (이때의 서비스명은 logback.xml에 등록한 서비스 명을 입력하면 된다.)
모니터링 도입 완료