Promtail에서 Alloy로: 쿠버네티스 환경에서 Alloy를 활용한 로그 수집과 Loki 연동

목차

Promtail의 지원 종료(2026년 3월 예정)로 Grafana의 새 에이전트 Alloy로 전환해야 합니다. Alloy는 로그, 메트릭, 트레이스를 한곳에서 수집하며, 컴포넌트 기반의 유연한 파이프라인을 제공합니다. 이 글에서는 Helm Chart를 사용해 쿠버네티스에 Alloy를 배포하고, Loki로 로그를 전송하는 방법을 실습 기반으로 설명합니다.

Promtail과 Alloy의 차이점

쿠버네티스에 Alloy 배포하기 (Helm Chart)

1. Helm 저장소 추가

Grafana Helm Chart 저장소를 추가하고 최신화합니다.

bash
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update

2. Alloy Helm Chart 설치

monitoring 네임스페이스에 Alloy를 설치합니다. ConfigMap으로 Alloy 설정 파일을 전달합니다.

bash
helm install alloy grafana/alloy \
  --namespace monitoring --create-namespace \
  -f values.yaml

Alloy 설정의 컴포넌트 연결과 Loki 전송

Alloy 설정의 컴포넌트 연결과 Loki 전송

Alloy 설정의 컴포넌트 연결과 Loki 전송local.file_match가 /var/log/syslog 대상을 loki.source.file로 넘긴다. discovery.kubernetes가 찾은 Pod 대상은 discovery.relabel을 거쳐 loki.source.kubernetes로 가고 loki.process가 cluster 라벨을 붙인다. loki.source.kubernetes_events가 읽은 클러스터 이벤트도 loki.process를 거친다. 세 흐름 모두 loki.write default로 모여 Loki push 주소로 전송된다.targetsforward_totargetsoutputforward_toforward_toforward_toforward_toendpoint urllocal.file_match node_logs/var/log/syslogloki.source.filenode_logsdiscovery.kubernetespoddiscovery.relabel pod_logsnamespace, pod, container 등 라벨loki.source.kubernetespod_logsloki.process pod_logscluster 정적 라벨loki.source.kubernetes_eventscluster_eventsloki.process cluster_eventscluster 정적 라벨loki.writedefaultLokiloki:3100/loki/api/v1/push
노드 로그, Pod 로그, 클러스터 이벤트가 각각 Alloy 컴포넌트를 거쳐 loki.write 하나로 모이고, loki.write가 Loki endpoint로 보낸다.
그림 관계를 글로 읽기
  1. local.file_match node_logs가 /var/log/syslog 대상을 loki.source.file node_logs의 targets로 넘긴다.
  2. loki.source.file이 읽은 노드 로그를 loki.write default로 forward_to 한다.
  3. discovery.kubernetes pod가 찾은 대상을 discovery.relabel pod_logs가 받는다.
  4. relabel 결과(output)가 loki.source.kubernetes pod_logs의 targets가 된다.
  5. Pod 로그는 loki.process pod_logs로 forward_to 된다.
  6. loki.process pod_logs가 cluster 정적 라벨을 붙여 loki.write로 보낸다.
  7. loki.source.kubernetes_events cluster_events가 클러스터 이벤트를 loki.process cluster_events로 보낸다.
  8. loki.process cluster_events가 라벨을 붙여 loki.write로 보낸다.
  9. loki.write default가 endpoint url(http://loki:3100/loki/api/v1/push)로 전송한다.

3. values.yaml 설정 예시

values.yaml에 아래 Alloy 설정 파일을 ConfigMap으로 마운트합니다.

yaml
configMap:
  enabled: true
  create: true
  name: alloy-config
  file: alloy.yaml
config:
  alloy.yaml: |
    logging {
      level  = "info"
      format = "logfmt"
    }

    loki.write "default" {
      endpoint {
        url = "http://loki:3100/loki/api/v1/push"
      }
    }

    // local.file_match discovers files on the local filesystem using glob patterns
    local.file_match "node_logs" {
      path_targets = [{
        __path__  = "/var/log/syslog",
        job       = "node/syslog",
        node_name = sys.env("HOSTNAME"),
        cluster   = "your-cluster-name",
      }]
    }

    // loki.source.file reads log entries from files
    loki.source.file "node_logs" {
      targets    = local.file_match.node_logs.targets
      forward_to = [loki.write.default.receiver]
    }

    // discovery.kubernetes finds scrape targets from Kubernetes resources
    discovery.kubernetes "pod" {
      role = "pod"
    }

    // discovery.relabel rewrites the label set of input targets
    discovery.relabel "pod_logs" {
      targets = discovery.kubernetes.pod.targets
      rule {
        source_labels = ["__meta_kubernetes_namespace"]
        action = "replace"
        target_label = "namespace"
      }
      rule {
        source_labels = ["__meta_kubernetes_pod_name"]
        action = "replace"
        target_label = "pod"
      }
      rule {
        source_labels = ["__meta_kubernetes_pod_container_name"]
        action = "replace"
        target_label = "container"
      }
      rule {
        source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_name"]
        action = "replace"
        target_label = "app"
      }
      rule {
        source_labels = ["__meta_kubernetes_namespace", "__meta_kubernetes_pod_container_name"]
        action = "replace"
        target_label = "job"
        separator = "/"
        replacement = "$1"
      }
      rule {
        source_labels = ["__meta_kubernetes_pod_uid", "__meta_kubernetes_pod_container_name"]
        action = "replace"
        target_label = "__path__"
        separator = "/"
        replacement = "/var/log/pods/*$1/*.log"
      }
      rule {
        source_labels = ["__meta_kubernetes_pod_container_id"]
        action = "replace"
        target_label = "container_runtime"
        regex = "^(\\S+):\\/\\/.+$"
        replacement = "$1"
      }
    }

    // loki.source.kubernetes tails logs from Kubernetes containers
    loki.source.kubernetes "pod_logs" {
      targets    = discovery.relabel.pod_logs.output
      forward_to = [loki.process.pod_logs.receiver]
    }

    // loki.process applies processing stages to logs
    loki.process "pod_logs" {
      stage.static_labels {
        values = {
          cluster = "your-cluster-name",
        }
      }
      forward_to = [loki.write.default.receiver]
    }

    // loki.source.kubernetes_events tails Kubernetes events
    loki.source.kubernetes_events "cluster_events" {
      job_name   = "integrations/kubernetes/eventhandler"
      log_format = "logfmt"
      forward_to = [loki.process.cluster_events.receiver]
    }

    // loki.process for cluster events
    loki.process "cluster_events" {
      forward_to = [loki.write.default.receiver]
      stage.static_labels {
        values = {
          cluster = "your-cluster-name",
        }
      }
      stage.labels {
        values = {
          kubernetes_cluster_events = "job",
        }
      }
    }

설정 적용 가이드:

  1. your-cluster-name을 실제 클러스터 이름(예: production, us-east-1)으로 교체하세요.
  2. Loki URL(http://loki:3100/loki/api/v1/push)이 환경에 맞는지 확인하세요.

Alloy Config 설명

실습 및 디버깅

  1. 배포 확인:

    bash
    kubectl -n monitoring get pods -l app.kubernetes.io/name=alloy

    Alloy Pod가 Running 상태인지 확인하세요.

  2. 로그 점검:

    bash
    kubectl -n monitoring logs -l app.kubernetes.io/name=alloy

    오류가 있다면, config 문법이나 Loki 연결 문제를 확인하세요.

  3. Loki 로그 확인:
    Grafana Explore에서 {cluster="your-cluster-name"} 쿼리로 로그가 수집되는지 확인하세요.

본문 이미지 1

마무리

Alloy는 Promtail을 대체하며, 노드 로그, Pod 로그, 클러스터 이벤트를 한곳에서 수집할 수 있습니다. Helm Chart와 이 글의 config를 활용하면 빠르게 설정할 수 있습니다. 테스트 환경에서 실습한 뒤 Grafana 대시보드로 로그를 시각화해 보세요.

참고 자료

도식

100%

끌어서 이동, 두 손가락이나 휠로 확대·축소. 키보드: 화살표 이동, + − 확대·축소, 0 맞춤, Esc 닫기. 같은 내용은 그림 아래 “그림 관계를 글로 읽기”에 있다.