Skip to content

feat: Add opt in persistent storage for the aggregator#251

Merged
aa1ex merged 8 commits into
kaasops:mainfrom
stigglor:feat/aggregator-persistent-disk-buffers
Jul 10, 2026
Merged

feat: Add opt in persistent storage for the aggregator#251
aa1ex merged 8 commits into
kaasops:mainfrom
stigglor:feat/aggregator-persistent-disk-buffers

Conversation

@stigglor

@stigglor stigglor commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Adds a persistence option to VectorAggregator and ClusterVectorAggregator. When you enable it, the operator renders the aggregator as a StatefulSet with a persistent volume per replica instead of the default Deployment, so the Vector data_dir gets durable, stable per replica storage.

The reason is that Vector's disk buffer lives under data_dir and only survives a restart if that directory is persistent and tied to the same replica. Today the aggregator is a Deployment on a node local hostPath, so a rescheduled pod comes back with a foreign or empty directory. This is the same split Vector's own Helm chart makes, where the durable Aggregator role is a StatefulSet with a per replica PVC.

This gives you the storage only. Disk buffering still has to be enabled per sink with buffer.type = disk, the operator does not set it for you.

spec:
  persistence:
    enabled: true
    size: 10Gi
    storageClassName: gp3

Closes #250

stigglor added 7 commits July 7, 2026 20:27
Add a persistence block to the shared aggregator spec. When enabled the
aggregator will run as a StatefulSet with a persistent volume per replica
so disk buffers survive pod restart and reschedule.

Includes the API type, defaults, the persistenceEnabled helper, and
regenerated deepcopy and CRD manifests.
Add the StatefulSet workload builder and branch the reconcile so the
aggregator is rendered as a StatefulSet with a volume claim template per
replica when persistence is enabled, otherwise it stays a Deployment.

The data volume now comes from the volume claim template in persistent
mode, so the hostPath data volume is only added for the Deployment path.
The StatefulSet references a headless governing service by name.
Assigning the whole desired spec on every reconcile fails once a
StatefulSet uses volume claim templates, since Kubernetes rejects changes
to volumeClaimTemplates, serviceName, selector, and podManagementPolicy.

Keep those fields from the live object on update and only assign the
mutable ones. Replicas are preserved when the desired count is nil so the
operator does not fight the autoscaler, and an immutable change is logged
as a warning since it needs the aggregator to be recreated.
Add a headless governing service in persistent mode so the StatefulSet has
stable per replica DNS, and point the HPA at the StatefulSet instead of the
Deployment when persistent.

Both aggregator controllers now own StatefulSets and have the RBAC to manage
them, so the operator reconciles on StatefulSet changes and can create them.
Add builder unit tests for the StatefulSet path and an e2e test that
deploys a persistence enabled aggregator and checks it becomes a
StatefulSet with a bound per replica volume and a headless service.

Document the persistence field, the Deployment versus StatefulSet rule,
and why volume resizing is left manual. Sync the helm chart CRDs and add
a changelog entry.
Extract the shared pod template so the Deployment and StatefulSet builders
no longer duplicate it. Delete the opposite workload when persistence is
toggled, so switching modes does not leave a Deployment and a StatefulSet
serving side by side. Reject a raw volumeClaimTemplates escape hatch that
has no claim named data, since the container mounts that volume, and make
the name a single constant. Align the resize docs with the log behavior.
@stigglor

stigglor commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

E2E failure looks like an intermittent dependency fetch failure, unrelated. Might just need a rerun?

@stigglor stigglor changed the title Add opt in persistent storage for the aggregator feat: Add opt in persistent storage for the aggregator Jul 9, 2026

@aa1ex aa1ex left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice work - clean, well documented and well tested, and it does exactly what it says. Left one small optional note inline on deleteObsoleteWorkload.

Comment thread internal/vector/aggregator/controller.go Outdated
deleteObsoleteWorkload issued a DELETE for the opposite workload kind on
every reconcile, which just returned NotFound in steady state. Read from
the Owns() cache first and only delete when the workload exists.

Add tests covering the delete and the skip paths.
@aa1ex aa1ex merged commit 9d732eb into kaasops:main Jul 10, 2026
6 of 8 checks passed
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.

Support persistent disk buffers for the aggregator (StatefulSet + PVC)

2 participants