Skip to content

helm/v2-alpha: the generated chart exposes metrics values the manager never receives #6021

Closed

Description

@camilamacedo86

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.go has one such fixture
    ("should template deployment fields when container name is not 'manager'")
    and it asserts nothing about metrics, so restoring the old gate leaves
    make test-unit green.
  • No test asserts that the bind address the chart hands the manager follows
    metrics.port rather than a literal 8443.
  • 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.

Activity

  1. Neilblaze commented on Sep 6, 2026

    @Neilblaze

    @camilamacedo86 Is this up for grabs? if yes, then I'd love to pick it up.

  2. Neilblaze commented on Sep 6, 2026

    @Neilblaze

    /assign

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

Metadata

Metadata

Assignees

Labels

kind/bugCategorizes issue or PR as related to a bug.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions