merge: remove cadvisor from the observability stack (chore/remove-cadvisor)
Some checks failed
CI / notebooks-smoke (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
Deploy / notebooks (push) Has been cancelled
Deploy / zotero (push) Has been cancelled
Deploy / docs (push) Has been cancelled
Deploy / api (push) Has been cancelled
Deploy / llm (push) Has been cancelled
Deploy / mc (push) Has been cancelled
Deploy / report (push) Has been cancelled
Infra CI / notebooks (push) Has been cancelled
Infra CI / zotero (push) Has been cancelled
Infra CI / docs (push) Has been cancelled
Infra CI / api (push) Has been cancelled
Infra CI / llm (push) Has been cancelled
Infra CI / mc (push) Has been cancelled

This commit is contained in:
kert
2026-09-09 10:38:18 -04:00
8 changed files with 18 additions and 170 deletions

View File

@@ -790,27 +790,6 @@ services:
- no-new-privileges:true - no-new-privileges:true
restart: unless-stopped restart: unless-stopped
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
networks:
- observability
privileged: true
volumes:
- /:/rootfs:ro
- ${DOCKER_SOCK:-/run/user/1000/docker.sock}:/var/run/docker.sock:ro
- /sys:/sys:ro
- /dev/disk/:/dev/disk:ro
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/healthz"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
labels:
- "promtail=true"
restart: unless-stopped
nvidia-exporter: nvidia-exporter:
image: nvcr.io/nvidia/k8s/dcgm-exporter:3.3.9-3.6.1-ubuntu22.04 image: nvcr.io/nvidia/k8s/dcgm-exporter:3.3.9-3.6.1-ubuntu22.04
# Prefixed: corwins.media compose also defines a "nvidia-exporter" # Prefixed: corwins.media compose also defines a "nvidia-exporter"

View File

@@ -2,11 +2,11 @@
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Replace Jaeger with Tempo, add cadvisor + nvidia-exporter, switch promtail from filesystem scraping to docker_sd opt-in, port per-service log pipelines to the stack's services, enable Loki retention, wire Grafana SSO via Gitea, and provision six per-service dashboards. **Goal:** Replace Jaeger with Tempo, add nvidia-exporter, switch promtail from filesystem scraping to docker_sd opt-in, port per-service log pipelines to the stack's services, enable Loki retention, wire Grafana SSO via Gitea, and provision six per-service dashboards.
**Architecture:** Compose-native — every change lands in `compose.yml`, an `infra/<component>/<config>.yml`, or a JSON dashboard. The full stack runs on Podman/Docker with the existing networks (`gateway`, `observability`, `storage`, `data`, `ci`). New services live on `observability`; tempo + cadvisor + nvidia-exporter only need docker.sock and host filesystem reads, so the network's `internal: true` constraint is preserved. Grafana already has `gateway + observability`, which is exactly what's needed for OAuth token exchange to `git:3000` plus internal datasource access. **Architecture:** Compose-native — every change lands in `compose.yml`, an `infra/<component>/<config>.yml`, or a JSON dashboard. The full stack runs on Podman/Docker with the existing networks (`gateway`, `observability`, `storage`, `data`, `ci`). New services live on `observability`; tempo + nvidia-exporter only need docker.sock and host filesystem reads, so the network's `internal: true` constraint is preserved. Grafana already has `gateway + observability`, which is exactly what's needed for OAuth token exchange to `git:3000` plus internal datasource access.
**Tech Stack:** Docker Compose, Loki, Promtail, Grafana, Prometheus, Tempo, OpenTelemetry Collector, cAdvisor, DCGM-exporter (NVIDIA), Traefik, Gitea (OAuth provider). **Tech Stack:** Docker Compose, Loki, Promtail, Grafana, Prometheus, Tempo, OpenTelemetry Collector, DCGM-exporter (NVIDIA), Traefik, Gitea (OAuth provider).
**Spec:** `docs/superpowers/specs/2026-05-01-observability-port-design.md` **Spec:** `docs/superpowers/specs/2026-05-01-observability-port-design.md`
@@ -27,11 +27,11 @@
- `tests/test_observability.py` — compose invariant tests for the new layout - `tests/test_observability.py` — compose invariant tests for the new layout
**Modified:** **Modified:**
- `compose.yml` — add tempo/cadvisor/nvidia-exporter, drop jaeger, label all services with `promtail=true`, Traefik access logs, Grafana OAuth env - `compose.yml` — add tempo/nvidia-exporter, drop jaeger, label all services with `promtail=true`, Traefik access logs, Grafana OAuth env
- `infra/loki/loki-config.yml` — retention + compactor - `infra/loki/loki-config.yml` — retention + compactor
- `infra/loki/promtail-config.yml` — full rewrite (docker_sd + per-service) - `infra/loki/promtail-config.yml` — full rewrite (docker_sd + per-service)
- `infra/otel/otel-collector.yml` — traces → tempo, add memory_limiter - `infra/otel/otel-collector.yml` — traces → tempo, add memory_limiter
- `infra/prometheus/targets/services.yml` — add cadvisor/nvidia/tempo, drop jaeger - `infra/prometheus/targets/services.yml` — add nvidia/tempo, drop jaeger
- `infra/grafana/provisioning/datasources/datasources.yml` — Tempo replaces Jaeger; Loki default; correlation - `infra/grafana/provisioning/datasources/datasources.yml` — Tempo replaces Jaeger; Loki default; correlation
- `infra/traefik/dynamic/services.yml` — swap jaeger → tempo route - `infra/traefik/dynamic/services.yml` — swap jaeger → tempo route
- `stack.toml` — `subdomains` swap jaeger → tempo - `stack.toml` — `subdomains` swap jaeger → tempo
@@ -224,89 +224,6 @@ git commit -m "feat(observability): add Tempo trace backend"
--- ---
## Task 2: cadvisor service
**Files:**
- Modify: `compose.yml`
- Test: `tests/test_observability.py`
- [ ] **Step 2.1: Write the failing test**
Append to `tests/test_observability.py`:
```python
class TestCadvisor:
def test_cadvisor_service_present(self):
svcs = _services()
assert "cadvisor" in svcs
def test_cadvisor_privileged(self):
# cadvisor needs privileged for cgroup reads
assert _services()["cadvisor"].get("privileged") is True
def test_cadvisor_mounts(self):
svc = _services()["cadvisor"]
sources = []
for v in svc["volumes"]:
if isinstance(v, str):
sources.append(v.split(":")[0])
# rootfs, sys, /dev/disk needed for resource introspection
assert any(s == "/" for s in sources)
assert any(s == "/sys" for s in sources)
```
- [ ] **Step 2.2: Run test to verify it fails**
```bash
uv run pytest tests/test_observability.py::TestCadvisor -v
```
Expected: FAIL.
- [ ] **Step 2.3: Add cadvisor to compose.yml**
Insert after the `tempo` service block:
```yaml
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
networks:
- observability
privileged: true
volumes:
- /:/rootfs:ro
- ${DOCKER_SOCK:-/run/user/1000/docker.sock}:/var/run/docker.sock:ro
- /sys:/sys:ro
- /dev/disk/:/dev/disk:ro
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/healthz"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
restart: unless-stopped
```
- [ ] **Step 2.4: Run tests, bring service up, verify**
```bash
uv run pytest tests/test_observability.py::TestCadvisor -v
docker compose up -d cadvisor
docker exec cadvisor wget -q -O- http://localhost:8080/healthz
# expected: "ok"
docker exec cadvisor wget -q -O- http://localhost:8080/metrics | grep -c '^container_cpu_usage_seconds_total'
# expected: > 0
```
- [ ] **Step 2.5: Commit**
```bash
git add compose.yml tests/test_observability.py
git commit -m "feat(observability): add cadvisor for container metrics"
```
---
## Task 3: nvidia-exporter (DCGM) service ## Task 3: nvidia-exporter (DCGM) service
**Files:** **Files:**
@@ -342,7 +259,7 @@ Expected: FAIL.
- [ ] **Step 3.3: Add service** - [ ] **Step 3.3: Add service**
Insert after the `cadvisor` service block: Insert after the `tempo` service block:
```yaml ```yaml
nvidia-exporter: nvidia-exporter:
@@ -972,7 +889,6 @@ class TestPrometheusTargets:
targets = yaml.safe_load(path.read_text()) targets = yaml.safe_load(path.read_text())
jobs = {entry["labels"]["job"] for entry in targets if "labels" in entry} jobs = {entry["labels"]["job"] for entry in targets if "labels" in entry}
assert "tempo" in jobs assert "tempo" in jobs
assert "cadvisor" in jobs
assert "nvidia-gpu" in jobs assert "nvidia-gpu" in jobs
assert "jaeger" not in jobs assert "jaeger" not in jobs
``` ```
@@ -1008,11 +924,6 @@ Expected: FAIL.
labels: labels:
job: loki job: loki
# cAdvisor
- targets: ['cadvisor:8080']
labels:
job: cadvisor
# NVIDIA GPU (DCGM) # NVIDIA GPU (DCGM)
- targets: ['nvidia-exporter:9400'] - targets: ['nvidia-exporter:9400']
labels: labels:
@@ -1049,14 +960,14 @@ uv run pytest tests/test_observability.py::TestPrometheusTargets -v
# Hot-reload (web.enable-lifecycle is on) # Hot-reload (web.enable-lifecycle is on)
docker exec prometheus wget -q --post-data= -O- http://localhost:9090/-/reload docker exec prometheus wget -q --post-data= -O- http://localhost:9090/-/reload
docker exec prometheus wget -q -O- 'http://localhost:9090/api/v1/targets?state=active' | grep -o '"job":"[^"]*"' | sort -u docker exec prometheus wget -q -O- 'http://localhost:9090/api/v1/targets?state=active' | grep -o '"job":"[^"]*"' | sort -u
# expected: cadvisor, nvidia-gpu, tempo, traefik, loki, etc. # expected: nvidia-gpu, tempo, traefik, loki, etc.
``` ```
- [ ] **Step 8.5: Commit** - [ ] **Step 8.5: Commit**
```bash ```bash
git add infra/prometheus/targets/services.yml tests/test_observability.py git add infra/prometheus/targets/services.yml tests/test_observability.py
git commit -m "feat(prom): add cadvisor/nvidia/tempo targets, drop jaeger" git commit -m "feat(prom): add nvidia/tempo targets, drop jaeger"
``` ```
--- ---
@@ -1177,7 +1088,7 @@ PROMTAIL_LABELED = {
"notebooks", "zotero", "webdav", "nessie", "trino", "polaris", "notebooks", "zotero", "webdav", "nessie", "trino", "polaris",
"dashboard", "docs", "api", "mail-poller", "auth-handler", "dashboard", "docs", "api", "mail-poller", "auth-handler",
"oauth2-proxy", "cloudflared", "loki", "promtail", "tempo", "oauth2-proxy", "cloudflared", "loki", "promtail", "tempo",
"cadvisor", "otel-collector", "prometheus", "grafana", "otel-collector", "prometheus", "grafana",
"nvidia-exporter", "nvidia-exporter",
} }
@@ -1240,7 +1151,7 @@ need the entry appended.
Special cases: Special cases:
- `promtail` itself gets `promtail=true` (it scrapes its own logs) - `promtail` itself gets `promtail=true` (it scrapes its own logs)
- `mc` and `wire` (the `tools` profile) get **no** label — see test - `mc` and `wire` (the `tools` profile) get **no** label — see test
- `tempo`, `cadvisor`, `nvidia-exporter` were created in tasks 1–3; add the - `tempo`, `nvidia-exporter` were created in tasks 1–3; add the
label to those service blocks too label to those service blocks too
- [ ] **Step 10.4: Enable Traefik JSON access logs** - [ ] **Step 10.4: Enable Traefik JSON access logs**
@@ -1874,7 +1785,7 @@ Cross-check against the spec sections:
| Spec section | Plan task | | Spec section | Plan task |
|---|---| |---|---|
| Compose changes — add tempo/cadvisor/nvidia-exporter | Tasks 1–3 | | Compose changes — add tempo/nvidia-exporter | Tasks 1–3 |
| Compose changes — remove jaeger | Task 13 | | Compose changes — remove jaeger | Task 13 |
| Compose changes — promtail=true labels | Task 10 | | Compose changes — promtail=true labels | Task 10 |
| Compose changes — Traefik access logs | Task 10 | | Compose changes — Traefik access logs | Task 10 |

View File

@@ -6,7 +6,7 @@
## Goal ## Goal
Port the corwins.media observability approach to the stack repo: replace Jaeger Port the corwins.media observability approach to the stack repo: replace Jaeger
with Tempo, add cadvisor + nvidia-exporter, switch promtail from filesystem with Tempo, add nvidia-exporter, switch promtail from filesystem
log scraping to `docker_sd_configs` with `promtail=true` opt-in, add per-service log scraping to `docker_sd_configs` with `promtail=true` opt-in, add per-service
log pipeline stages tailored to the stack's services, enable Loki retention, log pipeline stages tailored to the stack's services, enable Loki retention,
wire Grafana OAuth via Gitea, and provision six thematic dashboards. wire Grafana OAuth via Gitea, and provision six thematic dashboards.
@@ -28,7 +28,6 @@ wire Grafana OAuth via Gitea, and provision six thematic dashboards.
### Compose changes ### Compose changes
**Add services** (all on `observability` network): **Add services** (all on `observability` network):
- `cadvisor` — container CPU/mem/disk/net metrics, scrapes `/`, `/sys`, docker.sock; runs `privileged: true` to read cgroup data
- `tempo` — OTLP trace backend, replaces Jaeger - `tempo` — OTLP trace backend, replaces Jaeger
- `nvidia-exporter` — DCGM GPU metrics, `runtime: nvidia`, GPU device reservation - `nvidia-exporter` — DCGM GPU metrics, `runtime: nvidia`, GPU device reservation
@@ -43,7 +42,7 @@ wire Grafana OAuth via Gitea, and provision six thematic dashboards.
**Volumes:** add `tempo_data`. Existing `loki_data`, `prometheus_data`, `grafana_data` unchanged. **Volumes:** add `tempo_data`. Existing `loki_data`, `prometheus_data`, `grafana_data` unchanged.
**Networks:** unchanged. `observability` stays `internal: true`. cadvisor, tempo, nvidia-exporter, promtail need only docker.sock + host filesystems, not internet egress. **Networks:** unchanged. `observability` stays `internal: true`. tempo, nvidia-exporter, promtail need only docker.sock + host filesystems, not internet egress.
### Subdomain / route changes ### Subdomain / route changes
- `stack.toml` `subdomains`: replace `"jaeger"` with `"tempo"` - `stack.toml` `subdomains`: replace `"jaeger"` with `"tempo"`
@@ -78,7 +77,6 @@ wire Grafana OAuth via Gitea, and provision six thematic dashboards.
| prometheus | yes | self-monitoring | | prometheus | yes | self-monitoring |
| grafana | yes | self-monitoring | | grafana | yes | self-monitoring |
| otel-collector | yes | self-monitoring | | otel-collector | yes | self-monitoring |
| cadvisor | yes | self-monitoring |
| mc | no | sleep-infinity sidecar, no useful logs | | mc | no | sleep-infinity sidecar, no useful logs |
| wire | no | one-shot bootstrap, profile=tools | | wire | no | one-shot bootstrap, profile=tools |
@@ -271,11 +269,6 @@ Replace traces exporter:
+ job: tempo + job: tempo
+ __metrics_path__: /metrics + __metrics_path__: /metrics
+ +
+# cadvisor
+- targets: ['cadvisor:8080']
+ labels:
+ job: cadvisor
+
+# NVIDIA GPU +# NVIDIA GPU
+- targets: ['nvidia-exporter:9400'] +- targets: ['nvidia-exporter:9400']
+ labels: + labels:
@@ -376,7 +369,6 @@ Six thematic dashboards under `infra/grafana/dashboards/` (auto-loaded by the ex
### 1. `homelab-overview.json` ### 1. `homelab-overview.json`
- **Stat row:** total containers up, total log volume (Loki) /1m, total error rate (Loki `level="error"`) /1m - **Stat row:** total containers up, total log volume (Loki) /1m, total error rate (Loki `level="error"`) /1m
- **Time series:** container CPU% from cadvisor (`rate(container_cpu_usage_seconds_total{container_label_promtail="true"}[1m])`), container memory from cadvisor
- **Logs:** top error sources by container (Loki bar chart) - **Logs:** top error sources by container (Loki bar chart)
### 2. `gateway-auth.json` ### 2. `gateway-auth.json`
@@ -404,7 +396,6 @@ Six thematic dashboards under `infra/grafana/dashboards/` (auto-loaded by the ex
### 6. `gpu-notebooks.json` ### 6. `gpu-notebooks.json`
- **Time series:** GPU utilization, memory used, temperature, power (DCGM `DCGM_FI_DEV_*`) - **Time series:** GPU utilization, memory used, temperature, power (DCGM `DCGM_FI_DEV_*`)
- **Time series:** notebooks + zotero container CPU/mem (cadvisor)
The existing `pipeline-performance.json` is folded into `data-pipelines.json` if its panels overlap; otherwise kept. The existing `pipeline-performance.json` is folded into `data-pipelines.json` if its panels overlap; otherwise kept.
@@ -412,7 +403,7 @@ The existing `pipeline-performance.json` is folded into `data-pipelines.json` if
| Step | Description | Verification | | Step | Description | Verification |
|---|---|---| |---|---|---|
| 1 | Add `tempo`, `cadvisor`, `nvidia-exporter` services. Don't remove jaeger yet. | `docker compose config` parses | | 1 | Add `tempo`, `nvidia-exporter` services. Don't remove jaeger yet. | `docker compose config` parses |
| 2 | Write new `loki-config.yml` (retention/compactor) and `tempo.yml`. | `docker compose up -d loki tempo` healthy | | 2 | Write new `loki-config.yml` (retention/compactor) and `tempo.yml`. | `docker compose up -d loki tempo` healthy |
| 3 | Rewrite `promtail-config.yml` with docker_sd + per-service stages. | promtail container starts; `curl loki:3100/loki/api/v1/labels` shows expected labels | | 3 | Rewrite `promtail-config.yml` with docker_sd + per-service stages. | promtail container starts; `curl loki:3100/loki/api/v1/labels` shows expected labels |
| 4 | Update `otel-collector.yml`: traces → tempo (keep jaeger receiver until step 6). | `curl tempo:3200/ready` returns ready; trace appears in Grafana Explore | | 4 | Update `otel-collector.yml`: traces → tempo (keep jaeger receiver until step 6). | `curl tempo:3200/ready` returns ready; trace appears in Grafana Explore |

View File

@@ -10,8 +10,6 @@
{"id": 1, "title": "GPU utilization %", "type": "timeseries", "gridPos": {"x": 0, "y": 0, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "DCGM_FI_DEV_GPU_UTIL"}]}, {"id": 1, "title": "GPU utilization %", "type": "timeseries", "gridPos": {"x": 0, "y": 0, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "DCGM_FI_DEV_GPU_UTIL"}]},
{"id": 2, "title": "GPU memory used (MiB)", "type": "timeseries", "gridPos": {"x": 12, "y": 0, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "DCGM_FI_DEV_FB_USED"}]}, {"id": 2, "title": "GPU memory used (MiB)", "type": "timeseries", "gridPos": {"x": 12, "y": 0, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "DCGM_FI_DEV_FB_USED"}]},
{"id": 3, "title": "GPU temp (°C)", "type": "timeseries", "gridPos": {"x": 0, "y": 8, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "DCGM_FI_DEV_GPU_TEMP"}]}, {"id": 3, "title": "GPU temp (°C)", "type": "timeseries", "gridPos": {"x": 0, "y": 8, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "DCGM_FI_DEV_GPU_TEMP"}]},
{"id": 4, "title": "GPU power (W)", "type": "timeseries", "gridPos": {"x": 12, "y": 8, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "DCGM_FI_DEV_POWER_USAGE"}]}, {"id": 4, "title": "GPU power (W)", "type": "timeseries", "gridPos": {"x": 12, "y": 8, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "DCGM_FI_DEV_POWER_USAGE"}]}
{"id": 5, "title": "Notebooks/Zotero CPU %", "type": "timeseries", "gridPos": {"x": 0, "y": 16, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "rate(container_cpu_usage_seconds_total{name=~\"notebooks|zotero\"}[1m]) * 100", "legendFormat": "{{name}}"}]},
{"id": 6, "title": "Notebooks/Zotero memory", "type": "timeseries", "gridPos": {"x": 12, "y": 16, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "container_memory_working_set_bytes{name=~\"notebooks|zotero\"} / 1024 / 1024", "legendFormat": "{{name}}"}]}
] ]
} }

View File

@@ -7,11 +7,8 @@
"time": {"from": "now-6h", "to": "now"}, "time": {"from": "now-6h", "to": "now"},
"refresh": "30s", "refresh": "30s",
"panels": [ "panels": [
{"id": 1, "title": "Containers up", "type": "stat", "gridPos": {"x": 0, "y": 0, "w": 4, "h": 4}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "count(container_last_seen{name!=\"\"})"}]}, {"id": 2, "title": "Log volume / 1m", "type": "stat", "gridPos": {"x": 0, "y": 0, "w": 6, "h": 4}, "datasource": {"uid": "loki"}, "targets": [{"expr": "sum(rate({container=~\".+\"}[1m]))"}]},
{"id": 2, "title": "Log volume / 1m", "type": "stat", "gridPos": {"x": 4, "y": 0, "w": 4, "h": 4}, "datasource": {"uid": "loki"}, "targets": [{"expr": "sum(rate({container=~\".+\"}[1m]))"}]}, {"id": 3, "title": "Error rate / 1m", "type": "stat", "gridPos": {"x": 6, "y": 0, "w": 6, "h": 4}, "datasource": {"uid": "loki"}, "targets": [{"expr": "sum(rate({level=\"error\"}[1m]))"}]},
{"id": 3, "title": "Error rate / 1m", "type": "stat", "gridPos": {"x": 8, "y": 0, "w": 4, "h": 4}, "datasource": {"uid": "loki"}, "targets": [{"expr": "sum(rate({level=\"error\"}[1m]))"}]}, {"id": 6, "title": "Top error sources (1h)", "type": "logs", "gridPos": {"x": 0, "y": 4, "w": 24, "h": 8}, "datasource": {"uid": "loki"}, "targets": [{"expr": "{level=\"error\"} | json"}]}
{"id": 4, "title": "Container CPU %", "type": "timeseries", "gridPos": {"x": 0, "y": 4, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "rate(container_cpu_usage_seconds_total{name!=\"\"}[1m]) * 100", "legendFormat": "{{name}}"}]},
{"id": 5, "title": "Container memory (MiB)", "type": "timeseries", "gridPos": {"x": 12, "y": 4, "w": 12, "h": 8}, "datasource": {"uid": "prometheus"}, "targets": [{"expr": "container_memory_working_set_bytes{name!=\"\"} / 1024 / 1024", "legendFormat": "{{name}}"}]},
{"id": 6, "title": "Top error sources (1h)", "type": "logs", "gridPos": {"x": 0, "y": 12, "w": 24, "h": 8}, "datasource": {"uid": "loki"}, "targets": [{"expr": "{level=\"error\"} | json"}]}
] ]
} }

View File

@@ -19,11 +19,6 @@
labels: labels:
job: loki job: loki
# cAdvisor
- targets: ['cadvisor:8080']
labels:
job: cadvisor
# NVIDIA GPU (DCGM) # NVIDIA GPU (DCGM)
- targets: ['nvidia-exporter:9400'] - targets: ['nvidia-exporter:9400']
labels: labels:

View File

@@ -136,7 +136,6 @@ class TestSecurityOpts:
"docs", # static site "docs", # static site
"promtail", # needs host log access "promtail", # needs host log access
"cloudflared", # tunnel agent "cloudflared", # tunnel agent
"cadvisor", # privileged: true for host metrics
"nvidia-exporter", # upstream dcgm-exporter, GPU runtime + SYS_ADMIN "nvidia-exporter", # upstream dcgm-exporter, GPU runtime + SYS_ADMIN
} }
compose = _load_compose() compose = _load_compose()

View File

@@ -42,26 +42,6 @@ class TestTempo:
assert any("./infra/tempo/tempo.yml" in v for v in mounts) assert any("./infra/tempo/tempo.yml" in v for v in mounts)
class TestCadvisor:
def test_cadvisor_service_present(self):
svcs = _services()
assert "cadvisor" in svcs
def test_cadvisor_privileged(self):
# cadvisor needs privileged for cgroup reads
assert _services()["cadvisor"].get("privileged") is True
def test_cadvisor_mounts(self):
svc = _services()["cadvisor"]
sources = []
for v in svc["volumes"]:
if isinstance(v, str):
sources.append(v.split(":")[0])
# rootfs, sys, /dev/disk needed for resource introspection
assert any(s == "/" for s in sources)
assert any(s == "/sys" for s in sources)
class TestNvidiaExporter: class TestNvidiaExporter:
def test_nvidia_exporter_present(self): def test_nvidia_exporter_present(self):
svcs = _services() svcs = _services()
@@ -155,7 +135,6 @@ class TestPrometheusTargets:
targets = yaml.safe_load(path.read_text()) targets = yaml.safe_load(path.read_text())
jobs = {entry["labels"]["job"] for entry in targets if "labels" in entry} jobs = {entry["labels"]["job"] for entry in targets if "labels" in entry}
assert "tempo" in jobs assert "tempo" in jobs
assert "cadvisor" in jobs
assert "nvidia-gpu" in jobs assert "nvidia-gpu" in jobs
assert "jaeger" not in jobs assert "jaeger" not in jobs
@@ -195,7 +174,6 @@ PROMTAIL_LABELED = {
"loki", "loki",
"promtail", "promtail",
"tempo", "tempo",
"cadvisor",
"otel-collector", "otel-collector",
"prometheus", "prometheus",
"grafana", "grafana",