Skip to content

feat: add volume capacity enforcement (size validation, capacity budget, XFS quota)#558

Open
luctrate wants to merge 10 commits intorancher:masterfrom
luctrate:feat/volume-capacity-enforcement
Open

feat: add volume capacity enforcement (size validation, capacity budget, XFS quota)#558
luctrate wants to merge 10 commits intorancher:masterfrom
luctrate:feat/volume-capacity-enforcement

Conversation

@luctrate
Copy link

Summary

Adds per-PVC volume capacity enforcement to local-path-provisioner, addressing #345 (capacity limit is ignored).

  • Per-PVC size validation: configurable minSize / maxSize bounds per StorageClass, rejecting PVCs outside limits
  • Per-path capacity budget: track allocated capacity per node path, reject new PVCs that would exceed the path's capacityGB budget
  • PVC resize controller: watch for PVC capacity changes (expand) and annotation-driven shrink requests, calling a configurable resize helper script
  • XFS project quota enforcement: quota-helper sidecar container with setup, teardown, and resize scripts that use xfs_quota to assign per-PVC project quotas on XFS filesystems
  • E2e test coverage: 8 XFS quota tests (k3s-targeted), Kind-based e2e tests for size/capacity, and a CI-runnable GitHub Actions workflow using loopback XFS

Commits

  1. refactor(test): extract shared test helpers, fix kustomize overlays
  2. feat: per-PVC size validation (minSize/maxSize)
  3. feat: per-path capacity budget tracking
  4. feat: resize controller for PVC expand and shrink
  5. feat: XFS project quota enforcement via quota-helper
  6. test: XFS quota e2e test suite (8 tests)
  7. docs: README section for volume capacity features
  8. chore: replace old examples with focused capacity examples
  9. test: CI-runnable XFS quota e2e via Kind + loopback XFS

Test plan

  • All commits compile (go build ./...)
  • All build tags compile (e2e, quota_e2e, quota_ci_e2e)
  • Kind e2e tests pass (size validation, capacity budget, path traversal)
  • XFS quota CI workflow passes on GitHub Actions (8/8 tests, loopback XFS)
  • XFS quota e2e tests pass against real k3s cluster with XFS disk
  • Existing upstream Kind e2e tests still pass

Closes #345

🤖 Generated with Claude Code

luctrate and others added 10 commits February 12, 2026 16:37
Move testdataFile, createCmd, runCmd, and deleteKustomizeDeployment to
helpers.go so both e2e and quota_e2e build tags can use them. Add
QUOTA_HELPER_IMAGE kind-load to SetupSuite, fix time.Tick to
time.NewTicker, add commonLabels to kustomization files, and rename
storageclass.yaml to storage-class.yaml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add minSize and maxSize fields to StorageClassConfigData and
StorageClassConfig, with validation in provisionFor() that rejects
PVCs outside the configured bounds. StorageClass parameters can
override config values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add CapacityTracker with TOCTOU-safe TryAllocate/TryResize for atomic
capacity checks. NodePathMap paths now support backward-compatible JSON
objects with optional maxCapacity field alongside plain strings.

- PathEntry/PathConfig types for per-path maxCapacity configuration
- NodePathMapData.Paths changed to []json.RawMessage with ParsePaths()
- initCapacityTracker rebuilds state from existing PVs on restart
- getPathOnNode performs capacity-aware path selection with shuffle
- provisionFor/deleteFor track and release capacity allocations
- storageClassConfigs in example-config.yaml with maxCapacity example
- E2E tests for capacity-within-budget and capacity-exhaustion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add workqueue-based ResizeController that watches PVCs for size changes
and handles both expansion and shrink operations via helper pods.

Provisioner changes:
- ActionTypeResize, quota type constants, resize annotations
- ResizeCommand field on ConfigData/Config for configurable resize scripts
- createHelperPodWithOutput() for resize operations needing stdout capture
- PodFailed handling with extractPodFailureReason/truncateLogs
- envVolQuotaType passed to helper pod environment
- Resize script key added to ConfigMap volume mounts

Deploy changes:
- RBAC: PVC update/patch, PVC/status update/patch for resize controller
- allowVolumeExpansion: true on StorageClass
- Default resize script in ConfigMap (du-based usage check)
- Helm chart: configmap template renders resize script, clusterrole updated

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add quota-helper sidecar image for filesystem-level XFS project quota
enforcement. The helper scripts handle setup (xfs_quota project init),
teardown (quota removal + project cleanup), and resize (limit update +
usage reporting) operations.

- package/quota-helper/: setup, teardown, resize scripts + helperPod.yaml
- package/Dockerfile.quota-helper: debian bookworm-slim + xfsprogs
- .github/workflows/build.yml: quota-helper image build steps (amd64/arm64)
- provisioner.go: read quotaEnforcement from SC parameters, write
  quotaTypeAnnotationKey on PV, read quota type from PV for teardown
- E2E test for quota rejection on unsupported filesystem

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add comprehensive e2e test suite for XFS project quota enforcement,
targeting real k3s cluster with XFS-formatted storage.

- quota_shared_test.go: 8 test functions + shared helpers under
  combined quota_e2e || quota_ci_e2e build tag
- quota_test.go: k3s-specific TestMain with in-cluster registry
  setup/teardown, port-forward, and image push helpers
- Test coverage: XFS enforce, backward compat, teardown cleanup,
  multi-PVC, space recovery, resize expand, shrink success, shrink
  rejection
- 10 testdata directories with kustomize overlays for each scenario

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document three volume capacity enforcement features: per-PVC size
validation, per-path capacity budget, and XFS project quota enforcement.
Include requirements for filesystem-level quota (XFS prjquota mount,
quota-helper image, privileged helper pod).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove obsolete examples/quota/ (CentOS 7-era example without flock,
resize, or auto-detect) and replace with three documented, kustomize-
based examples:

- examples/capacity-budget/: per-path maxCapacity budget (200Gi)
- examples/size-validation/: per-SC minSize/maxSize bounds (1Gi-50Gi)
- examples/xfs-quota/: filesystem-level XFS project quota enforcement

Each example includes a README with setup instructions and expected
behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Kind-based quota e2e test infrastructure that runs in GitHub Actions
without requiring a real XFS-formatted disk.

- quota_ci_test.go: Kind-based TestMain with loopback XFS setup
- kind-cluster-quota.yaml: Kind config with XFS extraMounts (Bidirectional)
- quota-ci-base/: kustomize overlay with local image names + IfNotPresent
- .github/workflows/quota-e2e.yml: GitHub Actions workflow that creates
  2G loopback XFS image, mounts with pquota, builds images, runs all 8
  shared quota test functions via Kind

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@luctrate
Copy link
Author

CI Results (fork test runs)

Workflow Status Link
XFS Quota E2E (8 tests via Kind + loopback XFS) ✅ Passed quota-e2e #1
Build (binary + docker — push step fails without credentials) ⚠️ Expected failure build #1

The build workflow fails at the Docker push step (no registry credentials on the fork), but the Go compilation and binary build steps succeed. The quota e2e workflow — which creates a loopback XFS filesystem, builds both images, spins up a Kind cluster, and runs all 8 quota test functions — passes cleanly.

@dharmjit
Copy link

@luctrate Is the PR ready for review? If yes, you can tag repo maintainers.

@luctrate
Copy link
Author

@derekbit The PR is ready for review.

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.

Capacity limit is ignored

2 participants