Skip to content

Metrics

VictoriaMetrics k8s stack

observability/base/victoria-metrics-k8s-stack/ deploys the victoria-metrics-k8s-stack chart (0.91.0) — the kube-prometheus-stack equivalent: VictoriaMetrics itself, vmagent, Alertmanager, a bundled Grafana subchart, and the default recording/alerting rule set. Only vmsingle is active; vmcluster sits in the same directory, fully valued, commented out of kustomization.yaml.

vmsingle (active)vmcluster (standby)
Retention1d — explicitly commented “Minimal retention, for tests only”10d
ReplicationreplicaCount: 1replicationFactor: 2, separate vmstorage/vmselect/vminsert with zone-aware anti-affinity
Storage10Gi RWO10Gi (vmstorage) + 2Gi (vminsert/vmselect) gp3
AlertmanagerreplicaCount unset (chart default)replicaCount: 2

mycluster-0’s overlay (observability/mycluster-0/victoria-metrics-k8s-stack/kustomization.yaml) adds no patches — it’s a pure passthrough to the base. Common values shared by both modes (vm-common-helm-values-configmap.yaml, applied via valuesFrom) disable the control-plane rule groups (kubernetes-system-apiserver, -controller-manager, -scheduler) — EKS runs these as a managed service this cluster can’t scrape, so the chart’s default absent()-based *Down alerts would otherwise fire permanently — and disable kubeProxy scraping for the same reason Cilium replaces it.

1d retention on the active vmsingle is a real operational constraint, not a typo to “fix”: anything you want to compare against last week is gone. Cluster mode’s 10d retention is one kustomization.yaml edit away if that becomes a problem, not a re-architecture.

metrics-server

observability/base/metrics-server/ runs the standard metrics-server chart (3.14.0) — but into kube-system, not observability, since it backs kubectl top and HPA Resource metrics cluster-wide. Non-default configuration worth knowing:

  • replicas: 2 with a PodDisruptionBudget (maxUnavailable: 1) and hostname anti-affinity — HA by default, not a single point of failure for every HPA in the cluster.
  • args: [--kubelet-insecure-tls] — required on EKS; the kubelet serving certificate isn’t signed by a CA metrics-server trusts otherwise.
  • serviceMonitor.enabled: true with additionalLabels.prometheus: victoria-metrics-k8s-stack so vmagent picks it up.

Scrape mechanisms

Three CRDs from the VictoriaMetrics Operator cover how targets get discovered, each used somewhere in this repo:

VMServiceScrape — the ServiceMonitor equivalent, scrapes a Service’s endpoints. Most charts in this repo render their own via a vmServiceScrape.enabled: true value (runlore, victoria-traces, victoria-logs, victoria-metrics-k8s-stack itself); a few are authored directly, e.g. observability/base/victoria-metrics-k8s-stack/vmservicecrapes/karpenter.yaml scrapes the karpenter namespace’s http-metrics port (Karpenter isn’t part of this stack, but its metrics land in the same VictoriaMetrics — the directory name carries an upstream typo, vmservicecrapes, not vmservicescrapes).

VMScrapeConfig — for targets that aren’t a Kubernetes Service at all. Two examples in vmscrapeconfigs/:

# observability/base/victoria-metrics-k8s-stack/vmscrapeconfigs/openbao.yaml
staticConfigs:
  - targets:
      - "bao.${private_domain_name}:8200"
    labels:
      job: openbao
scheme: HTTPS
tlsConfig:
  ca:
    secret:
      name: openbao-ca
      key: ca.crt
  serverName: "bao.${private_domain_name}"
path: /v1/sys/metrics

OpenBao is scraped by DNS name over HTTPS with a real CA, not EC2 service discovery — the instance security group only admits the internal NLB on 8200, and the server certificate carries a single DNS SAN, so scraping individual instance IPs could never verify TLS. ec2.yaml in the same directory is the EC2-SD counterpart, used for node-exporter (tag observability:node-exporter=true, port 9100) where per-instance scraping is fine.

VMPodMonitor — scrapes Pods directly rather than through a Service. Not currently used by any component in this repo; if you add one, it renders the same way VMServiceScrape does.

Example queries

Written against metrics this cluster actually exposes, not generic placeholders:

# RunLore agent missing entirely (real alert: RunloreAgentDown)
absent(runlore_build_info)

# CloudNativePG: call volume by database, from the query-performance dashboard
sum by (database) (rate(cnpg_pg_stat_statements_calls[5m]))

# RunLore model-request p95 latency (real alert: RunloreModelLatencyHigh)
histogram_quantile(0.95, sum(rate(runlore_model_request_duration_seconds_bucket[15m])) by (le))

The first two are drawn directly from observability/base/victoria-metrics-k8s-stack/vmrules/runlore.yaml and infrastructure/base/cloudnative-pg/grafana-dashboard-query-performance.yaml. Standard cAdvisor/kube-state-metrics queries (container_cpu_usage_seconds_total, kube_pod_status_phase, and similar) also work unchanged — they come from the bundled kube-state-metrics/node-exporter subcharts, not from anything specific to this repo.

No CiliumNetworkPolicy exists in victoria-metrics-k8s-stack/ or metrics-server/ for either component. Of the nine observability component directories, only runlore ships one — see Dashboards & Alerts for the CiliumNetworkPolicy it does define, and for the CiliumClusterwideNetworkPolicy that isn’t a default-deny (it only allows the Gateway API L7 proxy).