Skip to content

Metrics

The operator serves /metrics on TCP 8080 (chart ServiceMonitor), each agent and gateway pod on TCP 9080 (chart PodMonitor). Collectors observe persisted status only — never messages, credentials, peer addresses or dynamic Headscale paths. How to read them in practice: Metric interpretation .

Operator

MetricTypeLabelsMeaning
tailnet_resource_readygaugekind, namespace, name, tailnetCurrent-generation Ready condition is True; absent without a current Ready condition (Tailnet has none; suspended gateways are withdrawn).
tailnet_resource_conditiongaugekind, namespace, name, type, reason1 for the current-generation reason of each condition (including False and Unknown); previously observed reasons are 0. Read type and reason, not the value as a boolean.
tailnet_egress_target_stategaugenamespace, name, target, reasonCurrent-generation target route reason; Present represents an empty successful route reason.
tailnet_ingress_expose_reachablegaugenamespace, name, exposeCurrent-generation expose backend reachability.
tailnet_node_onlinegaugekind, namespace, name1 when a successful Headscale node list contains an online node matching this resource’s tag and hostname; absent without a current observation.
tailnet_node_last_seen_secondsgaugekind, namespace, nameUnix timestamp of Headscale lastSeen for the matching node; absent when unknown. Use time() - … for the age.
tailnet_headscale_user_conflictsgaugetailnetHeadscale user names carried by more than one user (status.userConflicts); anything above 0 makes Headscale reject every policy write. Absent without a current UsersUnique verdict.
tailnet_policy_pendinggaugetailnet1 only in Apply mode while a non-empty renderedHash differs from appliedHash; 0 otherwise. Absent without policy status.
tailnet_policy_generatedgaugetailnet, kindGenerated entries in the persisted policy status (kind ∈ tags, grants, routes).
tailnet_policy_applied_timestamp_secondsgaugetailnetUnix time the rendered policy was last applied to the control server. An old value alone is healthy.
tailnet_policy_apply_errors_totalcountertailnetPolicy writes the control server rejected or that failed.
tailnet_policy_write_duration_secondshistogramtailnetSetPolicy latency including failures.
tailnet_route_approvals_replayed_totalcountertailnetRoutes successfully approved by replay — counted per route, not per request, so one batch adds several.
tailnet_headscale_api_requests_totalcountertailnet, method, path_template, codeHeadscale operations; paths are bounded templates, code 0 means no HTTP response (transport failure).
tailnet_headscale_api_duration_secondshistogramtailnet, method, path_template, codeHeadscale operation latency including failures.
tailnet_apikey_expires_secondsgaugetailnetSeconds until the operator’s working API key expires; negative once expired.
tailnetegress_authkey_expires_secondsgaugenamespace, nameSeconds until a TailnetEgress pre-auth key expires.
tailnetingress_authkey_expires_secondsgaugenamespace, nameSeconds until a TailnetIngress pre-auth key expires.
tailnetegress_routes_missinggaugenamespace, nameDeprecated (kept through v0.4.x): use tailnet_egress_target_state. Target routes missing from the egress netmap.
tailnetingress_backends_unreachablegaugenamespace, nameDeprecated (kept through v0.4.x): use tailnet_ingress_expose_reachable. Backends an ingress agent could not reach.

The controller-runtime families (controller_runtime_reconcile_errors_total, …) and the Go runtime families are exported as well; the bundled alerts use controller_runtime_reconcile_errors_total and up.

Agents (egress, ingress) and gateways

MetricTypeLabelsMeaning
tailnet_agent_connections_activegaugetarget, exposeOpen client TCP connections assigned to a target; HTTP assignment begins at a recognized SNI.
tailnet_agent_bytes_totalcountertarget, expose, directionBytes on target-assigned client connections (to_target / from_target); HTTP counts after the recognized SNI, including TLS wire overhead.
tailnet_agent_dial_duration_secondshistogramtarget, exposeUpstream TCP dial duration, including failed dials and health probes.
tailnet_agent_http_unattributed_connections_activegauge—Open HTTP connections without a recognized SNI (HTTP listeners only).
tailnet_agent_http_unattributed_bytes_totalcounterdirectionTLS wire bytes before a recognized SNI, including rejected handshakes.

Labels carry target and expose names, never peers or IP addresses. A TailnetGateway pod additionally exposes the Tailscale sidecar’s own metrics on TCP 8080 and the CoreDNS metrics on TCP 9153; the chart PodMonitor scrapes all three.

Source: docs/reference/metrics.md at v0.18.0 — found a mistake? Tell us.