An automated cleanup controller for orphaned ZFSVolume Custom Resource Definitions (CRDs) in Kubernetes clusters using OpenEBS with ZFS storage.
This controller identifies ZFSVolumes that are no longer associated with any PersistentVolume (PV) or PersistentVolumeClaim (PVC) and safely removes them to prevent resource accumulation and maintain cluster hygiene.
ghcr.io/blackdark/openebs-zfs-cleanup-controller:latest
docker.io/blackdark93/openebs-zfs-cleanup-controller:latest- 🔍 Automated detection of orphaned ZFSVolume CRDs
- 🛡️ Safe deletion with comprehensive validation
- 🔄 Unified binary supporting both CronJob and long-running deployment modes
- 🎛️ Mode selection via
--modeflag (controller=default orcronjob) - 📊 Comprehensive logging and Prometheus metrics
- 🧪 Configurable dry-run mode for safe testing
- 🔐 Minimal RBAC permissions following security best practices
This project uses a single binary that can operate in two modes:
- 🚀 Controller Mode (
--mode=controller): Long-running service that continuously monitors and cleans up orphaned ZFSVolumes - ⏰ CronJob Mode (
--mode=cronjob): One-time execution that performs cleanup and exits
# Controller mode (default)
./bin/manager
./bin/manager --mode=controller
# CronJob mode
./bin/manager --mode=cronjob --timeout=5mThe same binary and Docker image can be used for both deployment types, simplifying the build and deployment process.
- ☸️ Kubernetes cluster with OpenEBS ZFS CSI driver installed
- 🐹 Go 1.21+ for development
- 🐳 Docker for containerized deployment
# Build the unified binary (works for both controller and cronjob modes)
make build
# Build Docker image
make docker-build# Run as controller (long-running service) - default mode
make run
# Run as one-time job
make run-cronjob
# Or run directly with mode flags
./bin/manager --mode=controller
./bin/manager --mode=cronjob --timeout=10mThe controller is configured via environment variables:
| Variable | Default | Description |
|---|---|---|
DRY_RUN |
false |
🧪 Enable dry-run mode (log only, no deletions) |
RECONCILE_INTERVAL |
1h |
⏱️ Reconciliation interval for controller mode |
MAX_CONCURRENT_RECONCILES |
1 |
🔄 Maximum concurrent reconciliation operations |
NAMESPACE_FILTER |
"" |
🏷️ Filter to specific namespace (empty = all namespaces) |
LOG_LEVEL |
info |
📝 Log level (debug, info, warn, error) |
Create a .env file with the following content:
DRY_RUN=true
RECONCILE_INTERVAL=30m
MAX_CONCURRENT_RECONCILES=2
NAMESPACE_FILTER="default"
LOG_LEVEL=debug
You can deploy via helm charts provided under charts or with the deployment yamls provided in deploy.
On startup, the controller validates all configuration fields. If a value is invalid, a clear error message is printed and the process exits. Example:
invalid configuration for RECONCILE_INTERVAL=0s: must be greater than 0
Refer to the ⚙️ Configuration section for valid ranges and options.
- ❌ Controller fails to start:
- 📋 Check logs for configuration validation errors.
- ✅ Ensure all required environment variables are set and valid.
- 🔍 No orphaned volumes detected:
- 🔍 Verify that ZFSVolume, PV, and PVC resources exist and are not associated.
- 🏷️ Check label and namespace filters.
- 🔐 Permission errors:
- 🔐 Ensure RBAC roles and ServiceAccount are correctly configured.
- 📄 See
deploy/rbac.yamlfor minimal required permissions.
- ⚡ API rate limiting:
- ⚙️ Adjust
API_RATE_LIMITandAPI_BURSTsettings if you see throttling errors.
- ⚙️ Adjust
- 📊 Metrics not exposed:
- 🔌 Confirm
METRICS_PORTis set and port is open in your deployment.
- 🔌 Confirm
See the config/ directory for Kubernetes deployment manifests.
# Run tests
make test
# Format code
make fmt
# Run linter
make vet# build the binaries
make build
# Load envs
echo "DRY_RUN=true" > .env
echo "RECONCILE_INTERVAL=30s" >> .env
echo "LOG_LEVEL=debug" >> .env
export $(cat .env | xargs)
./bin/manager --mode=cronjobThis project is licensed under the Apache License 2.0.