중앙 집중 로깅용 Grafana Loki 배포
Entry, Enterprise, Enterprise Advanced 플랜에서 사용할 수 있습니다(Professional에서는 제공되지 않습니다).
이 가이드는 기존 Prometheus·Grafana 성능 모니터링 배포 환경에 Grafana Loki를 추가해 중앙 집중 로그 집계를 구성하는 방법을 다룹니다. Prometheus가 지표(CPU, 요청 지연 시간, 고루틴 수)를 수집하는 반면 Loki는 로그를 수집하므로, 운영 팀이 하나의 Grafana 인터페이스에서 모든 서버의 Mattermost 애플리케이션 로그를 검색하고 필터링하며 연관 분석할 수 있게 됩니다.
Loki를 도입하면 다음을 할 수 있습니다.
- Grafana에서 모든 애플리케이션 서버의 Mattermost 로그를 검색합니다.
- 로그 수준, HTTP 상태 코드, 자유 텍스트 검색으로 필터링합니다.
- 반복적으로 발생하는 주요 오류와 경고를 식별합니다.
- 동일한 타임라인에서 로그 이벤트와 Prometheus 지표 급증을 연관 분석합니다.
- 선택적으로 PostgreSQL 데이터베이스 로그를 애플리케이션 로그와 함께 수집합니다.
이 가이드는 성능 모니터링 가이드에 따라 Prometheus와 Grafana를 이미 배포했다고 가정합니다. Loki와 OpenTelemetry Collector가 그 기존 인프라에 추가됩니다.
아키텍처 개요
이 배포는 모니터링 스택에 두 가지 구성 요소를 추가합니다.
- Loki — 로그 집계 엔진으로, 기존 Grafana/Prometheus 모니터링 서버에 설치합니다.
- OpenTelemetry Collector — 로그를 전송하기 위해 각 Mattermost 애플리케이션 서버에 설치하는 범용 업계 표준 에이전트입니다.
┌──────────────────────┐ ┌──────────────────────┐
│ Mattermost App 01 │ │ Mattermost App 02 │
│ │ │ │
│ /opt/mattermost/ │ │ /opt/mattermost/ │
│ logs/mattermost.log│ │ logs/mattermost.log│
│ │ │ │ │ │
│ [ OTel Col ] │ │ [ OTel Col ] │
└─────────┬────────────┘ └─────────┬────────────┘
│ push (:3100/otlp) │
▼ ▼
┌─────────────────────────────────────────────────────┐
│ Monitoring Server │
│ │
│ [ Prometheus :9090 ] [ Loki :3100 ] │
│ │ │ │
│ └──────┬──────────────┘ │
│ ▼ │
│ [ Grafana :3000 ] │
│ Metrics + Logs │
└─────────────────────────────────────────────────────┘
Optional: Add the OpenTelemetry Collector on your PostgreSQL server to also
ship database logs to Loki.
사전 요구 사항
시작하기 전에 다음을 확인하세요.
- 성능 모니터링 가이드에 따라 Prometheus와 Grafana가 배포되어 Mattermost 지표를 수집하고 있어야 합니다.
- 모니터링 서버와 각 Mattermost 애플리케이션 서버에 sudo 권한이 있는 SSH 접근이 가능해야 합니다.
- Mattermost가
/opt/mattermost(기본 위치)에 설치되어 있어야 합니다. 설치 경로가 다르다면/opt/mattermost가 나오는 모든 위치를 사용 중인 경로로 바꾸세요. - 네트워크 연결: 각 Mattermost 서버가 TCP 3100 포트(Loki의 HTTP API)로 모니터링 서버에 접근할 수 있어야 합니다.
1단계: Mattermost JSON 로깅 확인
Loki 쿼리가 동작하려면 Mattermost가 JSON 형식의 파일 로그를 기록하고 있어야 합니다. 이는 모든 플랜에서 기본값이며, 각 애플리케이션 서버에서 다음과 같이 확인하세요.
tail -1 /opt/mattermost/logs/mattermost.log
JSON 형식의 줄은 다음과 같은 모습입니다.
{"timestamp":"2025-01-15T14:32:01.123Z","level":"info","msg":"Server is listening on [::]:8065","caller":"app/server.go:482"}
대신 일반 텍스트 출력이 보인다면 System Console > Environment > Logging으로 이동해 Output file logs as JSON을 true로 설정한 뒤 Mattermost를 재시작하세요.
sudo systemctl restart mattermost
2단계: 모니터링 서버에 Loki 설치
Grafana와 Prometheus가 실행 중인 동일한 서버에 Loki를 설치합니다. 이 섹션의 모든 명령은 모니터링 서버에서 실행합니다.
아래 명령은 Loki 버전 3.4.2를 사용합니다. 최신 버전은 Loki 릴리스 페이지에서 확인하고 필요에 따라 버전 번호를 바꾸세요.
Loki 사용자와 디렉터리를 만들고 바이너리를 내려받습니다.
# Create a dedicated system user sudo useradd --system --no-create-home --shell /bin/false loki # Create directories sudo mkdir -p /opt/loki/data /opt/loki/bin # Download and extract Loki sudo apt-get install -y unzip cd /tmp curl -LO https://github.com/grafana/loki/releases/download/v3.4.2/loki-linux-amd64.zip unzip loki-linux-amd64.zip sudo mv loki-linux-amd64 /opt/loki/bin/loki sudo chmod +x /opt/loki/bin/loki프로덕션 구성 파일을 내려받아 설치합니다.
sudo cp loki-config.yaml /opt/loki/loki-config.yaml팁로그 보존 기간은 기본적으로 14일로 설정되어 있습니다. 이를 변경하려면
/opt/loki/loki-config.yaml을 편집해limits_config아래의retention_period값을 수정하세요. Loki는 이 값을 시간 단위로 요구합니다. 자주 쓰이는 값은 다음과 같습니다.336h= 14일(기본값)720h= 30일2160h= 90일8760h= 365일
보존 기간이 길수록 디스크 사용량이 늘어납니다. 대략적인 기준으로, 적당히 활발한 Mattermost 배포 환경에서는 하루 1~3GB를 예상하세요(로그 양에 따라 달라집니다). 첫 주가 지난 뒤
/opt/loki/data/를 모니터링해 필요한 저장 용량을 산정하세요. 보존 정책이 적용되려면compactor.retention_enabled설정이true로 유지되어야 합니다.소유권을 설정합니다.
sudo chown -R loki:loki /opt/lokisystemd 서비스 파일을 만듭니다.
sudo tee /etc/systemd/system/loki.service > /dev/null <<'EOF' [Unit] Description=Grafana Loki Log Aggregation Documentation=https://grafana.com/docs/loki/latest/ After=network-online.target Wants=network-online.target [Service] Type=simple User=loki Group=loki ExecStart=/opt/loki/bin/loki -config.file=/opt/loki/loki-config.yaml Restart=on-failure RestartSec=5 LimitNOFILE=65536 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOFLoki를 시작합니다.
sudo systemctl daemon-reload sudo systemctl enable --now lokiLoki가 실행 중인지 확인합니다.
sudo systemctl status loki curl -s http://localhost:3100/ready/ready엔드포인트는ready를 반환해야 합니다. Loki는 시작 후 준비 상태를 보고하기까지 15~20초가 걸릴 수 있으며, 이 워밍업 지연은 정상입니다.
3단계: 각 Mattermost 서버에 OpenTelemetry Collector 설치
OpenTelemetry(OTel) Collector는 각 Mattermost 애플리케이션 서버에서 실행되며 로그를 Loki로 전송합니다. 모든 Mattermost 애플리케이션 서버에서 다음 단계를 반복하세요.
<LOKI_HOST>는 모니터링 서버의 IP 주소 또는 호스트명으로, <HOSTNAME>은 해당 서버의 호스트명(예: mm-app-01)으로, <SERVICE_NAME>은 서비스 유형(예: mattermost 또는 postgres)으로 바꾸세요.
OTel Collector Contrib 배포판을 설치합니다.
# Add OTel Collector repository and install # Commands below are for Ubuntu/Debian wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.145.0/otelcol-contrib_0.145.0_linux_amd64.deb sudo dpkg -i otelcol-contrib_0.145.0_linux_amd64.deb참고설치 과정에서
otelcol-contrib라는 이름의 시스템 사용자와 그룹이 자동으로 생성됩니다.OpenTelemetry Collector 구성 파일을 내려받아 편집합니다.
sudo cp otel-collector-config-mattermost.yaml /etc/otelcol-contrib/config.yaml/etc/otelcol-contrib/config.yaml을 편집해 자리 표시자를 바꾸세요.<LOKI_HOST>를 모니터링 서버의 주소로 바꿉니다.<HOSTNAME>을 해당 서버의 호스트명으로 바꿉니다.<SERVICE_NAME>을 서비스 유형(예:mattermost)으로 바꿉니다.
sudo vi /etc/otelcol-contrib/config.yamlCollector에 Mattermost 로그 디렉터리 읽기 권한을 부여합니다.
# Grant the collector access to read Mattermost logs. # Substitute 'mattermost' for the group that owns your log file. sudo usermod -aG mattermost otelcol-contrib # Ensure logs are group-readable sudo chmod 640 /opt/mattermost/logs/mattermost.log sudo chmod g+rx /opt/mattermost/logs서비스를 재시작합니다.
sudo systemctl restart otelcol-contrib sudo systemctl enable otelcol-contribCollector가 실행 중이며 로그를 전송하고 있는지 확인합니다.
sudo systemctl status otelcol-contrib sudo journalctl -u otelcol-contrib -f
4단계: Grafana에 Loki를 데이터 소스로 추가
- Grafana에 로그인합니다(기본값:
http://<monitoring-server>:3000). - Administration > Data Sources > Add data source로 이동합니다.
- 목록에서 Loki를 선택합니다.
- 연결을 구성합니다.
- Name:
Loki - URL:
http://localhost:3100(Loki가 Grafana와 같은 서버에 있으므로)
- Name:
- Save & test를 선택합니다. Grafana가 데이터 소스가 정상 동작함을 확인해 줍니다.
5단계: Mattermost Loki 대시보드 가져오기
로그 모니터링에는 사전 제작된 Grafana 대시보드 사용을 권장합니다. 이 대시보드는 기본 예시로 제공됩니다.
이 대시보드는 유용한 출발점이 되지만, Grafana의 Explore 탭을 사용하면 즉석에서 맞춤 LogQL 쿼리를 작성해 완전한 쿼리 유연성을 확보할 수 있습니다.
이 대시보드는 다음을 제공합니다.
- Log Volume by Level — 심각도별 로그 발생률을 보여 주는 누적 막대 차트.
- Error / Warning / Total counters — 선택한 기간에 대한 통계 패널.
- HTTP 4xx/5xx count — 애플리케이션 수준 HTTP 오류를 빠르게 파악.
- Error Rate Over Time — 오류 급증을 포착하기 위한 인스턴스별 시계열.
- Top Error Messages — 가장 빈번한 오류의 순위를 보여 주는 표.
- Log Browser — 로그 수준과 자유 텍스트 변수로 검색·필터링할 수 있는 로그 패널.
대시보드를 가져오려면 다음과 같이 하세요.
- Grafana에서 Dashboards > New > Import로 이동합니다.
- Upload JSON file을 선택하고 내려받은
mattermost-loki-logs.json파일을 선택합니다. - 가져오기 화면에서 드롭다운으로 Loki 데이터 소스를 선택합니다.
- Import를 선택합니다.
6단계: 유용한 LogQL 쿼리
다음 쿼리는 Grafana Explore에서 직접 실행하거나(Loki 데이터 소스 선택), 추가 대시보드 패널을 구성하는 데 사용할 수 있습니다.
모든 Mattermost 로그 검색:
{service_name="mattermost"}
로그 수준으로 필터링:
{service_name="mattermost"} | json | detected_level="error"
모든 HTTP 4xx 응답 검색:
{service_name="mattermost"} | json | status_code >= 400
모든 HTTP 5xx 응답 검색:
{service_name="mattermost"} | json | status_code >= 500
5분 구간 기준 상위 5개 오류 메시지:
topk(5, sum(count_over_time({service_name="mattermost"} | json | detected_level="error" [5m])) by (msg))
5분 구간 기준 메시지별 오류 수 집계:
sum(count_over_time({service_name="mattermost"} | json | detected_level="error" [5m])) by (msg)
자유 텍스트 검색(예: 플러그인 오류):
{service_name="mattermost"} |~ "plugin"
인증 관련 로그 줄:
{service_name="mattermost"} |~ "(?i)(auth|login|token|session)"
특정 서버 인스턴스의 로그:
{service_name="mattermost", service_instance_id="mm-app-01"}
LogQL 전체 레퍼런스는 Grafana Loki LogQL 문서를 참고하세요.
선택 사항: PostgreSQL 로그 수집 추가
PostgreSQL 데이터베이스가 전용 서버(RDS가 아닌)에서 실행 중이라면 그 로그도 Loki로 전송할 수 있습니다. 느린 쿼리나 데이터베이스 오류를 Mattermost 애플리케이션 이벤트와 연관 분석할 때 유용합니다.
PostgreSQL 로그 수집을 위한 별도의 구성 파일이 제공됩니다. 3단계와 동일한 절차로 PostgreSQL 서버에 OpenTelemetry Collector를 설치한 뒤, Mattermost용 구성 파일 대신 이 구성 파일을 사용하세요.
PostgreSQL 구성은 일반적인 Ubuntu/Debian JSON 로그 경로(/var/log/postgresql/*.json)를 처리합니다. 3단계에서 설명한 것과 동일한 <LOKI_HOST>, <HOSTNAME>, <SERVICE_NAME> 자리 표시자를 바꾸세요.
실행되고 나면 PostgreSQL 로그가 {service_name="postgres"} 레이블 아래 Grafana에 나타납니다.
{service_name="postgres"} | json | detected_level="error"
검증 및 문제 해결
엔드투엔드 검증 체크리스트:
Loki가 정상 상태입니다.
curl -s http://<monitoring-server>:3100/ready # Expected: "ready"OpenTelemetry Collector가 로그를 전송하고 있습니다(각 Mattermost 서버에서 실행).
sudo journalctl -u otelcol-contrib -n 100 # Look for export successful messages or lack of errorsGrafana에서 로그가 보입니다. Explore로 이동해 Loki 데이터 소스를 선택하고
{service_name="mattermost"}를 실행하세요. 최근 로그 줄이 보여야 합니다.대시보드가 로드됩니다. Mattermost Log Aggregation 대시보드를 열어 패널에 데이터가 채워졌는지 확인하세요. (참고: 대시보드 쿼리가
service_name과service_instance_id를 사용하도록 업데이트해야 할 수 있습니다.)
흔한 문제:
| 증상 | 해결 방법 |
|---|---|
| OTel Col 대상에 오류가 표시됨 | 구성 파일의 파일 경로가 실제 로그 파일 위치와 일치하는지 확인하세요. 파일 권한도 확인하세요(otelcol-contrib 사용자가 파일을 읽을 수 있어야 합니다). |
3100 포트에서 connection refused 발생 |
Loki가 실행 중인지 확인하세요(systemctl status loki). 방화벽 규칙을 확인하세요. sudo iptables -L -n | grep 3100을 실행하거나, AWS 보안 그룹이 Mattermost 서버로부터의 TCP 3100을 허용하는지 확인하세요. |
| 로그는 Loki에 나타나지만 필드가 파싱되지 않음 | Mattermost가 JSON 형식 로그를 기록하고 있는지 확인하세요(1단계 참고). json_parser 연산자(Postgres용)나 OTel 프로세서가 올바르게 구성되었는지 확인하세요. |
/ready가 오류를 반환함 |
Loki 로그를 확인하세요. sudo journalctl -u loki -f. 흔한 원인은 /opt/loki/data/의 권한 문제입니다. loki 사용자가 해당 디렉터리를 소유하고 있는지 확인하세요. |
| 오래된 로그가 삭제되지 않음 | Loki 구성에 compactor.retention_enabled: true와 limits_config.retention_period가 모두 설정되어 있는지 확인하세요. 컴팩터는 compaction_interval(기본값 10분)마다 실행되며, 실제로 데이터를 제거하기 전에 retention_delete_delay(기본값 2시간)를 적용합니다. |
| 모니터링 서버의 디스크 사용량이 높음 | 구성의 보존 기간을 검토하세요. 기간을 줄이거나 디스크를 추가하는 것을 고려하세요. 현재 사용량은 du -sh /opt/loki/data/로 확인하세요. |