mirror of
https://github.com/tiennm99/composes.git
synced 2026-10-04 22:13:26 +00:00
- node_exporter (host) + cadvisor (containers) via one scrape job - docker container logs + systemd journal to loki - filter regex keeps only metrics needed for standard dashboards - sized for grafana cloud free tier (~10k active series cap) - shell env driven (no .env file); fail-fast on missing vars - least-privilege: cap_drop all, no privileged, no pid host, ui not published
129 lines
4.4 KiB
YAML
129 lines
4.4 KiB
YAML
# Required shell env vars (export before `docker compose up`):
|
|
# ALLOY_HOSTNAME PROM_URL PROM_USER LOKI_URL LOKI_USER GRAFANA_TOKEN
|
|
|
|
services:
|
|
alloy:
|
|
image: grafana/alloy:v1.10.0
|
|
container_name: alloy
|
|
restart: unless-stopped
|
|
hostname: ${ALLOY_HOSTNAME:?required}
|
|
user: "0:0"
|
|
environment:
|
|
ALLOY_HOSTNAME: ${ALLOY_HOSTNAME}
|
|
PROM_URL: ${PROM_URL:?required}
|
|
PROM_USER: ${PROM_USER:?required}
|
|
LOKI_URL: ${LOKI_URL:?required}
|
|
LOKI_USER: ${LOKI_USER:?required}
|
|
GRAFANA_TOKEN: ${GRAFANA_TOKEN:?required}
|
|
# UI reachable only from inside the Docker network: http://alloy:12345
|
|
# (attach another container to the same network to access it)
|
|
expose: [ "12345" ]
|
|
security_opt: [ "no-new-privileges:true" ]
|
|
cap_drop: [ ALL ]
|
|
volumes:
|
|
- alloy-data:/var/lib/alloy/data
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
- /var/lib/docker:/var/lib/docker:ro
|
|
- /proc:/host/proc:ro
|
|
- /sys:/host/sys:ro
|
|
- /:/rootfs:ro,rslave
|
|
- /var/log/journal:/var/log/journal:ro
|
|
configs:
|
|
- { source: alloy_config, target: /etc/alloy/config.alloy }
|
|
command: [ run, --server.http.listen-addr=0.0.0.0:12345, --storage.path=/var/lib/alloy/data, /etc/alloy/config.alloy ]
|
|
|
|
volumes:
|
|
alloy-data:
|
|
|
|
configs:
|
|
alloy_config:
|
|
content: |
|
|
prometheus.remote_write "gc" {
|
|
endpoint {
|
|
url = sys.env("PROM_URL")
|
|
basic_auth {
|
|
username = sys.env("PROM_USER")
|
|
password = sys.env("GRAFANA_TOKEN")
|
|
}
|
|
}
|
|
}
|
|
|
|
loki.write "gc" {
|
|
endpoint {
|
|
url = sys.env("LOKI_URL")
|
|
basic_auth {
|
|
username = sys.env("LOKI_USER")
|
|
password = sys.env("GRAFANA_TOKEN")
|
|
}
|
|
}
|
|
}
|
|
|
|
prometheus.exporter.unix "host" {
|
|
rootfs_path = "/rootfs"
|
|
procfs_path = "/host/proc"
|
|
sysfs_path = "/host/sys"
|
|
filesystem { mount_points_exclude = "^/(dev|proc|sys|run|var/lib/docker)($|/)" }
|
|
netdev { device_exclude = "^(veth|docker|br-|lo).*$" }
|
|
}
|
|
|
|
prometheus.exporter.cadvisor "containers" {
|
|
docker_only = true
|
|
}
|
|
|
|
discovery.relabel "metrics" {
|
|
targets = array.concat(
|
|
prometheus.exporter.unix.host.targets,
|
|
prometheus.exporter.cadvisor.containers.targets,
|
|
)
|
|
rule { target_label = "instance" replacement = constants.hostname }
|
|
}
|
|
|
|
prometheus.scrape "metrics" {
|
|
targets = discovery.relabel.metrics.output
|
|
forward_to = [prometheus.relabel.filter.receiver]
|
|
scrape_interval = "60s"
|
|
}
|
|
|
|
// Keep only metrics powering the standard Grafana Cloud dashboards.
|
|
// Essential for the 10k active-series cap on Cloud Free.
|
|
prometheus.relabel "filter" {
|
|
forward_to = [prometheus.remote_write.gc.receiver]
|
|
rule {
|
|
source_labels = ["__name__"]
|
|
action = "keep"
|
|
regex = "up|node_(cpu_seconds_total|load(1|5|15)|boot_time_seconds|uname_info|memory_(MemTotal|MemAvailable|Cached|Buffers|SwapTotal|SwapFree)_bytes|filesystem_(size|avail)_bytes|filesystem_readonly|disk_(read|written)_bytes_total|disk_io_time_seconds_total|network_(receive|transmit)_(bytes|errs)_total)|container_(cpu_usage_seconds_total|memory_usage_bytes|fs_(usage|limit)_bytes|network_(receive|transmit)_bytes_total)|machine_memory_bytes"
|
|
}
|
|
}
|
|
|
|
discovery.docker "containers" {
|
|
host = "unix:///var/run/docker.sock"
|
|
}
|
|
|
|
discovery.relabel "container_logs" {
|
|
targets = discovery.docker.containers.targets
|
|
rule { target_label = "instance" replacement = constants.hostname }
|
|
rule {
|
|
source_labels = ["__meta_docker_container_name"]
|
|
regex = "/(.*)"
|
|
target_label = "container"
|
|
}
|
|
rule {
|
|
source_labels = ["__meta_docker_container_name"]
|
|
regex = "/alloy"
|
|
action = "drop"
|
|
}
|
|
}
|
|
|
|
loki.source.docker "containers" {
|
|
host = "unix:///var/run/docker.sock"
|
|
targets = discovery.relabel.container_logs.output
|
|
forward_to = [loki.write.gc.receiver]
|
|
}
|
|
|
|
loki.source.journal "system" {
|
|
max_age = "12h"
|
|
path = "/var/log/journal"
|
|
forward_to = [loki.write.gc.receiver]
|
|
labels = { job = "systemd-journal", instance = constants.hostname }
|
|
}
|