Grafana Alloy 명령어
Grafana Alloy는 원격 분석 데이터(메트릭, 로그, 추적)를 수집, 처리 및 내보내기 위한 유연한 공급업체 중립적 OpenTelemetry 배포판입니다. Grafana Agent의 후속작으로, 컴포넌트 기반 구성 언어를 사용합니다.
설치
Linux 패키지 저장소
Debian/Ubuntu
sudo mkdir -p /etc/apt/keyrings/
wget -qO - https://apt.grafana.com/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/grafana.gpg
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get install alloy
RHEL/CentOS/Fedora
sudo tee /etc/yum.repos.d/grafana.repo << EOF
[grafana]
name=grafana
baseurl=https://rpm.grafana.com
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://rpm.grafana.com/gpg.key
EOF
sudo dnf install alloy
macOS
brew install grafana/grafana/alloy
alloy --version
이진 다운로드
# 최신 릴리스 다운로드
wget https://github.com/grafana/alloy/releases/download/v1.14.0/alloy-v1.14.0-linux-amd64.zip
unzip alloy-v1.14.0-linux-amd64.zip
sudo mv alloy /usr/local/bin/
alloy --version
Docker
docker pull grafana/alloy:latest
docker run -v /path/to/config.alloy:/etc/alloy/config.alloy \
grafana/alloy:latest run /etc/alloy/config.alloy --server.http.listen-addr=0.0.0.0:12345
Helm 차트
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm install alloy grafana/alloy --namespace monitoring --create-namespace \
-f values.yaml
기본 명령어
| 명령 | 설명 |
|---|---|
alloy run config.alloy | 지정된 구성 파일로 Alloy 실행 |
alloy run config.alloy --server.http.listen-addr=0.0.0.0:12345 | 사용자 정의 HTTP 서버 주소로 실행 |
alloy fmt config.alloy | 구성 파일 형식 지정 및 검증 (드라이 런) |
alloy fmt -w config.alloy | 구성 파일을 제자리에서 형식 지정 |
alloy tools parse config.alloy | 구성 구문 파싱 및 검증 |
alloy tools lint config.alloy | 구성 문제에 대한 린트 |
alloy --version | Alloy 버전 표시 |
alloy --help | 도움말 정보 표시 |
alloy run --help | 실행 명령 옵션 표시 |
구성 기초
파일 확장명 및 구문
Alloy는 .alloy 파일 확장명을 사용하는 컴포넌트 기반 구성 언어(HCL과 유사)를 사용합니다.
기본 구조
// Comments use //
// Component instantiation: <component_type>.<unique_name> { ... }
prometheus.scrape "example" {
targets = [{"__address__" = "localhost:9090"}]
forward_to = [prometheus.remote_write.grafana.receiver]
}
// Export data from component to another
prometheus.remote_write "grafana" {
endpoint {
url = "https://prometheus.grafana.net/api/prom/push"
headers = {
"Authorization" = "Bearer ${GRAFANA_TOKEN}"
}
}
}
변수 및 보안 정보
// Environment variables
GRAFANA_TOKEN = env("GRAFANA_TOKEN")
PROMETHEUS_URL = env("PROMETHEUS_URL")
// Local variables
local "my_targets" {
value = [
{"__address__" = "localhost:9090"},
{"__address__" = "localhost:9100"},
]
}
// Reference variables
prometheus.scrape "nodes" {
targets = local.my_targets.value
}
인수 및 내보내기 블록
// Most components accept arguments
prometheus.scrape "example" {
targets = [{"__address__" = "localhost:9090"}]
scrape_interval = "30s"
scrape_timeout = "10s"
forward_to = [prometheus.remote_write.grafana.receiver]
}
// Components export data (visible in UI under Exports)
// Example: prometheus.scrape exports scraped_targets and targets
컴포넌트 - 소스
Prometheus Scrape
prometheus.scrape "kubernetes" {
targets = discovery.kubernetes.nodes.targets
scrape_interval = "30s"
scrape_timeout = "10s"
metrics_path = "/metrics"
scheme = "http"
forward_to = [prometheus.relabel.drop_internal.receiver]
}
Loki 파일 소스
loki.source.file "app_logs" {
targets = [
{
__path__ = "/var/log/app/*.log",
job = "app",
env = "production",
}
]
forward_to = [loki.relabel.add_labels.receiver]
}
OpenTelemetry Receiver (OTLP)
otelcol.receiver.otlp "default" {
grpc {
endpoint = "0.0.0.0:4317"
}
http {
endpoint = "0.0.0.0:4318"
}
output {
traces = [otelcol.processor.batch.default.input]
metrics = [otelcol.processor.batch.default.input]
logs = [otelcol.processor.batch.default.input]
}
}
Prometheus Remote Write Receiver
prometheus.receive_http "example" {
http {
address = "0.0.0.0:9009"
}
forward_to = [prometheus.relabel.example.receiver]
}
Loki API 서버
loki.relabel "add_labels" {
forward_to = [loki.write.grafana.receiver]
rule {
source_labels = ["__path__"]
target_label = "job"
replacement = "app-logs"
}
}
컴포넌트 - 프로세서
배치 프로세서
otelcol.processor.batch "default" {
send_batch_size = 1000
timeout = "10s"
send_batch_max_size = 2000
output {
traces = [otelcol.exporter.otlp.grafana.input]
metrics = [otelcol.exporter.prometheus.grafana.input]
logs = [otelcol.exporter.loki.grafana.input]
}
}
필터 프로세서
otelcol.processor.filter "drop_internal" {
metrics {
exclude {
match_type = "regexp"
regexp = "internal_.*"
}
}
output {
metrics = [otelcol.exporter.prometheus.grafana.input]
}
}
리소스 감지 프로세서
otelcol.processor.resourcedetection "default" {
detectors = ["env", "system", "gcp", "aws", "azure", "docker", "kubernetes"]
output {
traces = [otelcol.processor.batch.default.input]
metrics = [otelcol.processor.batch.default.input]
logs = [otelcol.processor.batch.default.input]
}
}
속성 프로세서
otelcol.processor.attributes "add_env" {
action {
key = "environment"
value = "production"
action = "insert"
}
action {
key = "pod_name"
from_attribute = "k8s.pod.name"
action = "insert"
}
output {
traces = [otelcol.processor.batch.default.input]
metrics = [otelcol.processor.batch.default.input]
logs = [otelcol.processor.batch.default.input]
}
}
메모리 제한 프로세서
otelcol.processor.memory_limiter "default" {
check_interval = "5s"
limit_mib = 512
spike_limit_mib = 256
output {
traces = [otelcol.processor.batch.default.input]
metrics = [otelcol.processor.batch.default.input]
logs = [otelcol.processor.batch.default.input]
}
}
스팬 프로세서 (추적)
otelcol.processor.span "extract_attributes" {
name {
to_attributes {
rules = ["^/api/(?P<version>v\\d)/(?P<resource>\\w+)"]
}
}
output {
traces = [otelcol.processor.batch.default.input]
}
}
컴포넌트 - 내보내기
Prometheus Remote Write
prometheus.remote_write "grafana" {
endpoint {
url = "https://prometheus.grafana.net/api/prom/push"
basic_auth {
username = "GRAFANA_USER_ID"
password = "${GRAFANA_TOKEN}"
}
headers = {
"X-Custom-Header" = "value"
}
tls_config {
insecure_skip_verify = false
}
}
wal {
enabled = true
directory = "/var/lib/alloy/wal"
}
queue_settings {
capacity = 10000
}
}
Loki Write
loki.write "grafana" {
endpoint {
url = "https://logs.grafana.net/loki/api/v1/push"
basic_auth {
username = "GRAFANA_USER_ID"
password = "${GRAFANA_TOKEN}"
}
}
tenant_id = "production"
}
OpenTelemetry Exporter (OTLP)
otelcol.exporter.otlp "grafana_cloud" {
client {
endpoint = "tempo.grafana.net:4317"
auth = otelcol.auth.basic "grafana" {}
tls {
insecure = false
}
}
retry_on_failure {
enabled = true
initial_interval = "5s"
max_interval = "30s"
max_elapsed_time = "5m"
}
}
OTLP 인증
otelcol.auth.basic "grafana" {
username = "GRAFANA_USER_ID"
password = "${GRAFANA_TOKEN}"
}
// OTLP with basic auth
otelcol.exporter.otlp "example" {
client {
endpoint = "tempo.grafana.net:4317"
auth = otelcol.auth.basic.grafana.handler
}
}
Prometheus Exporter (Node Exporter 스타일)
prometheus.exporter.unix "local_system" {
disabled_collectors = ["netdev", "netstat"]
}
prometheus.scrape "local_system" {
targets = prometheus.exporter.unix.local_system.targets
forward_to = [prometheus.remote_write.grafana.receiver]
}
컴포넌트 - 디스커버리
Kubernetes 디스커버리
discovery.kubernetes "cluster" {
role = "pod"
namespaces {
names = ["default", "monitoring", "production"]
}
}
prometheus.scrape "kubernetes" {
targets = discovery.kubernetes.cluster.targets
forward_to = [prometheus.remote_write.grafana.receiver]
relabel_configurations {
source_labels = ["__meta_kubernetes_pod_annotation_prometheus_io_scrape"]
regex = "true"
action = "keep"
}
}
Docker 디스커버리
discovery.docker "local" {
host = "unix:///var/run/docker.sock"
}
prometheus.scrape "docker" {
targets = discovery.docker.local.targets
forward_to = [prometheus.remote_write.grafana.receiver]
}
Consul 디스커버리
discovery.consul "example" {
server = "localhost:8500"
datacenter = "dc1"
services = ["prometheus", "app"]
}
prometheus.scrape "consul" {
targets = discovery.consul.example.targets
forward_to = [prometheus.remote_write.grafana.receiver]
}
파일 기반 디스커버리
discovery.file "dynamic_targets" {
files = ["/etc/alloy/targets.json"]
refresh_interval = "30s"
}
prometheus.scrape "file_targets" {
targets = discovery.file.dynamic_targets.targets
forward_to = [prometheus.remote_write.grafana.receiver]
}
메트릭 수집
Prometheus 스크래핑 재라벨링
prometheus.scrape "prometheus" {
targets = [
{
__address__ = "prometheus.example.com:9090",
job = "prometheus",
},
{
__address__ = "alertmanager.example.com:9093",
job = "alertmanager",
},
]
metrics_path = "/metrics"
scrape_interval = "30s"
scrape_timeout = "10s"
relabel_configurations {
source_labels = ["__address__"]
target_label = "instance"
regex = "([^:]+)(?::\\d+)?"
replacement = "${1}"
}
metric_relabel_configurations {
source_labels = ["__name__"]
regex = "up|job|instance"
action = "keep"
}
forward_to = [prometheus.relabel.drop_internal.receiver]
}
Node Exporter 통합
prometheus.exporter.unix "node_metrics" {
collectors = ["cpu", "diskstats", "filesystem", "loadavg", "meminfo", "netdev", "netstat"]
disabled_collectors = ["netdev"]
set_collectors = ["textfile"]
textfile_directory = "/var/lib/node_exporter/textfile_collector"
}
prometheus.scrape "node_exporter" {
targets = prometheus.exporter.unix.node_metrics.targets
forward_to = [prometheus.remote_write.grafana.receiver]
}
사용자 정의 메트릭 엔드포인트
prometheus.scrape "custom_app" {
targets = [
{
__address__ = "app.example.com:8080",
__metrics_path__ = "/api/metrics",
job = "custom-app",
env = "production",
},
]
scrape_interval = "15s"
forward_to = [prometheus.remote_write.grafana.receiver]
}
로그 수집
Loki로 파일 테일링
loki.source.file "application" {
targets = [
{
__path__ = "/var/log/app/app.log",
job = "app",
service = "web",
env = "production",
},
{
__path__ = "/var/log/app/error.log",
job = "app",
level = "error",
},
]
forward_to = [loki.relabel.add_labels.receiver]
}
Journal 로그 (systemd)
loki.source.journal "systemd" {
path = "/var/log/journal"
labels = {
job = "systemd",
}
forward_to = [loki.relabel.add_labels.receiver]
}
JSON 로그 파싱
loki.relabel "parse_json" {
forward_to = [loki.process.extract_json.receiver]
rule {
source_labels = ["__path__"]
target_label = "filename"
}
}
loki.process "extract_json" {
forward_to = [loki.write.grafana.receiver]
stage {
json {
expressions = {
timestamp = "ts",
message = "msg",
level = "level",
service = "service",
}
}
}
stage {
labels {
values = {
level = "level",
service = "service",
}
}
}
stage {
timestamp {
source = "timestamp"
format = "Unix"
}
}
}
다중 행 로그 (스택 추적)
loki.process "multiline" {
forward_to = [loki.write.grafana.receiver]
stage {
multiline {
line_start_pattern = "^\\d{4}-\\d{2}-\\d{2}"
}
}
stage {
regex {
expression = "^(?P<timestamp>\\d{4}-\\d{2}-\\d{2}) (?P<level>\\w+) (?P<message>.*)"
}
}
stage {
labels {
values = {
level = "level",
}
}
}
}
추적 수집
OpenTelemetry 추적 파이프라인
otelcol.receiver.otlp "app" {
grpc {
endpoint = "0.0.0.0:4317"
}
http {
endpoint = "0.0.0.0:4318"
}
output {
traces = [otelcol.processor.memory_limiter.default.input]
}
}
otelcol.processor.memory_limiter "default" {
check_interval = "5s"
limit_mib = 512
spike_limit_mib = 256
output {
traces = [otelcol.processor.batch.default.input]
}
}
otelcol.processor.batch "default" {
send_batch_size = 100
timeout = "10s"
output {
traces = [otelcol.exporter.otlp.grafana.input]
}
}
otelcol.exporter.otlp "grafana" {
client {
endpoint = "tempo.grafana.net:4317"
auth = otelcol.auth.basic.grafana.handler
}
}
otelcol.auth.basic "grafana" {
username = "GRAFANA_USER_ID"
password = "${GRAFANA_TOKEN}"
}
Jaeger Receiver
otelcol.receiver.jaeger "default" {
protocols {
grpc {
endpoint = "0.0.0.0:14250"
}
thrift_http {
endpoint = "0.0.0.0:14268"
}
}
output {
traces = [otelcol.processor.batch.default.input]
}
}
Zipkin Receiver
otelcol.receiver.zipkin "default" {
endpoint = "0.0.0.0:9411"
output {
traces = [otelcol.processor.batch.default.input]
}
}
Kubernetes 배포
Helm 값 (values.yaml)
config: |
otelcol.receiver.otlp "default" {
grpc {
endpoint = "0.0.0.0:4317"
}
http {
endpoint = "0.0.0.0:4318"
}
output {
traces = [otelcol.processor.batch.default.input]
}
}
otelcol.processor.batch "default" {
send_batch_size = 100
output {
traces = [otelcol.exporter.otlp.grafana.input]
}
}
otelcol.exporter.otlp "grafana" {
client {
endpoint = "tempo.grafana.net:4317"
auth = otelcol.auth.basic.grafana.handler
}
}
otelcol.auth.basic "grafana" {
username = "GRAFANA_USER_ID"
password = "${GRAFANA_TOKEN}"
}
alloy:
remoteConfigUrl: ""
serviceAccount:
create: true
rbac:
create: true
daemonset:
enabled: true
deployment:
enabled: true
replicas: 1
configMap:
content: ""
livenessProbe:
enabled: true
readinessProbe:
enabled: true
Helm 설치
# 사용자 정의 값으로 설치
helm install alloy grafana/alloy \
--namespace monitoring \
--create-namespace \
-f values.yaml
# 기존 설치 업그레이드
helm upgrade alloy grafana/alloy \
--namespace monitoring \
-f values.yaml
# 제거
helm uninstall alloy --namespace monitoring
DaemonSet 예제
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alloy
namespace: monitoring
spec:
selector:
matchLabels:
app: alloy
template:
metadata:
labels:
app: alloy
spec:
serviceAccountName: alloy
containers:
- name: alloy
image: grafana/alloy:latest
args:
- run
- /etc/alloy/config.alloy
- --server.http.listen-addr=0.0.0.0:12345
ports:
- name: http
containerPort: 12345
- name: otlp-grpc
containerPort: 4317
- name: otlp-http
containerPort: 4318
volumeMounts:
- name: config
mountPath: /etc/alloy
- name: varlog
mountPath: /var/log
readOnly: true
volumes:
- name: config
configMap:
name: alloy-config
- name: varlog
hostPath:
path: /var/log
---
apiVersion: v1
kind: ConfigMap
metadata:
name: alloy-config
namespace: monitoring
data:
config.alloy: |
prometheus.scrape "kubernetes" {
targets = discovery.kubernetes.nodes.targets
forward_to = [prometheus.remote_write.grafana.receiver]
}
discovery.kubernetes "nodes" {
role = "node"
}
prometheus.remote_write "grafana" {
endpoint {
url = "https://prometheus.grafana.net/api/prom/push"
basic_auth {
username = "GRAFANA_USER_ID"
password = "${GRAFANA_TOKEN}"
}
}
}
ServiceMonitor 예제
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: app-metrics
namespace: production
spec:
selector:
matchLabels:
app: myapp
endpoints:
- port: metrics
interval: 30s
path: /metrics
Docker 구성
Compose 파일
version: '3.8'
services:
alloy:
image: grafana/alloy:latest
container_name: alloy
command:
- run
- /etc/alloy/config.alloy
- --server.http.listen-addr=0.0.0.0:12345
ports:
- "12345:12345"
- "4317:4317"
- "4318:4318"
volumes:
- ./alloy-config.alloy:/etc/alloy/config.alloy
- /var/run/docker.sock:/var/run/docker.sock
- /var/log:/var/log:ro
environment:
- GRAFANA_TOKEN=${GRAFANA_TOKEN}
networks:
- monitoring
prometheus:
image: prom/prometheus:latest
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
networks:
- monitoring
networks:
monitoring:
driver: bridge
컨테이너 실행
# 구성 파일로 실행
docker run -d \
--name alloy \
-v /path/to/config.alloy:/etc/alloy/config.alloy \
-p 12345:12345 \
-p 4317:4317 \
-p 4318:4318 \
-e GRAFANA_TOKEN=$GRAFANA_TOKEN \
grafana/alloy:latest run /etc/alloy/config.alloy \
--server.http.listen-addr=0.0.0.0:12345
# 로그 보기
docker logs -f alloy
# 컨테이너 중지
docker stop alloy
docker rm alloy
디버깅
웹 UI 접근
# Alloy UI 접근 (기본 포트 12345)
# 컴포넌트 상태, 내보내기, 메트릭 표시
curl http://localhost:12345
# 브라우저: http://localhost:12345/graph
로그 레벨
# Debug 로깅으로 실행
alloy run config.alloy --log.level=debug
# Info 로깅으로 실행 (기본값)
alloy run config.alloy --log.level=info
# 경고 로깅으로 실행
alloy run config.alloy --log.level=warn
구성 검증
# 실행하지 않고 구성 파싱
alloy tools parse config.alloy
# 구문 오류 확인
alloy fmt config.alloy
# Lint 및 검증
alloy tools lint config.alloy
컴포넌트 검사
# 모든 컴포넌트 유형 보기
alloy tools component list
# 컴포넌트 문서 가져오기
alloy tools component doc prometheus.scrape
# 컴포넌트 스키마 표시
alloy tools component schema prometheus.scrape
Pprof 프로파일링
# pprof 서버 활성화 (기본: http://localhost:6060/debug/pprof)
alloy run config.alloy --pprof.enabled=true --pprof.address=0.0.0.0:6060
# Heap 프로필 보기
curl http://localhost:6060/debug/pprof/heap > heap.prof
go tool pprof heap.prof
# Goroutine 프로필 보기
curl http://localhost:6060/debug/pprof/goroutine
추적 검사
# 분산 추적 활성화
alloy run config.alloy --traces.enabled=true
# 추적 UI 접근 (노출된 경우)
curl http://localhost:12345/traces
환경 변수
| 변수 | 설명 |
|---|---|
ALLOY_CONFIG_FILE | 구성 파일 경로 |
GRAFANA_TOKEN | Grafana Cloud 인증 토큰 |
PROMETHEUS_URL | Prometheus 서버 엔드포인트 |
LOKI_URL | Loki API 엔드포인트 |
TEMPO_URL | Tempo API 엔드포인트 |
OTEL_EXPORTER_OTLP_ENDPOINT | OpenTelemetry OTLP 내보내기 엔드포인트 |
OTEL_EXPORTER_OTLP_HEADERS | OTLP 내보내기 헤더 |
OTEL_SDK_DISABLED | OpenTelemetry SDK 비활성화 |
LOG_LEVEL | 로깅 레벨: debug, info, warn, error |
ALLOY_REMOTE_CONFIG_URL | 원격 구성 URL |
NODE_NAME | 노드 식별자 (k8s 노드 이름) |
POD_NAME | Pod 이름 (k8s용) |
NAMESPACE | Kubernetes 네임스페이스 |
환경 변수 사용
# 변수 내보내기
export GRAFANA_TOKEN="glc_xxx"
export PROMETHEUS_URL="https://prometheus.grafana.net"
# Alloy 실행
alloy run config.alloy
# config.alloy에서 ${ }로 참조
prometheus.remote_write "grafana" {
endpoint {
url = "${PROMETHEUS_URL}/api/prom/push"
basic_auth {
password = "${GRAFANA_TOKEN}"
}
}
}
리소스
- 공식 문서: https://grafana.com/docs/alloy/latest/
- 구성 참조: https://grafana.com/docs/alloy/latest/reference/
- 컴포넌트 카탈로그: https://grafana.com/docs/alloy/latest/reference/components/
- GitHub 저장소: https://github.com/grafana/alloy
- 릴리스 노트: https://github.com/grafana/alloy/releases
- Grafana Cloud 통합: https://grafana.com/products/cloud/
- OpenTelemetry 명세: https://opentelemetry.io/docs/
- 커뮤니티 토론: https://community.grafana.com/
- 튜토리얼 및 예제: https://grafana.com/docs/alloy/latest/tutorials/
- Helm 차트: https://github.com/grafana/helm-charts/tree/main/charts/alloy
- Docker 이미지: https://hub.docker.com/r/grafana/alloy
- 피드백 및 이슈: https://github.com/grafana/alloy/issues