Skip to content

Controller-manager metrics #247

Description

@zolug

Sub-issue of #236 (item 2: "Controller-manager metrics — gateway count/programmed,
DG endpoints/max/ready"). Follows the #153 study and the architectural approach
prescribed in #236.

Scope

Expose Prometheus metrics for the controller-manager describing the Gateway and
DistributionGroup state it manages. Cache-backed, lazy/pull-based collection per
#236's preferred pattern (an authoritative external source — the informer cache —
exists, so no push-style accumulation is needed).

Metrics

Metric Labels Meaning
<prefix>_gateway_count Gateways with Accepted=True managed by this controller
<prefix>_gateway_programmed gateway, namespace 0/1 per Gateway, from the Programmed condition
<prefix>_distributiongroup_ready dg, namespace 0/1 per DG, from the Ready condition
<prefix>_distributiongroup_endpoints dg, gateway, namespace, gateway_namespace endpoint count per DG per Gateway
<prefix>_distributiongroup_max_endpoints dg, gateway, namespace, gateway_namespace capacity per DG per Gateway (+Inf if unbounded)

Approach (per #236)

  • Lazy collectors on controller-runtime's metrics.Registry, reading the
    informer cache on scrape — never from the reconcile path.
  • kube-state-metrics label conventions: metric name = subject kind, labels =
    object identity; separate namespace/gateway_namespace so all-namespace
    watches don't collide identically-named objects. No per-controller label
    (instance identity belongs on the scrape target).
  • Enabled-gating (Implement Meridio-2 metrics #236 requirement): nothing registered and no instrumentation
    runs when --metrics-bind-address == "0".
  • Prefix: --metrics-prefix (default meridio_2), validated at startup.
  • Cache-sync gate: a scrape before the informer cache has synced fails fast
    with a single error rather than blocking or emitting a partial set. Collect
    has no context, so --metrics-collect-timeout (default 5s, below Prometheus's
    10s scrape_timeout) bounds the wait.
  • The subprocess/netlink safety requirements in Implement Meridio-2 metrics #236 (mutex-serialized Collect,
    per-call timeouts) do not apply here — these collectors are cache-backed, the
    carve-out Implement Meridio-2 metrics #236 calls out explicitly.

Prep / refactor (landed alongside)

Shared Gateway/DG helpers extracted into internal/common/gatewayutil
(IsGatewayAcceptedByController, IsGatewayProgrammed) and DistributionGroup
Gateway/route resolution de-methodized, so collectors reuse the exact reconciler
semantics without depending on the controller packages. No behavior change.

Open question — distributiongroup_ready semantics

Neither #153 nor #236 specifies what "ready" means for a DistributionGroup, so the
collector reports the existing DG Ready condition as-is. Today that condition means
"the DG has assigned endpoints" (len(desiredSlices) > 0), not "the DG has
endpoints ready to serve traffic" — per-endpoint LoadBalancerEndpoint.Ready is not
consulted (buildReadyCondition in distributiongroup/status.go). The collector
deliberately does not invent a second, metrics-only readiness under the same name.
Whether the Ready condition itself should account for per-endpoint readiness is a
DistributionGroup reconciler design decision — flagging here to decide whether the
metric's current meaning is acceptable or should track a readiness redesign.

Deployment (remaining)

--metrics-bind-address defaults to "0" (disabled) by design (#236); the endpoint,
secure filter, and opt-in are already wired in the binary. What remains is enabling
and validating the in-cluster scrape path (much of the config/ scaffolding
already exists — Service, ServiceMonitor, metrics RBAC, cert-manager patches):

  • opt the manager Deployment into --metrics-bind-address + container port
  • metrics Service port name matches the ServiceMonitor's expected port
  • scraper RBAC (metrics-reader / auth) verified end-to-end
  • wire config/prometheus/monitor.yaml with the Prometheus Operator
  • validate secure serving (cert-manager TLS) + a real Prometheus scrape (e.g. in Kind)

Testing

  • Unit tests: cache-sync gate, prefix validation, collector registration.
  • Local go run smoke test against Kind validated all metrics and both label
    branches; recipe in docs/development/metrics-testing.md.
  • go build ./..., package tests, make lint all clean.

Refs #236, #153

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions