Grafana Labs에서 만든 도구입니다.
이미 Grafana를 쓰고 있는 사용자에게 권장합니다.
Loki
로그 내용 전체를 인덱싱하지 않고 레이블(메타데이터)만 인덱싱합니다. 덕분에 저장 공간을 훨씬 적게 차지합니다.
주요 기능
- 로그 내용이 아닌 레이블만 인덱싱하여 비용 효율적입니다.
- Prometheus와 유사한 쿼리 언어(LogQL)를 사용합니다.
- S3, GCS 등 오브젝트 스토리지를 지원합니다.
- 멀티테넌시를 지원합니다.
Prometheus와 유사한 언어를 사용하기 때문에 PromQL을 이미 사용하거나 알고 있다면,
더 빠르게 학습하여 도입할 수 있습니다.
Promtail
Promtail은 각 서버에서 로그 파일을 읽어서 Loki로 보내는 에이전트입니다.
주요 기능
- 로컬 로그 파일 수집 및 전송을 담당합니다.
- 로그에 레이블 자동 부여합니다.
- Kubernetes Pod 로그를 자동으로 수집할 수 있습니다.
- 로그 파싱 및 필터링이 가능합니다.
- 여러 Loki 인스턴스로 전송 가능합니다.
두 기능은 Prometheus와 Grafana를 사용 중이라면 훌륭한 선택지이며, Elasticsearch/ELK 스택보다도, Fluentd나 FluentBit보다도 적은 리소스로 사용이 가능합니다.
이 조합의 가장 큰 장점은, “가벼움” 입니다.
글을 쓰다 느낀건데… 요즘은 AI가 어지간한 환경파일은 프롬프트만 잘 설정하면 만져주기 때문에,
사실 실제로 어떻게 구현하는지 다른 사람의 것을 참고하기보다는 내 환경에 맞춰 AI와 올리는게 더 효율적이라는 생각을 했습니다.
일단 대충 올려놓긴 했습니다만, AI와 함께 본인의 시스템에 어울리는 환경설정을 통해 이용하시는걸 권장드립니다.
구현부
먼저 수집할 로그의 형태를 조정합니다.
사용하는 Application에 따라, 로그 사양은 다르기 때문에 Spring Boot로 설명드리면 logback 파일 설정정도의 의미입니다.
logging: file: path: logs name: logs/spring.log level: root: INFO spring .server: INFO org.springframework: WARN org.hibernate: WARN
다음은 Loki와 Promtail을 실행시켜야 합니다. 그전에 Loki와 Promtail에 들어갈 실행 파일을 미리 만들면 좋습니다. 나중에 만들어서 재시작해도 되지만, 처음부터 대부분의 기능은 완성된 상태가 이롭습니다.
참고로 loki의 실행 파일은 ai에게 물어보는 것이 상황과 조건에 따라 달라지기 때문에, 더 이로울 수 있어서 생략하겠습니다.
이제 Promtail로 Spring boot의 로그를 수집해야 합니다.
#promtail-config.yaml
server:
http_listen_port: 9080
grpc_listen_port: 0
log_level: info
positions:
filename: /var/lib/promtail/positions/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
timeout: 10s
backoff_config:
min_period: 500ms
max_period: 5m
max_retries: 10
scrape_configs:
# Spring Boot Event Server 로그
- job_name: docker-spring-server
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
filters:
- name: name
values: ["spring-server"]
relabel_configs:
- source_labels: ['__meta_docker_container_name']
regex: '/(.*)'
target_label: 'container'
- source_labels: ['__meta_docker_container_log_stream']
target_label: 'stream'
- replacement: 'spring-server'
target_label: 'job'
- replacement: 'prod'
target_label: 'env'
- replacement: 'event'
target_label: 'server'
pipeline_stages:
# JSON 로그 파싱
- json:
expressions:
timestamp: timestamp
level: level
thread: thread
logger: logger_name
message: message
trace_id: traceId
span_id: spanId
# 타임스탬프 설정
- timestamp:
source: timestamp
format: RFC3339
# 로그 레벨을 레이블로 추가
- labels:
level:
thread:
# WARN 감지
- match:
selector: '{job="spring-server", level="WARN"}'
stages:
- labels:
alert_type: "warning"
# ERROR 감지
- match:
selector: '{job="spring-server", level="ERROR"}'
stages:
- labels:
alert_type: "error"컨테이너 네임과 promtail이 인식하는 이름을 일치시켜면 대체적으로 로그를 불러옵니다.
만약 로그를 불러오지 않는다면, 컨테이너 이름이든 어딘가 이상한 값을 쓰고 있을 확률이 높습니다.
( 예 : spring-server, 어딘가의 이상한 값 : spring-server-v1 )
참고로 promtail은 docker socket에서 바로 연결을 가져오기 때문에 /lib… 으로 시작하는 일반적으로 도커 파일을 읽을 수 있는 로그 저장공간이 아닙니다.
이제 Docker Compose 파일을 생성합니다
services:
grafana:
image: grafana/grafana:latest
env_file:
- .env
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=password
- GF_USERS_ALLOW_SIGN_UP=false
- GF_SERVER_SERVE_FROM_SUB_PATH=true
- GF_PANELS_DISABLE_SANITIZE_HTML=true
- GF_SECURITY_ALLOW_EMBEDDING=true
- GF_AUTH_ANONYMOUS_ENABLED=false
volumes:
- ./volumes/grafana:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
- ./grafana/dashboards:/etc/grafana/dashboards
restart: unless-stopped
networks:
- spring-network
# Loki Init
loki-init:
image: busybox
container_name: loki-init
user: root
volumes:
- loki-data:/loki
command: |
sh -c "
mkdir -p /loki/chunks /loki/rules &&
chown -R 10001:10001 /loki &&
chmod -R 755 /loki
"
networks:
- spring-network
# Loki Log Aggregation
loki:
image: grafana/loki:2.9.3
container_name: loki
ports:
- "3100:3100"
volumes:
# 파일을 직접 마운트 (디렉토리가 아닌 파일로)
- ./loki/loki-config.yaml:/etc/loki/local-config.yaml:ro
- loki-data:/loki
# 올바른 설정 파일 경로 지정
command: -config.file=/etc/loki/local-config.yaml
restart: unless-stopped
depends_on:
loki-init:
condition: service_completed_successfully
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3100/ready || exit 1"]
interval: 10s
timeout: 5s
retries: 5
networks:
- spring-network
# Promtail Log Collector
promtail:
image: grafana/promtail:2.9.3
container_name: promtail
user: root
volumes:
# 파일을 직접 마운트
- ./promtail/promtail-config.yaml:/etc/promtail/config.yaml:ro
- promtail-positions:/var/lib/promtail/positions
# Docker 컨테이너 로그 수집
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
command: -config.file=/etc/promtail/config.yaml
restart: unless-stopped
depends_on:
loki:
condition: service_healthy
networks:
- spring-network
volumes:
# Loki 데이터 볼륨
loki-data:
driver: local
driver_opts:
type: none
o: bind
device: ./volumes/loki
# Promtail positions 볼륨
promtail-positions:
driver: local
driver_opts:
type: none
o: bind
device: ./volumes/promtail
networks:
spring-network:
external: true
name: spring-network저는 온프레미스 환경에서 개발하기 때문에, 인메모리 영속성 저장공간이 필요하여 volume 설정을 해주었습니다. 상황에 따라 다르기 때문에 참고해주시면 감사하겠습니다.
Docker Compose로 Loki와 Promtail이 올라간 걸 확인하면
docker compose logs
입력 후, 잘 실행됐는지 확인해주시기 바랍니다.
그 다음입니다.
Grafana에 반영할 datasource를 생성합니다.
apiVersion: 1
datasources:
# Loki DataSource
- name: Loki
type: loki
access: proxy
url: http://loki:3100
isDefault: false
editable: true
jsonData:
pdcInjected: falseLoki와 Promtail도 실행됐고, Grafana도 실행된 상태라면 해당 datasource반영을 위해 Grafana를 재시작 해줍니다.
docker compose down restart grafana
재시작된 Grafana의 왼쪽 UI 상 Datasource를 검색해보거나
http://localhost:3000/api/datasources # 비슷한 주소였던 걸로 추정Datasource 리스트를 불러올 수 있는 기능을 호출하던가 하는 방식으로 데이터 소스를 검색해보면 아마 있을 겁니다.
이제 Dashboard 를 만들고,

이렇게 입력하면 ..
.png%253FspaceId%253Df02ca0c9-9279-4cd3-bf61-49a4adc12473%3Ftable%3Dblock%26id%3D2a75cb6e-6e79-807a-8986-df39d6b5bcae%26cache%3Dv2&w=1920&q=75)
대충 이렇게 서버 로그를 볼 수 있게 됩니다.
구현부의 핵심은, Spring Boot에 Logback 설정해놓고 Promtail로 로그 수집하고가 끝이긴 합니다.
다만 Container의 이름 설정은 조금 신경써서 확인하시는 것이 좋습니다. 매핑된 값의 유효성을 검사하는 스크립트를 누군가 짜준다면 좋겠지만, 대부분의 회사에서는 사람의 눈을 통해 확인하기 때문에 좀 더 꼼꼼히 살피는걸 추천합니다.
결론적으로,
.png%253FspaceId%253Df02ca0c9-9279-4cd3-bf61-49a4adc12473%3Ftable%3Dblock%26id%3D2a75cb6e-6e79-8056-9d4e-cd3aaa0e0181%26cache%3Dv2&w=1920&q=75)
Application으로부터 Promtail로 모은 로그를 Loki에 저장하고 Grafana로 시각화하는 아주 간단하지만 강력한 솔루션입니다.
이전 회사에서 Kubernetes와 ArgoCD를 사용할 때, 새로운 서버의 로그를 확인하려면 매번 새 창을 열어야 했습니다. 서버가 늘어날수록 브라우저 탭도 함께 늘어났고, 로그를 확인하는 것 자체가 소모적인 작업이 되었습니다.
당시에는 Fluentd를 도입해 S3에 로그를 저장하는 등 복잡한 파이프라인을 구축했지만, S3에도 저장하고.. 뭐 어쩐다고 썻었는데, 지금 생각해보니 그냥 당시의 제가 해결하고 싶었던 고통은 "여러 창을 오가며 로그를 확인하는 번거로움" 이었습니다.
그런 의미에서 복잡한 설정없이 간단하게 도입할 수 있는 Promtail + Loki와 함께한다면… 적은 인원으로도 많은 리소스를 관리하는데 큰 도움이 될 것 같다는 생각이 듭니다.
Fluentd + S3 같은 복잡한 솔루션이 "해야 하는 일"이었다면, 실제로 "해야만 하는 일"은 로그를 쉽게 확인하는 것뿐이었습니다.
딸깍 딸깍 몇 번으로, 많은 서버의 로그를 한곳에서 중앙 집중형으로 볼 수 있게 됐습니다. 도입을 망설이지 마시고, 창을 여러개 켜놓고 서버 로그를 확인하고 있다면 망설이지 말고 도입하세요!
Share article