Loki와 Promtail을 활용한 백엔드 로그 수집

소개

Grafana Labs의 오픈소스 로깅 시스템인 Loki와 log tailing agent인 Promtail을 활용하여 백엔드 로그를 수집하는 방법을 다룹니다.

선택 이유

로그 수집 시스템으로 ELK Stack, New Relic 등 여러 선택지가 있습니다. 하지만 각각 다음과 같은 단점이 있습니다.

  • ELK Stack: 기본 리소스 사용량이 많습니다.
  • New Relic: On-premise 옵션이 없고, 일정 사용량 이후 비용이 발생합니다.

Grafana와 Prometheus 조합으로 모니터링 환경을 구축한 경험이 있어, 가볍고 기존 환경과 잘 어울리는 Grafana + Loki 조합을 선택합니다.

Loki와 Promtail 소개

Loki는 Grafana Labs에서 출시한 로깅 시스템입니다. Prometheus와 달리 메트릭 수집보다 로그 수집에 특화되어 있어 가볍고 로깅 관련 쿼리가 빠릅니다.

Promtail은 메트릭 푸시 방식인 Loki에게 로그를 전송하기 위해 만들어진 tailing agent입니다.

아키텍처

시스템 아키텍처

현재 노드 3개를 Docker Swarm으로 묶어서 사용합니다. 어떤 노드에 어떤 컨테이너가 배치되어도 문제없이 동작할 수 있도록 설계합니다.

네트워크 구성

  • Grafana: Loki와 같은 Stack에서 같은 네트워크로 연결되어 있습니다.
  • 외부 접근: host 네트워크로 동작하는 Cloudflare Tunnel이 grafana.example.comlocalhost:{Grafana port}를 가리킵니다.
  • 로그 전송: Web Server의 Promtail이 로그를 수집하여 host.docker.internal:{Loki port}로 전송합니다.

host.docker.internal은 컨테이너를 실행하는 노드를 가리킵니다. Grafana, Loki 스택이 ingress 네트워크로 모든 노드에 포트가 바인딩되어 있으므로, 컨테이너 위치가 변해도 정상 동작합니다.

설정 파일

Promtail 설정

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://host.docker.internal:3100/loki/api/v1/push

scrape_configs:
- job_name: system
  static_configs:
  - targets:
      - localhost
    labels:
      job: varlogs
      __path__: /mnt/config/logs/*log

Loki 설정

auth_enabled: false

server:
  http_listen_port: 3100
  grpc_listen_port: 9096

frontend:
  address: 127.0.0.1

common:
  instance_interface_names:
    - "lo"
  path_prefix: /tmp/loki
  storage:
    filesystem:
      chunks_directory: /tmp/loki/chunks
      rules_directory: /tmp/loki/rules
  replication_factor: 1
  ring:
    instance_interface_names:
      - "lo"
    instance_addr: 127.0.0.1
    kvstore:
      store: inmemory

schema_config:
  configs:
    - from: 2020-10-24
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

ruler:
  alertmanager_url: http://localhost:9093

발생한 문제 및 해결

문제 1: Ingress 네트워크 인터페이스 바인딩 오류

Loki가 Docker Swarm ingress 네트워크에 바인딩되어 있을 때, 컨테이너 내부 인터페이스가 아닌 ingress용 외부 인터페이스를 바인딩하는 오류가 발생합니다.

level=error caller=scheduler_processor.go:87
msg="error contacting scheduler"
err="rpc error: code = Unavailable
     desc = connection error:
     desc= transport: Error while dialing dial tcp 10.0.0.47:9095 i/o timeout"
addr=10.0.0.47:9095

해결: loki-config 파일에서 내부 인터페이스만 사용하도록 instance_interface_namesinstance_addr 옵션을 설정합니다. 다만 일정 확률로 여전히 외부 인터페이스를 바인딩하는 문제가 남아있어 추가 개선이 필요합니다.

문제 2: 로컬 스토리지 사용

현재 Loki의 저장소가 로컬 파일시스템으로 지정되어 있습니다. NFS로 관리하고 있어 당장 큰 문제는 없으나, 데이터량이 증가하면 유실 위험이 있습니다. S3를 스토리지 백엔드로 사용하면 리스크를 줄일 수 있습니다.

마무리

Loki와 Promtail 조합은 가볍고 Grafana와의 통합이 뛰어나 소규모 인프라의 로그 수집에 적합합니다. Docker Swarm 환경에서 ingress 네트워크와 함께 사용할 때 인터페이스 바인딩 문제에 주의해야 합니다.