You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
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.
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
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
<prefix>_gateway_countAccepted=Truemanaged by this controller<prefix>_gateway_programmedgateway,namespaceProgrammedcondition<prefix>_distributiongroup_readydg,namespaceReadycondition<prefix>_distributiongroup_endpointsdg,gateway,namespace,gateway_namespace<prefix>_distributiongroup_max_endpointsdg,gateway,namespace,gateway_namespace+Infif unbounded)Approach (per #236)
metrics.Registry, reading theinformer cache on scrape — never from the reconcile path.
object identity; separate
namespace/gateway_namespaceso all-namespacewatches don't collide identically-named objects. No per-controller label
(instance identity belongs on the scrape target).
runs when
--metrics-bind-address == "0".--metrics-prefix(defaultmeridio_2), validated at startup.with a single error rather than blocking or emitting a partial set.
Collecthas no context, so
--metrics-collect-timeout(default 5s, below Prometheus's10s
scrape_timeout) bounds the wait.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 DistributionGroupGateway/route resolution de-methodized, so collectors reuse the exact reconciler
semantics without depending on the controller packages. No behavior change.
Open question —
distributiongroup_readysemanticsNeither #153 nor #236 specifies what "ready" means for a DistributionGroup, so the
collector reports the existing DG
Readycondition as-is. Today that condition means"the DG has assigned endpoints" (
len(desiredSlices) > 0), not "the DG hasendpoints ready to serve traffic" — per-endpoint
LoadBalancerEndpoint.Readyis notconsulted (
buildReadyConditionindistributiongroup/status.go). The collectordeliberately does not invent a second, metrics-only readiness under the same name.
Whether the
Readycondition itself should account for per-endpoint readiness is aDistributionGroup 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-addressdefaults 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/scaffoldingalready exists — Service, ServiceMonitor, metrics RBAC, cert-manager patches):
--metrics-bind-address+ container portServiceport name matches the ServiceMonitor's expected portconfig/prometheus/monitor.yamlwith the Prometheus OperatorTesting
go runsmoke test against Kind validated all metrics and both labelbranches; recipe in
docs/development/metrics-testing.md.go build ./..., package tests,make lintall clean.Refs #236, #153