Phase 13 build: logs, metrics, alerting and a deadman on a diag. host
Six containers, all loopback-published, reachable only through the gated diag. host: victorialogs 30d retention, -http.pathPrefix=/logs so Caddy passes the prefix through unchanged vector docker_logs + journald -> VictoriaLogs (elasticsearch bulk, the documented path) victoriametrics 90d, scrapes the four taps that were already live plus the new services vmalert-metrics 11 metric rules: disk, load, memory, RAID, restart loops, a core container gone vmalert-logs 5 LogsQL rules: sweep failures, publish-deny bursts, failed bot deploys, cert trouble alertmanager groups and inhibits, posts to Discord, webhook read from a 0600 file not the config The deadman (bin/vanguard-deadman.sh, host timer, 5 min) is the part that does not trust any of the above: curl only, it checks each component answers, that the always-firing Watchdog alert is still arriving through vmalert -> Alertmanager -> dumpd /heartbeat, and the disks. It reports on change and announces recovery once. Verified here: failures listed, silence when nothing changes, disk threshold, recovery fired once. Collection uses the Docker socket (Phase 13 option A, chosen explicitly). That is root-equivalent on this host and is recorded as such in vector.yaml with the two upgrade paths. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -345,10 +345,135 @@ services:
|
||||
privileged: true
|
||||
restart: unless-stopped
|
||||
|
||||
# ================================================================ observability (Phase 13)
|
||||
# Logs: Vector -> VictoriaLogs. Metrics: VictoriaMetrics scrapes the four taps.
|
||||
# Alerting: a vmalert per datasource -> Alertmanager -> Discord. All loopback; published via diag.HOST.
|
||||
# The deadman (bin/vanguard-deadman.sh, a host timer) watches THIS stack, because nothing in it can.
|
||||
victorialogs:
|
||||
logging: *vglog
|
||||
labels: { vanguard.service: victorialogs, vanguard.category: infra }
|
||||
image: docker.io/victoriametrics/victoria-logs:latest
|
||||
container_name: victorialogs
|
||||
user: "1000:1000"
|
||||
command:
|
||||
- -storageDataPath=/data
|
||||
- -retentionPeriod=30d
|
||||
- -httpListenAddr=:9428
|
||||
- -http.pathPrefix=/logs # its own UI then emits /logs/... so Caddy must NOT strip the prefix
|
||||
ports:
|
||||
- "127.0.0.1:9428:9428"
|
||||
volumes:
|
||||
- /srv/appdata/victorialogs:/data
|
||||
restart: unless-stopped
|
||||
|
||||
vector:
|
||||
logging: *vglog
|
||||
labels: { vanguard.service: vector, vanguard.category: infra }
|
||||
image: docker.io/timberio/vector:latest-debian
|
||||
container_name: vector
|
||||
environment:
|
||||
VECTOR_CONFIG: /etc/vector/vector.yaml
|
||||
volumes:
|
||||
- ./observability/vector.yaml:/etc/vector/vector.yaml:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock # Phase 13 decision "A": container logs need the Docker
|
||||
# API, so this is root-equivalent on the host. Upgrade
|
||||
# paths: journald log driver, or a read-only socket proxy.
|
||||
- /var/log/journal:/var/log/journal:ro # our own systemd units
|
||||
- /etc/machine-id:/etc/machine-id:ro # journald needs it to find the right journal
|
||||
- vector_data:/var/lib/vector
|
||||
depends_on:
|
||||
- victorialogs
|
||||
restart: unless-stopped
|
||||
|
||||
victoriametrics:
|
||||
logging: *vglog
|
||||
labels: { vanguard.service: victoriametrics, vanguard.category: infra }
|
||||
image: docker.io/victoriametrics/victoria-metrics:latest
|
||||
container_name: victoriametrics
|
||||
user: "1000:1000"
|
||||
command:
|
||||
- -storageDataPath=/data
|
||||
- -retentionPeriod=90d
|
||||
- -httpListenAddr=:8428
|
||||
- -promscrape.config=/etc/vm/scrape.yml
|
||||
- -promscrape.config.strictParse=false
|
||||
ports:
|
||||
- "127.0.0.1:8428:8428"
|
||||
volumes:
|
||||
- /srv/appdata/victoriametrics:/data
|
||||
- ./observability/scrape.yml:/etc/vm/scrape.yml:ro
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway" # the four taps bind the host's loopback
|
||||
restart: unless-stopped
|
||||
|
||||
vmalert-metrics:
|
||||
logging: *vglog
|
||||
labels: { vanguard.service: vmalert-metrics, vanguard.category: infra }
|
||||
image: docker.io/victoriametrics/vmalert:latest
|
||||
container_name: vmalert-metrics
|
||||
command:
|
||||
- -datasource.url=http://victoriametrics:8428
|
||||
- -notifier.url=http://alertmanager:9093
|
||||
- -remoteWrite.url=http://victoriametrics:8428
|
||||
- -rule=/etc/alerts/alerts-metrics.yml
|
||||
- -httpListenAddr=:8880
|
||||
- -evaluationInterval=1m
|
||||
ports:
|
||||
- "127.0.0.1:8880:8880"
|
||||
volumes:
|
||||
- ./observability/alerts-metrics.yml:/etc/alerts/alerts-metrics.yml:ro
|
||||
depends_on:
|
||||
- victoriametrics
|
||||
- alertmanager
|
||||
restart: unless-stopped
|
||||
|
||||
vmalert-logs:
|
||||
logging: *vglog
|
||||
labels: { vanguard.service: vmalert-logs, vanguard.category: infra }
|
||||
image: docker.io/victoriametrics/vmalert:latest
|
||||
container_name: vmalert-logs
|
||||
# A vmalert instance has one datasource, so log rules need their own: this one queries VictoriaLogs'
|
||||
# LogsQL stats endpoints, which answer in the Prometheus format vmalert expects.
|
||||
command:
|
||||
- -datasource.url=http://victorialogs:9428/logs
|
||||
- -notifier.url=http://alertmanager:9093
|
||||
- -remoteWrite.url=http://victoriametrics:8428
|
||||
- -rule=/etc/alerts/alerts-logs.yml
|
||||
- -httpListenAddr=:8881
|
||||
- -evaluationInterval=2m
|
||||
ports:
|
||||
- "127.0.0.1:8881:8881"
|
||||
volumes:
|
||||
- ./observability/alerts-logs.yml:/etc/alerts/alerts-logs.yml:ro
|
||||
depends_on:
|
||||
- victorialogs
|
||||
- alertmanager
|
||||
restart: unless-stopped
|
||||
|
||||
alertmanager:
|
||||
logging: *vglog
|
||||
labels: { vanguard.service: alertmanager, vanguard.category: infra }
|
||||
image: docker.io/prom/alertmanager:latest
|
||||
container_name: alertmanager
|
||||
command:
|
||||
- --config.file=/etc/alertmanager/alertmanager.yml
|
||||
- --storage.path=/data
|
||||
- --web.listen-address=:9093
|
||||
ports:
|
||||
- "127.0.0.1:9093:9093"
|
||||
volumes:
|
||||
- ./observability/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
|
||||
- /etc/vanguard/alert-webhook:/etc/vanguard/alert-webhook:ro # written by configure.py, mode 0600
|
||||
- /srv/appdata/alertmanager:/data
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway" # the Watchdog heartbeat goes to dumpd on the bridge port
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
botnet: # isolates discord-bot from the shared default network (see above)
|
||||
|
||||
volumes:
|
||||
copyparty_hist:
|
||||
vector_data:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
|
||||
Reference in New Issue
Block a user