3937b4f366
Deploys the whole stack into the observability namespace of the local cluster with Kustomize alone — no helm install, no dashboard created by hand in the UI. The Makefile carries every command: deploy, dashboards, diagnostics, PVC flush, teardown. Dashboards are files, never UI objects. Each carries a stable uid, which is what keeps URLs, cross-links and alerts alive across redeployments, and references datasources by stable uid rather than by name. The dashboard ConfigMap is generated without a name-suffix hash so applying it updates it in place and Grafana reloads without a restart, while the provisioning ConfigMaps keep their hash precisely so that a change there does force one. Prometheus scrapes the kubelet /metrics/resource endpoint rather than /metrics/cadvisor: on this cluster cadvisor exposes machine_* series only and no container_* at all, which would leave every CPU and memory panel empty. Alloy ships every pod's logs to Loki through the Kubernetes API, so no /var/log mount is needed. Tempo's metrics_generator feeds span metrics and the service graph back into Prometheus, and the datasources are wired so a log line's trace_id opens the matching trace. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
67 lines
1.6 KiB
Plaintext
67 lines
1.6 KiB
Plaintext
// Grafana Alloy -- ships the logs of every pod in the cluster to Loki.
|
|
// Reads through the Kubernetes API (no /var/log mount required).
|
|
|
|
logging {
|
|
level = "info"
|
|
format = "logfmt"
|
|
}
|
|
|
|
discovery.kubernetes "pods" {
|
|
role = "pod"
|
|
}
|
|
|
|
discovery.relabel "pod_logs" {
|
|
targets = discovery.kubernetes.pods.targets
|
|
|
|
rule {
|
|
source_labels = ["__meta_kubernetes_namespace"]
|
|
target_label = "namespace"
|
|
}
|
|
rule {
|
|
source_labels = ["__meta_kubernetes_pod_name"]
|
|
target_label = "pod"
|
|
}
|
|
rule {
|
|
source_labels = ["__meta_kubernetes_pod_container_name"]
|
|
target_label = "container"
|
|
}
|
|
rule {
|
|
source_labels = ["__meta_kubernetes_pod_node_name"]
|
|
target_label = "node"
|
|
}
|
|
rule {
|
|
source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_name"]
|
|
target_label = "app"
|
|
}
|
|
rule {
|
|
source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_component"]
|
|
target_label = "component"
|
|
}
|
|
// job = <namespace>/<container>: the usual Loki convention.
|
|
rule {
|
|
source_labels = ["__meta_kubernetes_namespace", "__meta_kubernetes_pod_container_name"]
|
|
separator = "/"
|
|
target_label = "job"
|
|
}
|
|
// Only collect containers on the current node (DaemonSet).
|
|
rule {
|
|
source_labels = ["__meta_kubernetes_pod_node_name"]
|
|
regex = env("HOSTNAME_NODE")
|
|
action = "keep"
|
|
}
|
|
}
|
|
|
|
loki.source.kubernetes "pods" {
|
|
targets = discovery.relabel.pod_logs.output
|
|
forward_to = [loki.write.default.receiver]
|
|
}
|
|
|
|
loki.write "default" {
|
|
endpoint {
|
|
url = "http://loki:3100/loki/api/v1/push"
|
|
}
|
|
external_labels = {
|
|
cluster = "orbstack",
|
|
}
|
|
}
|