feat(workloadmonitor): bucket metrics endpoint override (#3443) [backport release-1.6] - #3558
Conversation
The controller discovers where to query SeaweedFS bucket size metrics via the namespace.cozystack.io/monitoring label, which assumes the monitoring stack that scrapes SeaweedFS runs in the same cluster. Some deployments host SeaweedFS and its metrics in a separate cluster, so add a --seaweedfs-metrics-endpoint flag to cozystack-controller (and a matching cozystackController.seaweedfsMetricsEndpoint chart value): an explicit base URL of a Prometheus-compatible query API, with scheme, host, optional port and path prefix; /api/v1/query is appended. Basic auth may be embedded as URL userinfo. The flag is validated and normalized at startup, so a malformed URL fails the rollout rather than the queries. Empty keeps label-based discovery unchanged. Bucket sizes feed billing, so metrics failures no longer collapse to "no size": previously any query failure yielded an empty result map and the reconciler overwrote Workload resources with it, silently wiping the recorded sizes. The reconciler now retains the last known s3-storage-bytes and s3-physical-storage-bytes values, emits a BucketMetricsUnavailable warning event on the WorkloadMonitor, and returns the error from Reconcile so it lands in the reconcile error metrics. Assisted-By: Claude <[email protected]> Signed-off-by: Timofei Larkin <[email protected]> (cherry picked from commit 95e4faf)
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Aleksei Sviridkin (lexfrei)
left a comment
There was a problem hiding this comment.
LGTM
Faithful backport. I diffed the patch of this branch's single commit against 95e4faf68 on main: they are byte-identical across all five files, modulo blob hashes, hunk offsets, and one context line (the pinned controller image, v1.6.1 here against v1.6.0 there, because this branch is further along). The "clean cherry-pick, no adaptations" claim in the description holds. The flag that forced a resolution on the 1.5 backport, --tenant-quota-buffer-percent, is present on release-1.6, which is why nothing conflicted here.
Applicability to the target branch checks out on every surface the change leans on. mgr.GetEventRecorderFor and k8s.io/client-go/tools/record are available, and the build is green. The new +kubebuilder:rbac marker for events is worth checking by hand rather than trusting: hack/update-codegen.sh does invoke controller-gen rbac:roleName=manager-role, but it points it at ./api/v1alpha1/..., ./api/backups/... and ./api/gateway/..., none of which hold a single +kubebuilder:rbac marker, while all 35 of them live under internal/, so the generator reads nothing, writes nothing, and make generate stays clean no matter what a marker says. The chart's ClusterRole is maintained by hand instead. Here the grant does exist in this branch's packages/system/cozystack-controller/templates/rbac.yaml, added earlier by the tenant quota work, so the warning event is genuinely creatable, but that is a coincidence rather than something the marker arranged. Worth a separate issue, and out of scope for a backport. Workload carries no status subresource, so the Update inside CreateOrUpdate does persist the retained status.resources: the retention logic works against a live API server, not only against the fake client in the tests. The new value is reachable in practice through Package.spec.components[].values, so the flag is not a knob nobody can turn.
Ran locally against the branch: go build ./... green, go test ./internal/controller/... green across all packages, helm lint clean, helm template renders --seaweedfs-metrics-endpoint only when the value is set and omits it by default, and make generate produces no drift. I mutation-checked the two behaviours the change is really about. Deleting the loop that seeds resources from the recorded sizes turns both retention tests red on exactly their retention assertions, and dropping the return ctrl.Result{}, bucketMetricsErr turns the query-failure test red on exactly its "expected Reconcile to return an error" assertion. The tests are not paper.
Four non-blocking notes, all inherited verbatim from the original, and none of them things to fix here, since that would break parity. Basic auth embedded as URL userinfo ends up verbatim in the Deployment args, readable through kubectl get deploy -o yaml, the container command line, and the Helm release secret; if that matters for a deployment, the fix belongs on main first. When a namespace carries no namespace.cozystack.io/monitoring label at all, resolvePrometheusURL returns an empty string and queryAllBucketMetrics returns an empty map with a nil error, so retention kicks in with no event, no log line, and no returned error: that is the one path where recorded sizes freeze silently, where they used to be zeroed. The BucketMetricsUnavailable event itself has no coverage, because every fixture leaves Recorder nil and only the nil branch ever runs, which record.NewFakeRecorder would close in a few lines. The chart already has a helm-unittest harness but no case for the new conditional arg.
One question for whoever owns the 1.6 line, not a code objection. Every one of the 29 commits on release-1.6 since v1.6.0 is a fix, chore, ci, docs, or test change, so this would be the first feat on the 1.6 patch series. The commit bundles two things: a genuine data-loss fix (a metrics failure used to overwrite recorded bucket sizes with nothing, which billing reads as an empty bucket) and a new administrator flag. Splitting them would break parity with main, so it lands whole or not at all, and that is a release-management call rather than a review one.
E2E is red on chainsaw/kubernetes-previous and chainsaw/kubernetes-latest, both tenant Kubernetes cluster provisioning. I could not find a causal path from this diff: the new argument renders only when the value is non-empty and it is empty by default, and the changed Go path only executes for WorkloadMonitors that own BucketClaims, which those tests never create. The bucket tests in the same run passed. The parallel 1.5 backport, carrying the same change, fails at a different phase entirely, which also points away from the shared diff. It still needs a green run before merge.
What this PR does
Hand-backport of #3443 to
release-1.6. The change merged tomainon 2026-07-24, after v1.6.0 was cut, so it never reached any 1.6 patch and is currently slated to wait for 1.7. This lands it in 1.6.2.The cozystack-controller meters S3 bucket sizes for billing by querying SeaweedFS metrics from a VictoriaMetrics vmselect it discovers via the
namespace.cozystack.io/monitoringlabel on the tenant namespace. That discovery assumes the monitoring stack scraping SeaweedFS runs in the same cluster. Some deployments host SeaweedFS (API and metrics both) in a separate cluster, where discovery can never produce a reachable endpoint. This adds a single controller flag,--seaweedfs-metrics-endpoint, exposed as the chart valuecozystackController.seaweedfsMetricsEndpoint, to point bucket-size metrics at a remote Prometheus-compatible query API. Empty keeps the existing label-based discovery, so behaviour is unchanged by default.Backport adaptations
Clean cherry-pick of
95e4faf68; no adaptations required.go build ./cmd/...and the fullinternal/controllertest suite pass.Screenshots
Not applicable — no UI change.
Downstream repositories
Release note