Skip to content

Render sourcegraph.labels on every object, and add storage and ServiceAccount labels - #1008

Draft
marcleblanc2 wants to merge 16 commits into
mainfrom
marc/pvc-serviceaccount-labels
Draft

marcleblanc2 wants to merge 16 commits into
mainfrom
marc/pvc-serviceaccount-labels

Conversation

@marcleblanc2

@marcleblanc2 marcleblanc2 commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Open issues

Found in review on 2026-11-13 (review thread), at 05bb302. The labels work as described; this PR is a draft until the first three are settled.

  1. A user's own app.kubernetes.io/instance label leaves both Jaeger Services with no endpoints. main pins that label on the Jaeger pod to the release name; this branch lets sourcegraph.labels, sourcegraph.podLabels, and jaeger.podLabels replace it, and the Services still select the release name. Reproduced on EKS with jaeger.enabled: true and jaeger.podLabels."app.kubernetes.io/instance": prod: jaeger-collector and jaeger-query went from 1 endpoint each to 0. Fix: merge the release name last in the pod's labels, and add a test
  2. The executor Service deletion and the kubernetes-services job removal, both taken from fix/resources: Drop unused ports, Services, Role verbs, and settings #1016, are in neither changelog nor this description. "No object is recreated" below is true, but the upgrade deletes the executor-<queueName> Service, and executor.serviceAnnotations, serviceLabels, and serviceType stop working. Fix: merge fix/resources: Drop unused ports, Services, Role verbs, and settings #1016 first, or copy its changelog entries
  3. "$@" is the wrong advice for one form of custom collector command. With the script in openTelemetry.gateway.args after command: ["/bin/sh", "-c"], the form tests/command_test.yaml uses, the chart's argument arrives as $0 and "$@" is empty, so the collector keeps serving metrics on 127.0.0.1. With the script inside command and a placeholder after it, "$@" works: that is what the test instance runs. Fix: document "$0" "$@" for the first form in values.yaml and the changelog
  4. otel-collector restarts on a config change only when openTelemetry.gateway.config.traces is set. The checksum annotation is absent with default values, so "otel-collector now restarts when the chart changes its configMap content" overstates it. prometheus gets its annotation in every case
  5. Small ones:
    • PVCs made from volumeClaimTemplates still get no labels, on new installs too
    • the EKS results under "Testing" are from 4dc65cf, which is no longer on the branch; the run below repeats most of them on the current head

Tested in this review on the EKS test instance m5, by upgrading from main to this branch merged onto main:

  • 83 objects before and 82 after: only the executor Service was removed. No UID, Service IP, or PVC volume changed, and every pod was replaced once
  • Every object Helm manages, and every pod template, has the labels
  • A chart-version-only upgrade replaced 0 pods
  • The otel-collector target is up, with the instance's own sh -c command
  • All 28 pods Ready, and search and an executor batch spec work

Not re-checked: which labels metrics gained and lost, helm test, and the two dind charts on a cluster.

Problem

  • Customer needs the ability to label all resources; Add opt-in selector labels to adopt existing workloads #1007 only went part way

  • Many objects didn't render sourcegraph.labels (PVCs, ServiceAccounts, RBAC objects, Services, ConfigMaps, Secrets, the Ingress), and some had no per-component labels at all

Solution

All four charts now render these labels on every object:

  • sourcegraph.labels, the standard Helm labels, deploy, and app.kubernetes.io/component
  • Per-component labels, empty by default:
    • <serviceName>.labels now also covers the component's ConfigMaps, Secrets, and PodDisruptionBudget
    • New: <serviceName>.storageLabels (PVCs), <serviceName>.serviceAccount.labels (ServiceAccounts and RBAC), storageClass.labels, priorityClasses[].labels
    • Executor charts: executor.labels now also covers the ConfigMaps, Secret, ServiceAccount, and RBAC objects, and new privateDockerRegistry.serviceLabels labels the dind registry Service

On upgrade:

  • No object is recreated, and no selector changes
  • Pods don't get helm.sh/chart or app.kubernetes.io/version, so a chart-only change doesn't restart every pod
  • A new Prometheus labeldrop rule keeps unused labels off metrics
    • Customers using prometheus.existingConfig can add this rule themselves
  • prometheus and otel-collector now restart when the chart changes their configMap content

Issues found along the way, and fixed:

  • jaeger.serviceAccount.create: true failed to render
  • redisStore.serviceAccount.annotations was dropped
  • The OpenTelemetry Collector "pods available" panel and alert had no data
    • The otel-collector Service gets an app label, and the collector serves its metrics on all interfaces through one extra --config argument
    • The argument also goes to a custom openTelemetry.gateway.command, which has to pass "$@" through
  • Prometheus couldn't scrape jaeger, so its scrape annotations are removed, as fix/resources: Drop unused ports, Services, Role verbs, and settings #1016 does

Open question: the --config argument replaces service.telemetry.metrics.readers in any config file a custom command loads. Should the readers be a Helm value instead?

Testing

  • helm unittest and helm lint pass on all four charts. New tests render every template, and fail on any object missing the labels
  • Add opt-in selector labels to adopt existing workloads #1007's golden snapshot only gained the two pod labels. No selector or volume claim template changed
  • On EKS (27 pods, Helm 4, bundled databases, k8s executor), at 4dc65cf:
    • Upgrade: 0 objects recreated, no Service IP or PVC volume changed, each pod replaced once
    • Chart-version-only upgrade and back: 0 pods replaced
    • Metrics lost only app_kubernetes_io_managed_by and gained nothing. No loaded rule or dashboard uses a dropped label
    • otel-collector targets went from down to up, and the "pods available" alert from firing to inactive
    • helm test, search, an executor batch spec, and jaeger.enabled work

Amp threads

Changelog

  • sourcegraph.labels, the standard Helm labels, deploy, and app.kubernetes.io/component are now on every object in all four charts. Existing releases gain them on upgrade
  • New per-component labels: storageLabels, serviceAccount.labels, storageClass.labels, priorityClasses[].labels, and privateDockerRegistry.serviceLabels. <serviceName>.labels and executor.labels now cover more objects
  • If using prometheus.existingConfig, add the new labeldrop rule to avoid new labels in metrics
  • Fixed jaeger.serviceAccount.create, redisStore.serviceAccount.annotations, the OpenTelemetry Collector "pods available" alert

@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

@marcleblanc2
marcleblanc2 added this pull request to stack #1009 November 11, 2026 17:12
@marcleblanc2
marcleblanc2 force-pushed the marc/pvc-serviceaccount-labels branch from 3d258bf to aaffaa9 Compare November 11, 2026 17:45
@marcleblanc2 marcleblanc2 changed the title sourcegraph: add labels to PVCs, ServiceAccounts, and RBAC objects Render sourcegraph.labels on every object, and add storage and ServiceAccount labels Nov 11, 2026
@marcleblanc2
marcleblanc2 force-pushed the marc/pvc-serviceaccount-labels branch from 679ac13 to 7e6b950 Compare November 11, 2026 22:59
Base automatically changed from marc/selector-labels to main November 13, 2026 05:38
marcleblanc2 added a commit that referenced this pull request Nov 13, 2026
Prometheus does not reload a changed ConfigMap by itself, so an upgrade that
keeps the image tag swapped the RBAC resources while the pod kept running
the old scrape configuration.

The annotation, its test, and the changelog entry are the same as in #1008.
marcleblanc2 and others added 15 commits November 13, 2026 00:25
Render sourcegraph.labels on the standalone PersistentVolumeClaims, every
ServiceAccount, and the prometheus RBAC objects, and add per-component
storageLabels and serviceAccount.labels values, so a release that takes over
objects created outside the chart can keep the labels they already have.

Also fix the jaeger ServiceAccount, which read its name and annotations from
a tracing value that does not exist and failed to render.

Amp-Thread-ID: https://ampcode.com/threads/T-c7c725c9-ed68-48e2-9f2d-0b8c31e76050
Co-authored-by: Amp <amp@ampcode.com>
Services, ConfigMaps, Secrets, the Ingress, PodDisruptionBudgets,
PriorityClasses, and extraResources of the sourcegraph chart did not render
sourcegraph.labels. Neither did any object of the sourcegraph-executor-k8s
chart, nor the docker-config ConfigMap and private-docker-registry Service of
the sourcegraph-executor-dind chart.

Prometheus copies Service labels to the metrics it scrapes, so its bundled
configuration now drops the chart's standard labels: helm.sh/chart and
app.kubernetes.io/version change on every upgrade.

Each chart gets a test that renders every template and checks the labels, so
a template added later is covered too.

Amp-Thread-ID: https://ampcode.com/threads/T-c7c725c9-ed68-48e2-9f2d-0b8c31e76050
Co-authored-by: Amp <amp@ampcode.com>
The redis-store ServiceAccount was the only one that did not include the
annotations helper, so redisStore.serviceAccount.annotations was silently
dropped.

Amp-Thread-ID: https://ampcode.com/threads/T-c7c725c9-ed68-48e2-9f2d-0b8c31e76050
Co-authored-by: Amp <amp@ampcode.com>
PodDisruptionBudgets, PriorityClasses, the StorageClass, the test Pod, and
the k8s executor Secret now have deploy and app.kubernetes.io/component
labels, and the jaeger objects have app.kubernetes.io/instance.
<serviceName>.labels and executor.labels are also rendered on a component's
ConfigMaps, Secrets, and PodDisruptionBudget. Adds storageClass.labels,
priorityClasses[].labels, and privateDockerRegistry.serviceLabels (dind).

Amp-Thread-ID: https://ampcode.com/threads/T-c7c725c9-ed68-48e2-9f2d-0b8c31e76050
Co-authored-by: Amp <amp@ampcode.com>
…ice with its app

The bundled Prometheus copies Service labels to the metrics it scrapes. Now
that every Service has sourcegraph.labels, the labeldrop rule also drops
those keys, so the labels of Service-scraped metrics stay as they are on main.

The rule no longer drops app.kubernetes.io/managed-by: Helm adds that label
to every object it installs, so the metrics already had it.

The otel-collector Service had no app label, unlike every other scraped
Service, so its metrics had no app and job labels and the dashboard's
up{app=~".*otel-collector"} panel and alert had no data.

Amp-Thread-ID: https://ampcode.com/threads/T-c7c725c9-ed68-48e2-9f2d-0b8c31e76050
Co-authored-by: Amp <amp@ampcode.com>
The image's logging.yaml, and the ConfigMap the chart renders for custom
exporters, left the collector's metrics on 127.0.0.1:8888, where Prometheus
cannot scrape them. With the app label the Service gained, up was 0 and the
pods available alert fired instead of showing no data.

Pass the telemetry readers setting as a second --config to the default
command, and add it to the rendered ConfigMap. jaeger.yaml already has it.

Amp-Thread-ID: https://ampcode.com/threads/T-c7c725c9-ed68-48e2-9f2d-0b8c31e76050
Co-authored-by: Amp <amp@ampcode.com>
…rics to be scraped

openTelemetry.gateway.command replaces the default command, so it does not get
the argument that serves the collector's metrics on all interfaces.

Amp-Thread-ID: https://ampcode.com/threads/T-c7c725c9-ed68-48e2-9f2d-0b8c31e76050
Co-authored-by: Amp <amp@ampcode.com>
Pod templates now get `sourcegraph.labels`, the chart's standard labels,
and `app.kubernetes.io/component`, as every other object does. One helper,
`sourcegraph.podLabels`, merges them with `sourcegraph.podLabels`, the
component's `podLabels`, and the selector labels, so each key is rendered
once and a selector label always wins.

The Prometheus `labeldrop` rule now also drops
`app.kubernetes.io/managed-by` and also applies to the `kubernetes-pods`
job, so Helm and `helm template | kubectl apply` installs get the same
metric labels. No bundled dashboard or alert queries the dropped labels.

The changelog no longer asks for a manual Prometheus restart: the
`checksum/prometheus-config` annotation restarts it.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1cc03-93a7-7445-8f1f-3dd7123272bf
Co-authored-by: Amp <amp@ampcode.com>
The setting that serves the collector's own metrics on all interfaces was
part of the default command, so a command set in
`openTelemetry.gateway.command` did not get it, and Prometheus could not
scrape the collector. It is now always the last container argument, after
`openTelemetry.gateway.args`, so a replacement command gets it too. Last,
so that it is `$0` of a `sh -c` command whose script is the first argument.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1cc03-93a7-7445-8f1f-3dd7123272bf
Co-authored-by: Amp <amp@ampcode.com>
The collector does not reload a changed ConfigMap by itself, so a change to openTelemetry.gateway.config.traces took effect only at the pod's next restart. The pod template now has a checksum/otel-collector-config annotation over those values, which are all the ConfigMap's data is rendered from. It is set only when the chart renders the ConfigMap, so the default install does not change.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1cc03-93a7-7445-8f1f-3dd7123272bf
Co-authored-by: Amp <amp@ampcode.com>
helm.sh/chart and app.kubernetes.io/version change with every chart version. As pod labels they changed every pod template, so every pod restarted whenever the chart version changed, even when nothing else did. On main no pod template depends on the chart version.

Pod templates in all four charts now get the common labels without these two. The other objects keep them.

This also updates the pod label snapshots of the selector labels golden test: every pod gains app.kubernetes.io/managed-by and app.kubernetes.io/component, and no selector, volume claim template, or existing pod label changes.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1cc03-93a7-7445-8f1f-3dd7123272bf
Co-authored-by: Amp <amp@ampcode.com>
The jaeger pod's prometheus.io/port annotation named port 16686, the
query UI, which has no /metrics, so the scrape target was down. Jaeger
v2 serves its own metrics on localhost:8888 unless its configuration
says otherwise.

The chart's Jaeger configuration now serves them on all interfaces,
port 8888, as Jaeger's own all-in-one configuration does, and the
annotation names that port.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1cc03-93a7-7445-8f1f-3dd7123272bf
Co-authored-by: Amp <amp@ampcode.com>
…does

#1016 deletes the executor-<queueName>
Service, which fronts a port the executor has not served since 4.1, and
the kubernetes-services scrape job, which probes through a blackbox
exporter the chart does not ship. Making the same deletions here keeps
this PR and #1016 from conflicting in those files.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1d269-2788-7075-b66b-b87e3087047d
Co-authored-by: Amp <amp@ampcode.com>
This replaces 4dc65cf, which served Jaeger's metrics on 0.0.0.0:8888 and
pointed the pod's prometheus.io/port annotation there.
#1016 removes the scrape annotations
instead: they pointed at port 16686, which has no /metrics, and Jaeger's
own otelcol_* metrics would otherwise mix into the OpenTelemetry Collector
dashboards. Making the same change here keeps this PR and #1016 from
conflicting in the Jaeger Deployment and the README.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1d269-2788-7075-b66b-b87e3087047d
Co-authored-by: Amp <amp@ampcode.com>
@marcleblanc2
marcleblanc2 force-pushed the marc/pvc-serviceaccount-labels branch from 6fd1fe2 to 756d760 Compare November 13, 2026 06:26
Each chart's label defines, with their comments, move unchanged out of
_helpers.tpl, next to the other one-topic helper files. Renders are
byte-identical.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1d360-e0b4-71d1-8ded-2e4851b93a8d
Co-authored-by: Amp <amp@ampcode.com>

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant