Loki + Promtail + Grafana로 로그 수집·검색·알림: 가벼운 ELK 대안 구축(단일 서버 → 다중 서버 확장)
운영 환경의 장애 원인 파악은 결국 로그에서 시작합니다. 하지만 전통 ELK(Elasticsearch+Logstash+Kibana)는 리소스 요구량과 관리 복잡도가 높습니다. Loki + Promtail + Grafana 조합은 인덱스 없는 설계로 저비용·간편 운영·빠른 도입이 장점입니다. 이 글은 Ubuntu 24.04 기준으로 단일 서버에 구축한 뒤, 다중 서버로 확장하는 방법까지 설정 스니펫과 운영 체크리스트로 정리합니다.
1) 아키텍처 한 장 요약
- Promtail: 로컬 파일(예:
/var/log/*.log) Tail → 라벨링 → Loki로 전송 - Loki: 로그 저장/쿼리. 인덱스 대신 라벨 메타데이터로 가볍게 관리
- Grafana: 시각화·검색(LogQL)·알림 룰
[App/OS Logs] --tail--> [Promtail] --push--> [Loki] <--query--> [Grafana]
핵심: “무분별한 라벨 남용 금지”. 필요한 라벨(호스트, 서비스명, 환경 등)만 최소화해 저장 효율을 유지합니다.
2) 설치(단일 서버 시작)
2-1) 패키지/사용자
sudo useradd --system --no-create-home --shell /usr/sbin/nologin loki
sudo useradd --system --no-create-home --shell /usr/sbin/nologin promtail
2-2) 바이너리 배치
공식 릴리스를 받아 /usr/local/bin에 배치(버전은 환경에 맞게 교체).
sudo mv loki promtail /usr/local/bin/
sudo chmod +x /usr/local/bin/loki /usr/local/bin/promtail
3) Loki 설정(로컬 볼륨 저장, 단일 인스턴스)
# /etc/loki/config.yml (최소 예시)
auth_enabled: false
server:
http_listen_port: 3100
common:
instance_addr: 127.0.0.1
path_prefix: /var/lib/loki
storage:
filesystem:
chunks_directory: /var/lib/loki/chunks
rules_directory: /var/lib/loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2025-01-01
store: boltdb-shipper
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
ingestion_rate_mb: 8
ingestion_burst_size_mb: 16
max_streams_per_user: 10000
chunk_store_config:
max_look_back_period: 720h
table_manager:
retention_deletes_enabled: true
retention_period: 720h # 30일 보관 예시
3-1) 디렉터리/권한
sudo mkdir -p /var/lib/loki/{chunks,rules}
sudo chown -R loki:loki /var/lib/loki /etc/loki
3-2) systemd 서비스
# /etc/systemd/system/loki.service
[Unit]
Description=Loki Log Aggregation
After=network-online.target
Wants=network-online.target
[Service]
User=loki
ExecStart=/usr/local/bin/loki --config.file=/etc/loki/config.yml
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now loki
systemctl status loki --no-pager
4) Promtail 설정(파일 경로 지정, 라벨 최소화)
# /etc/promtail/config.yml
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /var/lib/promtail/positions.yaml
clients:
- url: http://127.0.0.1:3100/loki/api/v1/push
scrape_configs:
- job_name: syslog
static_configs:
- targets: [localhost]
labels:
job: syslog
host: ${HOSTNAME}
__path__: /var/log/syslog
- job_name: nginx
static_configs:
- targets: [localhost]
labels:
job: nginx
host: ${HOSTNAME}
__path__: /var/log/nginx/*.log
- job_name: app
static_configs:
- targets: [localhost]
labels:
job: myapp
env: prod
host: ${HOSTNAME}
__path__: /var/log/myapp/*.log
4-1) 디렉터리/서비스
sudo mkdir -p /var/lib/promtail
sudo chown -R promtail:promtail /var/lib/promtail /etc/promtail
# /etc/systemd/system/promtail.service
[Unit]
Description=Promtail Log Collector
After=network-online.target
Wants=network-online.target
[Service]
User=promtail
ExecStart=/usr/local/bin/promtail --config.file=/etc/promtail/config.yml
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now promtail
systemctl status promtail --no-pager
5) Grafana 연결(탐색·대시보드·알림)
- Grafana 설치 후 로그인 → Connections → Data sources → Add data source
- Loki 선택, URL에
http://127.0.0.1:3100입력 → Save & Test - Explore에서 LogQL로 즉시 검색
5-1) LogQL 기초
{job="nginx"} |= "GET" |~ "\\.css"
{job="myapp", env="prod"} | logfmt | level="ERROR"
{host="web-01"} | json | line_status >= 500
팁: 애플리케이션 로그를 JSON/Logfmt로 찍으면 파싱 후 필터링이 쉬워집니다.
6) 알림(로그 패턴 기반 경보)
Grafana 10+의 Alerting을 사용해 특정 LogQL 카운트를 지표로 전환 후 임계치 알림을 보낼 수 있습니다.
- Dashboards → Alerting → Alert rules → New
- 쿼리 예시(5분간 에러 20회 이상):
# Loki → Metrics 탭에서 count_over_time 사용
sum by (job) (count_over_time({job="myapp"} |= "ERROR" [5m])) >= 20
Slack/Webhook/Email 연락처를 연결하면 실시간 통지가 가능합니다.
7) 다중 서버 확장(Agent만 추가)
- 각 서버에 Promtail만 설치하고,
clients.url을 중앙 Loki로 지정 - 라벨에
host,env,job정도만 유지(카디널리티 폭증 방지)
# 각 애플리케이션 서버의 /etc/promtail/config.yml (발췌)
clients:
- url: http://loki.example.internal:3100/loki/api/v1/push
스토리지: 단일 서버는 filesystem으로 시작하고, 규모가 커지면 S3 호환 오브젝트 스토리지(미니오 등)로 이전을 검토합니다.
8) 운영 체크리스트
- 라벨 가이드: host, job, env, (선택)app. 동적 값(사용자ID 등)은 절대 라벨로 넣지 않기.
- 보관정책: 7~30일 사이로 시작 → 비용/검색 패턴에 따라 조정.
- 보안: Loki HTTP 엔드포인트는 내부망 제한(방화벽/UFW). Reverse proxy로 인증 헤더 부여 가능.
- 성능: Promtail의
positions.yaml이 손상되면 재수집 가능성. 백업 또는 변동 최소화. - 백업: 운영 정책에 따라
/var/lib/loki스냅샷(또는 오브젝트 스토리지 자체 내구성 의존).
9) 문제 해결 빠른 분기
- 로그가 안 들어옴: Promtail 로그에서
client에러 확인 → Loki URL/포트/방화벽 재확인. - 검색이 느림: 기간/라벨 범위를 좁히고, 과도한 라벨 제거. 보관기간/청크 파라미터 점검.
- 용량 급증: 라벨 폭발(카디널리티) 여부 점검,
env·job외 가변 라벨 삭제. - 중복 수집: positions 파일 경로 고정, 동일 로그 파일의 로테이션 정책 확인(logrotate 설정).
10) 마무리
Loki 스택은 “적당히 가볍고 충분히 강력한” 로그 플랫폼입니다. 단일 서버에서 빠르게 시작해, Promtail만 늘려 다중 서버로 매끄럽게 확장할 수 있습니다. 지금 운영 중인 서비스의 에러 키워드 2~3개부터 알림을 걸고, 팀 합의된 라벨 가이드만 지켜도 장애 대응 속도는 눈에 띄게 개선됩니다.
'Database & Storage' 카테고리의 다른 글
| 개발자가 자주 잊어버리는 SQL 기본 명령어 7가지 (JOIN, GROUP BY 실습) (0) | 2025.11.10 |
|---|---|
| SQL 쿼리 정렬과 주석 달기 실전 가이드 — 초보 개발자도 읽히는 쿼리 쓰는 법 (1) | 2025.11.07 |
| 다운타임 없는 DB 마이그레이션 완전 가이드: PostgreSQL & MySQL(Online DDL, gh-ost/pt-osc, Expand→Migrate→Contract) (0) | 2025.10.28 |
| Testcontainers로 DB 통합테스트: Docker 이미지까지 자동 띄우는 실전 가이드 (0) | 2025.10.10 |
| Micrometer·Prometheus·Grafana로 스프링 부트 서비스 모니터링 대시보드 만들기 (0) | 2025.10.10 |