Files
homelab-infra/platform/observability/README.md
T
2026-09-16 15:53:00 +00:00

187 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# observability
Metrics, logs, and traces for the cluster — one VictoriaMetrics-ecosystem stack,
operator-driven, running in the `monitoring` namespace. Replaces the standalone
Docker Compose monitoring stack. The retired stack and its three Docker data volumes
were removed on 2026-09-16 with the maintainer's explicit approval.
## Grafana 当前入口(2026-09-16)
统一使用 <https://grafana.ad.ddupan.top>,A 记录指向 `192.168.10.127`,由共享
Envoy Gateway 的 `https` listener 与 `*.ad.ddupan.top` 证书提供 TLS。
Grafana root_url 和 Authelia 回调均使用此域名;旧专用 Tailscale Ingress 已停用。
远程客户端仍需有到 LAN 的路由及已配置的内网 DNS 转发。
内存看板:`/d/homelab-memory`;采集配置及 AppArmor 规则见
[主机与进程内存采集](metrics/exporters/README.md)。
Grafana 由 Flux 管理;修改 values 后通过 Git 合并触发 HelmRelease,避免现场 Helm
修改被漂移检测回滚。Authelia 当前不由 Flux 管理,需单独 Helm upgrade 并先结构比较
live values。迁移时先添加 DNS 和回调,再切换 Grafana。Recreate 策略会短暂中断访问,
但保留原 PVC、用户、看板和数据源。回滚需同时恢复 root_url、回调和 Ingress 配置。
## 初始部署记录(2026-07-10)
Live and verified in the `monitoring` namespace (operator chart 0.66.2):
metrics (data queryable), logs (pods ingesting), traces (VTSingle CRD, verified via
Jaeger API), Grafana (3 datasources healthy, VM dashboard loaded, Tailscale ingress
`grafana.tail7e769.ts.net`, Authelia OIDC client registered). All PVCs on
`localpv-zfs-ceph`. Note the vmagent hot-reload RBAC fix (`metrics/reload-rbac.yaml`,
see `metrics/README-reload.md`) and that VL/VT CRDs are served under `.../v1`.
### Flux 接管状态
可观测性栈使用一个 `observability` Flux Kustomization,按依赖顺序逐步加入 Operator、
Metrics、Logs、Traces 和 Grafana,避免多个 reconciler 争夺共享 namespace、Helm source
或 VictoriaMetrics CRD。brownfield 迁移期间保持 `prune: false`。
VictoriaMetrics Operator 已固定 chart `0.66.2` / app `v0.73.1` 完成分阶段 Flux
HelmRelease 接管,保存 values 与 `operator/values.yaml` 一致。阶段一确认 Helm revision
保持为 2、Operator Pod UID 未变、24 个 CRD 及 6 个核心 VM/VL/VT CR 未变化;随后
通过独立 PR 解除暂停。
其余已部署资源也已统一完成接管:Metrics CR、rules、scrapes、node-exporter,Logs 的
VLSingle 与固定 `0.3.6` 的 Collector,以及 Traces 的 VTSingle、OTel Collector,最后是
固定 `10.5.15` 的 Grafana 与 dashboard ConfigMap。阶段一确认 11 个 Pod UID、4 个 PVC、
6 个核心 CR、17 个 rule/scrape 对象及 dashboard 哈希均未变化,Collector 和 Grafana
Helm revision 均保持为 1;随后在同一独立 PR 中解除两个 HelmRelease 的暂停。
首次 Grafana Helm reconcile 暴露了本地 ZFS RWO 卷限制:chart 默认 `RollingUpdate`
会先创建新 Pod,但 CSI 拒绝在旧 Pod 仍挂载 PVC 时再次 mount,使 upgrade 卡在
`pending-upgrade`。`grafana/values.yaml` 因此显式使用 `deploymentStrategy.type: Recreate`。
Grafana 升级会有一次短暂停机,但旧 Pod 会先退出,新 Pod 才挂载同一 PVC;不要改回
RollingUpdate,除非存储改为真正支持并发挂载的 RWX。
以下内容明确不属于本批接管:尚未部署的 kube-state-metrics、`vlogs-ingress.yaml`,以及
仅作 standalone chart 参考的 `traces-values.yaml`。`grafana/oidc-secret.yaml` 是不含真实
值的占位模板;live `grafana-oidc` Secret 继续只被 HelmRelease 引用,尚未由 OpenBao/ESO
纳管。
Still host-side (not yet done): deploy `docker-hosts/compose.yaml` on the Docker
hosts and `logs/vlogs-ingress.yaml` to push their logs.
## Decision
| Pillar | Choice | Why |
| -------- | ----------------------------- | --- |
| Metrics | **VictoriaMetrics** (VMSingle)| already in use; keep it |
| Logs | **VictoriaLogs** (VLSingle) | same vendor/operator, tiny footprint, LogsQL |
| Traces | **VictoriaTraces** + OTel Collector | no extra storage deps, OTLP in, Jaeger query API |
| Collect | vmagent (metrics), vlagent (logs), OTel Collector (traces) | native to each backend |
| Visualize| **Grafana**, one instance, 3 datasources | single pane |
| Manage | **victoria-metrics-operator** | VMSingle/VMAgent/VMAlert/VMAlertmanager/VMRule **and** VLSingle as CRDs |
| Expose | **Tailscale ingress** (private) + **Authelia OIDC** | admin tool: private + SSO |
VictoriaMetrics Operator 的 Prometheus converter 已启用;官方
`prometheus-operator-crds` chart 由 `operator/` 一并管理。因此应用 chart 可以原生
声明 `ServiceMonitor`、`PodMonitor` 或 `PrometheusRule`,再由 converter 转换为对应
VM 资源,不需要每个应用额外维护一份 `VM*Scrape`。
## Architecture
```
Grafana (grafana.<tailnet>.ts.net, Authelia OIDC)
├── VictoriaMetrics datasource → VMSingle ← vmagent (k8s SD, node-exporter, kubelet/cAdvisor, KSM)
├── VictoriaLogs datasource → VLSingle ← vlagent DaemonSet (pod logs)
└── Jaeger datasource → VictoriaTraces ← OTel Collector (OTLP 4317/4318) ← apps
VMAlert (VMRules) → VMAlertmanager
```
## Layout
```
observability/
namespace.yaml monitoring namespace
operator/ victoria-metrics-operator (Helm)
metrics/
vmsingle|vmagent|vmalert|vmalertmanager.yaml core CRs
rules/ VMRules migrated from the retired Compose stack (source in Git history)
exporters/ node-exporter (+VMNodeScrape), kube-state-metrics (Helm)
scrapes/ kubelet + cAdvisor VMNodeScrapes
logs/ VLSingle CR + victoria-logs-collector (Helm)
traces/ victoria-traces-single (Helm) + OTel Collector
grafana/ Grafana (Helm) values, OIDC secret, install script
docker-hosts/ per-Docker-host sidecar (cAdvisor + node-exporter + Vector)
```
## Docker hosts
The Compose services on Docker hosts (`../../apps/vlmcsd`, `../../apps/ps3netsrv`, `../../apps/netboot`, ...)
are monitored too:
- **Metrics — pull, nothing exposed.** Each host runs `docker-hosts/compose.yaml`
(cAdvisor `:8080` + node-exporter `:9100`). The cluster's vmagent scrapes their LAN
IPs via `metrics/scrapes/docker-hosts.yaml` (VMStaticScrape). VMSingle stays private.
- **Logs — push over the tailnet.** A **Vector** container per host tails the Docker
socket and ships to VictoriaLogs' Elasticsearch-bulk endpoint, exposed privately as
`vlogs.<tailnet>.ts.net` by `logs/vlogs-ingress.yaml`.
Deploy:
```bash
# cluster side (once): expose VictoriaLogs ingest + register the scrape
kubectl apply -f logs/vlogs-ingress.yaml -f metrics/scrapes/docker-hosts.yaml
# on each Docker host:
cd docker-hosts
cp .env.example .env # set HOST_LABEL and confirm VLOGS_ENDPOINT (tailnet FQDN)
docker compose up -d
# then add the host's IP to metrics/scrapes/docker-hosts.yaml and re-apply
```
Note: cAdvisor uses host port `8080` — remap it (and the scrape target) if taken.
## Deploy order
```bash
# 1. Operator (installs CRDs) + namespace
cd operator && ./helm.sh && cd ..
# 2. Metrics: core CRs, rules, scrapes, exporters
kubectl apply -f metrics/vmsingle.yaml -f metrics/vmagent.yaml \
-f metrics/vmalert.yaml -f metrics/vmalertmanager.yaml
kubectl apply -f metrics/rules/ -f metrics/scrapes/
kubectl apply -f metrics/exporters/node-exporter.yaml
metrics/exporters/kube-state-metrics.sh # needs Prometheus CRDs; see the script
# 3. Logs
cd logs && ./helm.sh && cd ..
# 4. Traces
cd traces && ./helm.sh && cd ..
# 5. Grafana (create the OIDC secret first — see grafana/oidc-secret.yaml)
cd grafana && ./helm.sh && cd ..
```
## Before it works — required edits
- **OIDC secret pair.** Generate once:
`authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length 72`
- plaintext → the `grafana-oidc` Secret (create imperatively, don't commit)
- hash → `authelia/values.yaml` grafana client `client_secret`, then `helm upgrade` Authelia.
- **Tailnet FQDN.** This scaffold assumes `grafana.tail7e769.ts.net` (your existing tailnet,
per `seaweedfs-admin`). If the operator assigns a different name, update it in
`grafana/values.yaml` (`root_url`) **and** the Authelia grafana `redirect_uris`.
- **Chart value names.** `logs/collector-values.yaml` and `traces/traces-values.yaml` note a
`helm show values` check — verify the keys against the installed chart versions.
- **Pin chart + image versions** after first install (all `helm.sh` scripts note this;
`otel-collector.yaml` pins the collector image — bump to current).
## Follow-ups
- Dashboards: the VictoriaMetrics single-node board is migrated to
`grafana/dashboards/victoriametrics.json`; `grafana/dashboards/apply.sh` loads it via
the Grafana sidecar. (The old `vmagent.json`/`vmalert.json` were empty dirs Docker
auto-created, not real boards.) Add the canonical ones by dropping their JSON in
`grafana/dashboards/` and re-running the script — vmagent (gnetId 12683),
vmalert (14950), node-exporter (1860), cAdvisor now that those exporters exist.
- Wire real Alertmanager receivers in `metrics/vmalertmanager.yaml` (email via
`../../apps/smtp-relay/`), replacing the ported `blackhole`.
- 旧 Compose 监控栈已于 2026-09-16 按维护者要求清理:原先已无容器,本次移除
旧配置及 `victoriametrics_vmdata`、`victoriametrics_vmagentdata`、
`victoriametrics_grafanadata` 三个无引用 Docker 卷。没有创建备份或迁移旧数据,
Kubernetes 监控资源未修改。旧配置仍可从 Git 历史查阅,旧卷中的数据已删除。
- Add app instrumentation: point `OTEL_EXPORTER_OTLP_ENDPOINT` at
`otel-collector.monitoring.svc:4317`.