helm/v2-alpha: the generated chart exposes metrics values the manager never receives
Summary
The chart the helm/v2-alpha plugin generates always writes a metrics section
into values.yaml and always scaffolds the metrics Service, the ServiceMonitor
and the metrics RBAC when the project has a metrics Service. But the manager
Deployment only receives the metrics arguments when the project's own manager
already carried a --metrics-bind-address.
For every other project the chart offers metrics.enabled, metrics.port and
metrics.secure, and none of the three reaches the manager. The chart says one
thing and the workload it installs does another.
Where it comes from
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/templater/appliers/manager.go,
in templateControllerManagerArgs:
if metricsLine != "" {
...
builder.WriteString("{{- if .Values.metrics.enabled }}\n")
builder.WriteString(metricsLine)
...
}metricsLine is the project's own --metrics-bind-address line. When the
project has none, the whole block is skipped: no bind address, no
--metrics-secure=false, and no {{- else }} branch to turn metrics off.
The values are written independently of that. metrics.enabled comes from a
*-metrics-service existing in the kustomize output, not from the manager's
arguments, so it can be true for a manager that receives nothing.
What happens today
The scaffolded cmd/main.go declares:
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", ...)0 disables the metrics server, so a manager that receives no bind address
serves no metrics at all.
| The project's manager runs with | values.yaml says | The rendered manager gets | Result |
|---|---|---|---|
--metrics-bind-address=:8443 |
enabled: true, port: 8443, secure: true |
the templated block | correct |
--metrics-secure=false, no bind address |
enabled: true, port: 8443, secure: false |
nothing | the Service, the ServiceMonitor and the http port name are all rendered for plain HTTP metrics, and the manager serves none |
| neither argument | enabled: true, port: 8443, secure: true |
nothing | the whole metrics stack is installed around a manager that never starts a metrics server |
| metrics Service on 7443, no bind address | enabled: true, port: 7443, secure: true |
nothing | same, and metrics.port is advertised but unused |
In the last three rows, setting metrics.enabled, metrics.port or
metrics.secure at install time changes the Service, the ServiceMonitor and the
RBAC, and changes nothing about the manager.
Why it matters
A chart user has no way to turn the metrics endpoint on, off, or onto plain HTTP
for these projects, even though the chart presents all three settings. The
--metrics-secure=false case is the sharpest: the project asked for plain HTTP
metrics, the chart records secure: false and renders the http port name and no
metrics-auth ClusterRole, and the manager still serves nothing.
Reproduction
Take any project, remove --metrics-bind-address from the manager's args in the
kustomize output, keep the metrics Service, and run kubebuilder edit --plugins=helm/v2-alpha. Then:
helm template dist/chart | grep -A5 'args:'The manager carries --leader-elect, the health probe address and the cert
paths, and no metrics argument, while dist/chart/values.yaml carries a full
metrics: section and the chart renders the metrics Service and ServiceMonitor.
Suggested fix
Emit the block for every manager, synthesising the bind address from the value when the project has none:
if metricsLine == "" {
metricsLine = itemIndent + "- --metrics-bind-address=:{{ .Values.metrics.port }}"
}
if metricsIndent == "" {
metricsIndent = itemIndent
}
builder.WriteString(metricsIndent)
builder.WriteString("{{- if .Values.metrics.enabled }}\n")
builder.WriteString(metricsLine)
...The {{- else }} branch that already writes --metrics-bind-address=0 then
covers metrics.enabled=false for these projects too, which is the same value
the scaffolded manager defaults to.
Projects whose manager already sets a bind address are unaffected: they keep
taking the existing path, and the four sample charts under testdata/ and
docs/book/src/*/testdata/ regenerate byte for byte.
Test gaps worth closing with it
- No unit test covers a manager with an
args:block and no--metrics-bind-address.templater_test.gohas one such fixture ("should template deployment fields when container name is not 'manager'") and it asserts nothing about metrics, so restoring the old gate leavesmake test-unitgreen. - No test asserts that the bind address the chart hands the manager follows
metrics.portrather than a literal8443. - A manager with no
args:key at all still receives nothing: the args regex finds no match and the function returns early. Worth deciding explicitly.
Source: kubernetes-sigs/kubebuilder