operator & charts/redpanda: cut release v26.2.3 / v26.2.3 - #1816
Merged
Conversation
## operator: cut release v26.2.3 ## [v26.2.3](https://github.com/redpanda-data/redpanda-operator/releases/tag/operator%2Fv26.2.3) - 2026-09-03 ### Added * The operator chart can add a scrape-time label identifying which Kubernetes cluster a metrics series came from, via `monitoring.clusterLabel`. Off by default. Applies to single-cluster and stretch-cluster deployments alike. Use it whenever operator metrics from more than one Kubernetes cluster land in the same Prometheus-compatible backend — several independent installs remote_writing to a shared Mimir/Thanos, or one StretchCluster spanning clusters. In either case nothing in the scraped series says which cluster produced it: job, namespace, service and pod names are identical in every cluster, and identical by design when each install uses the same release name. The series collide, and a graph of, say, `controller_runtime_reconcile_total` sums clusters together without saying so. `monitoring.clusterLabel.enabled=true` renders a relabeling on the ServiceMonitor endpoint that stamps `redpanda_k8s_cluster` onto every series from that operator. `monitoring.clusterLabel.name` and `.value` override the label and its value. When `multicluster.enabled` is true the value defaults to `multicluster.name`, which is already the cluster's identity in the operator's raft group, so a stretch deployment needs only the toggle. Otherwise `.value` is required — including when `multicluster.name` happens to be set but multicluster mode is off, since that name configures nothing else there and inheriting it would turn a stale value into a metric label. The render fails rather than emitting an empty label, since an empty label looks like data. Off by default because one cluster reporting to its own Prometheus has nothing to disambiguate, and adding a label to everyone's series would churn existing dashboards and recording rules. * Rolling restarts now wait for each broker's Schema Registry store to catch up on _schemas (via the auth-exempt GET /status/ready probe) before rolling the next broker, so overlapping SR replay windows can no longer leave a cluster without a consistent Schema Registry endpoint mid-upgrade. The gate applies to the V1 (Cluster), V2 (Redpanda), and multicluster (StretchCluster) controllers, is skipped on clusters without a Schema Registry listener, and can be disabled with --wait-for-schema-registry-sync=false. * Telemetry now reports `id_hash` for clusters licensed through their CR, not only for operators given their own license file. `id_hash` was previously derived solely from the operator's own `--license-file-path` (operator chart `enterprise.licenseSecretRef`), which deployers set only for the Connect controller or multicluster — so every install that licensed Redpanda the usual way, on the CR, reported no `id_hash` and could not be correlated to an account. The collector now resolves the license configured on each managed cluster (`Redpanda .spec.clusterSpec.enterprise.license`/`licenseSecretRef` and legacy `Cluster .spec.licenseRef`) and reports its checksum. The operator's own license stays authoritative when present. A new `clusterLicenses.checksums` field carries the distinct license checksums found across the managed clusters, sorted, so a fleet holding several licenses still correlates to every account it belongs to instead of to none; `id_hash` itself is left empty in that case, since no single checksum represents the install. `clusterLicenses.licensed` counts the clusters carrying a valid license, which the deduplicated checksum list cannot express — several clusters commonly share one license. Licenses that are expired, non-enterprise, or unreadable are skipped rather than failing the report, and commands that do not reconcile the legacy v1 API do not report those clusters' licenses. * The single-cluster operator now supports --leader-election-lease-duration, --leader-election-renew-deadline, and --leader-election-retry-period for tuning leader election. The existing 15s, 10s, and 2s defaults remain unchanged. ### Fixed * The sidecar's user watcher now sets the `superusers` cluster property once per sync pass, with the union of every users file, instead of once per file with only that file's users. Operator-managed clusters never saw the transient superuser revocation this fixes — the operator deploys the sidecar with `--no-set-superusers`, so the watcher never wrote the property there. The visible change for them is log hygiene: malformed users-file lines, which can contain passwords, are no longer echoed into the sidecar log. See the redpanda chart's changelog entry for the full description. * The `multicluster` command now serves its metrics endpoint over HTTPS by default, so the operator chart's ServiceMonitor can actually scrape a multicluster deployment. The chart renders the ServiceMonitor with `scheme: https` and `insecureSkipVerify: true`, which is what the `run` command's `--metrics-secure` default (true) produces — controller-runtime terminates TLS with a self-signed certificate when no certificate path is given. The `multicluster` command had no such flag and enabled secure serving only when `--metrics-cert-path`/`--metrics-key-path` were passed, which the chart never does, so it listened for plain HTTP on the metrics port and every scrape failed in the TLS handshake. Operator metrics from a multicluster installation were therefore never collected. `multicluster` now takes the same `--metrics-secure` flag, defaulting to true; the metrics endpoint stays behind bearer-token authn/authz either way. If you worked around this by overriding the rendered ServiceMonitor to `scheme: http`, drop that override — the scrape now needs `https`. To keep the old plain-HTTP endpoint instead, pass `--metrics-secure=false` to the operator. Relatedly, `rpk k8s multicluster bundle` now expects HTTPS unless `--metrics-secure=false` is present in the deployment's arguments, and retries a failed scrape with the other scheme so bundles still collect metrics from operators predating this change. * The multicluster operator now reports telemetry instead of dropping every report. The telemetry collector listed the legacy `vectorized.io/v1alpha1` `Cluster` API unconditionally, which the multicluster command's scheme does not register because it does not reconcile that API. The resulting `no kind is registered for the type v1alpha1.ClusterList` is neither a NoMatch nor a Forbidden, so it propagated out of `Collect` and the reporter discarded the whole document on every cycle — no stretch or multicluster install has ever reported telemetry, in any release. The `multicluster` command now declares that it does not collect the legacy v1 API, so that list is skipped outright rather than attempted against a scheme that cannot serialize it. This keeps each command's scheme matching the CRDs it actually installs and saves an API server round trip per reporting cycle. As a backstop for any future type a command's scheme omits, the collector also tolerates a not-registered type the same way it already tolerated a missing CRD or missing RBAC: that one field degrades to its zero value and every other field is still reported, instead of the whole install vanishing from the dataset. One consequence worth knowing: legacy `vectorized.io/v1alpha1` clusters running alongside a multicluster install are reported as zero. Those clusters are not managed by that command either. * An unreadable broker list no longer aborts the whole reconcile pass — the maintenance-mode step defers instead. Because it runs first in both the single-cluster and StretchCluster chains, a transient admin-API read failure against a broker whose pod is already gone (mid-roll, mid-decommission, or a BrokerPool being deleted) previously aborted decommissioning and cluster-config sync for that pass, so the very broker that made the read fail was never removed * The StretchCluster admin, Kafka, and Schema Registry clients no longer offer brokers whose pod cannot be dialed. Endpoints came from declared replica counts alone, so clients also tried deliberately absent brokers — a deleted pool, a broker mid-roll — spending their timeout on each. Terminating, finished, and address-less pods are now skipped; with none dialable, the full declared list is used as before. * The `monitoring.rulesEnabled` PrometheusRule and the shipped Grafana dashboard now scope every expression to this operator install by `job` and `namespace`, and keep both labels on the recorded series. `controller_runtime_*` and `workqueue_*` are exported by every controller-runtime operator on the cluster (Karpenter, Flux, cert-manager, Trivy), so unscoped rules fired the operator's alerts for foreign controllers and merged same-named controllers across operators. The dashboard gains Namespace and Job pickers plus one for the opt-in `monitoring.clusterLabel` label. * The `monitoring.rulesEnabled` alerts that read a recording rule now carry the same job/namespace matcher as the rest, so two operator installs sharing a Prometheus stop alerting on each other's controllers. K8S-926 scoped the recording rules and the alerts that read raw metrics, but left `OperatorReconcileErrors`, `OperatorReconcileRunaway` and `OperatorReconcileStalled` matching a recorded series by name alone. A recorded series is not namespaced to whichever install produced it, so with two installs rendering their PrometheusRule into one Prometheus, each install's copy of those alerts evaluated against both installs' series. * Fixed false-positive `OperatorReconcileRunaway` and `OperatorWorkerPoolSaturated` alerts during healthy interval reconciliation. A new `OperatorReconcileChurn` alert tracks non-interval work, Runaway retains a higher-threshold total-rate backstop, and saturation now measures sustained workqueue delay instead of worker utilization. * User, Role, and Group resources now reconcile on clusters with `listeners.schemaRegistry.enabled=false`. The Schema Registry client is no longer resolved via DNS SRV lookup (which always failed with the listener disabled, blocking all ACL syncs); a disabled listener is treated as "Schema Registry not configured", matching v1 clusters. ## charts/redpanda: cut release v26.2.3 ## [v26.2.3](https://github.com/redpanda-data/redpanda-operator/releases/tag/charts%2Fredpanda%2Fv26.2.3) - 2026-09-03 ### Changed * Bump operator sidecar image tag to v26.2.3 release * The default Redpanda version installed by the chart is now [v26.2.2](https://github.com/redpanda-data/redpanda/releases/tag/v26.2.2). ### Fixed * The sidecar's user watcher now sets the `superusers` cluster property once per sync pass, with the union of every users file, instead of once per file with only that file's users. Previously every sidecar start and every users-secret update transiently replaced the list with a partial one — kubelet's `..data` symlink even parsed as an empty users file — momentarily revoking superuser status from connected clients. Only helm-chart deployments were affected; the operator deploys the sidecar with `--no-set-superusers`. The property is now written only when the list actually changes, so sidecar restarts no longer bump the cluster config version; when a users file can't be read, the patch is withheld and the pass retried with backoff instead of writing a partial list; and malformed users-file lines, which can contain passwords, are no longer echoed into the sidecar log. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RafalKorepta
requested review from
andrewstucki,
chrisseto,
gene-redpanda and
hidalgopl
as code owners
September 3, 2026 13:16
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
david-yu
approved these changes
Sep 3, 2026
chrisseto
approved these changes
Sep 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cuts the operator and charts/redpanda releases on the release/v26.2.x line in a single commit.
Also bumps the default Redpanda version installed by the chart (appVersion) to v26.2.2.
operator: cut release v26.2.3
v26.2.3 - 2026-09-03
Added
The operator chart can add a scrape-time label identifying which Kubernetes
cluster a metrics series came from, via
monitoring.clusterLabel. Off bydefault. Applies to single-cluster and stretch-cluster deployments alike.
Use it whenever operator metrics from more than one Kubernetes cluster land in
the same Prometheus-compatible backend — several independent installs
remote_writing to a shared Mimir/Thanos, or one StretchCluster spanning
clusters. In either case nothing in the scraped series says which cluster
produced it: job, namespace, service and pod names are identical in every
cluster, and identical by design when each install uses the same release
name. The series collide, and a graph of, say,
controller_runtime_reconcile_totalsums clusters together without saying so.monitoring.clusterLabel.enabled=truerenders a relabeling on theServiceMonitor endpoint that stamps
redpanda_k8s_clusteronto every seriesfrom that operator.
monitoring.clusterLabel.nameand.valueoverride thelabel and its value.
When
multicluster.enabledis true the value defaults tomulticluster.name, which is already the cluster's identity in theoperator's raft group, so a stretch deployment needs only the toggle.
Otherwise
.valueis required — including whenmulticluster.namehappensto be set but multicluster mode is off, since that name configures nothing
else there and inheriting it would turn a stale value into a metric label.
The render fails rather than emitting an empty label, since an empty label
looks like data.
Off by default because one cluster reporting to its own Prometheus has nothing
to disambiguate, and adding a label to everyone's series would churn existing
dashboards and recording rules.
Rolling restarts now wait for each broker's Schema Registry store to catch up
on _schemas (via the auth-exempt GET /status/ready probe) before rolling the
next broker, so overlapping SR replay windows can no longer leave a cluster
without a consistent Schema Registry endpoint mid-upgrade. The gate applies
to the V1 (Cluster), V2 (Redpanda), and multicluster (StretchCluster)
controllers, is skipped on clusters without a Schema Registry listener, and
can be disabled with --wait-for-schema-registry-sync=false.
Telemetry now reports
id_hashfor clusters licensed through their CR, notonly for operators given their own license file.
id_hashwas previously derived solely from the operator's own--license-file-path(operator chartenterprise.licenseSecretRef), whichdeployers set only for the Connect controller or multicluster — so every
install that licensed Redpanda the usual way, on the CR, reported no
id_hashand could not be correlated to an account. The collector nowresolves the license configured on each managed cluster
(
Redpanda .spec.clusterSpec.enterprise.license/licenseSecretRefandlegacy
Cluster .spec.licenseRef) and reports its checksum.The operator's own license stays authoritative when present. A new
clusterLicenses.checksumsfield carries the distinct license checksumsfound across the managed clusters, sorted, so a fleet holding several
licenses still correlates to every account it belongs to instead of to
none;
id_hashitself is left empty in that case, since no single checksumrepresents the install.
clusterLicenses.licensedcounts the clusterscarrying a valid license, which the deduplicated checksum list cannot
express — several clusters commonly share one license.
Licenses that are expired, non-enterprise, or unreadable are skipped rather
than failing the report, and commands that do not reconcile the legacy v1
API do not report those clusters' licenses.
The single-cluster operator now supports --leader-election-lease-duration,
--leader-election-renew-deadline, and --leader-election-retry-period for
tuning leader election. The existing 15s, 10s, and 2s defaults remain
unchanged.
Fixed
The sidecar's user watcher now sets the
superuserscluster property onceper sync pass, with the union of every users file, instead of once per file
with only that file's users.
Operator-managed clusters never saw the transient superuser revocation this
fixes — the operator deploys the sidecar with
--no-set-superusers, so thewatcher never wrote the property there. The visible change for them is log
hygiene: malformed users-file lines, which can contain passwords, are no
longer echoed into the sidecar log.
See the redpanda chart's changelog entry for the full description.
The
multiclustercommand now serves its metrics endpoint over HTTPS bydefault, so the operator chart's ServiceMonitor can actually scrape a
multicluster deployment.
The chart renders the ServiceMonitor with
scheme: httpsandinsecureSkipVerify: true, which is what theruncommand's--metrics-securedefault (true) produces — controller-runtime terminatesTLS with a self-signed certificate when no certificate path is given. The
multiclustercommand had no such flag and enabled secure serving only when--metrics-cert-path/--metrics-key-pathwere passed, which the chart neverdoes, so it listened for plain HTTP on the metrics port and every scrape
failed in the TLS handshake. Operator metrics from a multicluster
installation were therefore never collected.
multiclusternow takes thesame
--metrics-secureflag, defaulting to true; the metrics endpoint staysbehind bearer-token authn/authz either way.
If you worked around this by overriding the rendered ServiceMonitor to
scheme: http, drop that override — the scrape now needshttps. To keepthe old plain-HTTP endpoint instead, pass
--metrics-secure=falseto theoperator.
Relatedly,
rpk k8s multicluster bundlenow expects HTTPS unless--metrics-secure=falseis present in the deployment's arguments, andretries a failed scrape with the other scheme so bundles still collect
metrics from operators predating this change.
The multicluster operator now reports telemetry instead of dropping every report.
The telemetry collector listed the legacy
vectorized.io/v1alpha1ClusterAPI unconditionally, which the multicluster command's scheme does not
register because it does not reconcile that API. The resulting
no kind is registered for the type v1alpha1.ClusterListis neither aNoMatch nor a Forbidden, so it propagated out of
Collectand the reporterdiscarded the whole document on every cycle — no stretch or multicluster
install has ever reported telemetry, in any release.
The
multiclustercommand now declares that it does not collect the legacyv1 API, so that list is skipped outright rather than attempted against a
scheme that cannot serialize it. This keeps each command's scheme matching
the CRDs it actually installs and saves an API server round trip per
reporting cycle. As a backstop for any future type a command's scheme
omits, the collector also tolerates a not-registered type the same way it
already tolerated a missing CRD or missing RBAC: that one field degrades to
its zero value and every other field is still reported, instead of the
whole install vanishing from the dataset.
One consequence worth knowing: legacy
vectorized.io/v1alpha1clustersrunning alongside a multicluster install are reported as zero. Those
clusters are not managed by that command either.
An unreadable broker list no longer aborts the whole reconcile pass — the
maintenance-mode step defers instead. Because it runs first in both the
single-cluster and StretchCluster chains, a transient admin-API read failure
against a broker whose pod is already gone (mid-roll, mid-decommission, or a
BrokerPool being deleted) previously aborted decommissioning and
cluster-config sync for that pass, so the very broker that made the read
fail was never removed
The StretchCluster admin, Kafka, and Schema Registry clients no longer offer
brokers whose pod cannot be dialed.
Endpoints came from declared replica counts alone, so clients also tried
deliberately absent brokers — a deleted pool, a broker mid-roll — spending
their timeout on each. Terminating, finished, and address-less pods are now
skipped; with none dialable, the full declared list is used as before.
The
monitoring.rulesEnabledPrometheusRule and the shipped Grafanadashboard now scope every expression to this operator install by
jobandnamespace, and keep both labels on the recorded series.controller_runtime_*andworkqueue_*are exported by everycontroller-runtime operator on the cluster (Karpenter, Flux, cert-manager,
Trivy), so unscoped rules fired the operator's alerts for foreign
controllers and merged same-named controllers across operators. The
dashboard gains Namespace and Job pickers plus one for the opt-in
monitoring.clusterLabellabel.The
monitoring.rulesEnabledalerts that read a recording rule now carrythe same job/namespace matcher as the rest, so two operator installs sharing
a Prometheus stop alerting on each other's controllers.
K8S-926 scoped the recording rules and the alerts that read raw metrics, but
left
OperatorReconcileErrors,OperatorReconcileRunawayandOperatorReconcileStalledmatching a recorded series by name alone. Arecorded series is not namespaced to whichever install produced it, so with
two installs rendering their PrometheusRule into one Prometheus, each
install's copy of those alerts evaluated against both installs' series.
Fixed false-positive
OperatorReconcileRunawayandOperatorWorkerPoolSaturatedalerts during healthy interval reconciliation.A new
OperatorReconcileChurnalert tracks non-interval work, Runawayretains a higher-threshold total-rate backstop, and saturation now measures
sustained workqueue delay instead of worker utilization.
User, Role, and Group resources now reconcile on clusters with
listeners.schemaRegistry.enabled=false. The Schema Registry client is nolonger resolved via DNS SRV lookup (which always failed with the listener
disabled, blocking all ACL syncs); a disabled listener is treated as "Schema
Registry not configured", matching v1 clusters.
charts/redpanda: cut release v26.2.3
v26.2.3 - 2026-09-03
Changed
v26.2.2.
Fixed
superuserscluster property onceper sync pass, with the union of every users file, instead of once per file
with only that file's users.
Previously every sidecar start and every users-secret update transiently
replaced the list with a partial one — kubelet's
..datasymlink evenparsed as an empty users file — momentarily revoking superuser status from
connected clients. Only helm-chart deployments were affected; the operator
deploys the sidecar with
--no-set-superusers.The property is now written only when the list actually changes, so sidecar
restarts no longer bump the cluster config version; when a users file can't
be read, the patch is withheld and the pass retried with backoff instead of
writing a partial list; and malformed users-file lines, which can contain
passwords, are no longer echoed into the sidecar log.
🤖 Generated with Claude Code