A Kubernetes operator that automatically restarts deployments when secrets change. No more manual rollouts after secret updates!
- Automatic Deployment Restart - Deployments automatically restart when their secrets change
- Flexible Filtering - Watch specific namespaces and secrets using label selectors
- Zero Downtime - Uses rolling restart strategy (Kubernetes default)
- Self-Protection - Operator never restarts itself
- Multi-Architecture - Supports AMD64 and ARM64
- Production Ready - Full RBAC, security scanning, comprehensive tests
- Quick Start
- How It Works
- Installation
- Configuration
- Examples
- Development
- Documentation
- Contributing
- License
kubectl apply -f https://github.com/GDXbsv/traktor/releases/latest/download/install.yamlkubectl label namespace my-app environment=productionkubectl label secret my-secret -n my-app auto-refresh=enabledapiVersion: traktor.gdxcloud.net/v1alpha1
kind: SecretsRefresh
metadata:
name: production-watcher
namespace: default
spec:
namespaceSelector:
matchLabels:
environment: production
secretSelector:
matchLabels:
auto-refresh: enabledApply it:
kubectl apply -f secretsrefresh.yamlkubectl create secret generic my-secret \
--from-literal=password=newpassword \
-n my-app \
--dry-run=client -o yaml | kubectl apply -f -
# Watch deployments restart
kubectl get pods -n my-app -w- Watch Secrets - Operator watches for changes to secrets matching your selectors
- Detect Changes - When a secret is updated, the operator is notified
- Restart Deployments - All deployments in the same namespace are restarted by adding an annotation:
traktor.gdxcloud.net/restartedAt: "2024-01-30T10:30:00Z"
- Rolling Update - Kubernetes performs a rolling restart (zero downtime)
- Pods Get New Secrets - New pods automatically mount the updated secrets
Flow Diagram:
Secret Update β Operator Detects β Adds Annotation β Rolling Restart β New Pods with Updated Secrets
- Kubernetes cluster v1.11.3+
- kubectl v1.11.3+
- Cluster admin permissions (for RBAC setup)
Using kubectl:
# Install latest version
kubectl apply -f https://github.com/GDXbsv/traktor/releases/latest/download/install.yaml
# Install specific version
kubectl apply -f https://github.com/GDXbsv/traktor/releases/download/v0.0.1/install.yamlUsing Helm (from Artifact Hub/GitHub Pages):
# Add Helm repository
helm repo add traktor https://gdxbsv.github.io/traktor
helm repo update
# Install latest version
helm install traktor traktor/traktor
# Install specific version
helm install traktor traktor/traktor --version 0.0.1
# Install with custom values
helm install traktor traktor/traktor -f values.yamlUsing Helm (from GitHub Release):
# Install directly from release
helm install traktor https://github.com/GDXbsv/traktor/releases/latest/download/traktor-0.0.1.tgz# Clone repository
git clone https://github.com/GDXbsv/traktor.git
cd traktor
# Install CRDs
make install
# Deploy operator
make deploy IMG=docker.io/gdxbsv/traktor:v0.0.17# Clone repository
git clone https://github.com/GDXbsv/traktor.git
cd traktor
# Install with Helm
helm install traktor ./charts/traktor
# Install in custom namespace
helm install traktor ./charts/traktor -n traktor-system --create-namespace
# Install with custom values
helm install traktor ./charts/traktor -f my-values.yamlkubectl apply -k config/default# Check operator is running
kubectl get pods -n traktor-system
# Expected output:
# NAME READY STATUS RESTARTS AGE
# traktor-controller-manager-xxxxxxxxxx-xxxxx 1/1 Running 0 30s
# Check CRD is installed
kubectl get crd secretsrefreshes.traktor.gdxcloud.netapiVersion: traktor.gdxcloud.net/v1alpha1
kind: SecretsRefresh
metadata:
name: my-secrets-watcher
namespace: default
spec:
# Filter namespaces by labels
namespaceSelector:
matchLabels:
environment: production
team: platform
matchExpressions:
- key: app
operator: In
values: [backend, frontend]
# Filter secrets by labels
secretSelector:
matchLabels:
auto-refresh: enabled
matchExpressions:
- key: type
operator: NotIn
values: [system]Match by exact labels:
namespaceSelector:
matchLabels:
environment: productionMatch by expressions:
namespaceSelector:
matchExpressions:
- key: team
operator: In
values: [backend, frontend, platform]Watch all namespaces:
# Omit namespaceSelector entirely
spec:
secretSelector:
matchLabels:
auto-refresh: enabledMatch by labels:
secretSelector:
matchLabels:
auto-refresh: enabled
type: app-configWatch all secrets in matched namespaces:
spec:
namespaceSelector:
matchLabels:
environment: production
# Omit secretSelector to watch all secretsWatch all secrets in production namespaces:
apiVersion: traktor.gdxcloud.net/v1alpha1
kind: SecretsRefresh
metadata:
name: production-watcher
spec:
namespaceSelector:
matchLabels:
environment: production
secretSelector:
matchLabels:
auto-refresh: enabledSetup:
# Label namespaces
kubectl label namespace app-backend environment=production
kubectl label namespace app-frontend environment=production
# Label secrets
kubectl label secret db-password -n app-backend auto-refresh=enabled
kubectl label secret api-keys -n app-frontend auto-refresh=enabledWatch only database-related secrets:
apiVersion: traktor.gdxcloud.net/v1alpha1
kind: SecretsRefresh
metadata:
name: database-credentials-watcher
spec:
namespaceSelector:
matchLabels:
environment: production
secretSelector:
matchLabels:
type: database-credentialsWatch secrets across different teams:
apiVersion: traktor.gdxcloud.net/v1alpha1
kind: SecretsRefresh
metadata:
name: multi-team-watcher
spec:
namespaceSelector:
matchExpressions:
- key: team
operator: In
values: [backend, frontend, platform]
secretSelector:
matchLabels:
auto-refresh: enabledWatch all secrets in a specific namespace:
apiVersion: traktor.gdxcloud.net/v1alpha1
kind: SecretsRefresh
metadata:
name: staging-watcher
spec:
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: In
values: [staging]See config/samples/ for more complete examples:
quickstart.yaml- Simple getting started exampleexample-complete.yaml- All configuration optionsproduction-example.yaml- Real-world production setup
- Go v1.24.0+
- Docker v17.03+
- kubectl v1.11.3+
- Access to Kubernetes cluster
# Clone repository
git clone https://github.com/GDXbsv/traktor.git
cd traktor
# Install dependencies
go mod download
# Install CRDs
make install
# Run locally (connects to your kubeconfig cluster)
make run# Run unit tests
make test
# Run with coverage
go test ./... -coverprofile=coverage.out
go tool cover -html=coverage.out
# Run linter
make lint
# Run E2E tests
make test-e2e# Build binary
make build
# Build Docker image
make docker-build
# Build and push (multi-arch)
export IMG=docker.io/yourusername/traktor:dev
make docker-build docker-push IMG=$IMG
# Deploy to cluster
make deploy IMG=$IMGtraktor/
βββ api/v1alpha1/ # API definitions (CRDs)
βββ cmd/ # Main application entry point
βββ config/ # Kubernetes manifests
β βββ crd/ # CRD definitions
β βββ manager/ # Operator deployment
β βββ rbac/ # RBAC manifests
β βββ samples/ # Example configurations
βββ internal/controller/ # Controller logic
βββ test/e2e/ # End-to-end tests
βββ docs/ # Documentation
- Installation Guide - Detailed deployment instructions
- Helm Chart - Helm installation and configuration
- Artifact Hub - Discover on Artifact Hub
- Artifact Hub Setup - How to publish to Artifact Hub
- Testing Guide - How to run and write tests
- CI/CD Setup - Setting up GitHub Actions
- Examples - Configuration examples
- Architecture - How the operator works
All releases are scanned with Trivy for vulnerabilities. See Security tab for reports.
The operator requires the following permissions:
- Read secrets in all namespaces
- Read namespaces
- Update deployments
See config/rbac/ for complete RBAC configuration.
Please report security vulnerabilities to security@gdxcloud.net
# Tag the release
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0GitHub Actions will automatically:
- Run all tests
- Build multi-arch images
- Generate Kubernetes manifests
- Create GitHub release with artifacts
- Push Docker images with proper tags
Each release includes:
install.yaml- Complete installation manifesttraktor-vX.Y.Z.tgz- Helm chart packagetraktor-vX.Y.Z-manifests.tar.gz- All manifests packagedsbom-vX.Y.Z.spdx.json- Software Bill of Materialsindex.yaml- Helm repository index- Docker images for AMD64 and ARM64
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for your changes
- Run tests locally (
make test) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Go best practices
- Run
make lintbefore committing - Write tests for new features
- Update documentation as needed
Check operator logs:
kubectl logs -n traktor-system deployment/traktor-controller-manager -fVerify labels:
# Check namespace labels
kubectl get namespace my-app --show-labels
# Check secret labels
kubectl get secrets -n my-app --show-labelsVerify SecretsRefresh exists:
kubectl get secretsrefreshCheck for OOM:
kubectl describe pod -n traktor-system -l control-plane=controller-managerIncrease memory limit in config/manager/manager.yaml:
resources:
limits:
memory: 1Gi # Increase from 512Mi- Check Documentation
- Open an Issue
- Review Closed Issues
The operator exposes Prometheus metrics on port 8443:
controller_runtime_reconcile_total- Total reconciliationscontroller_runtime_reconcile_errors_total- Reconciliation errorsworkqueue_*- Work queue metrics
Access metrics:
kubectl port-forward -n traktor-system svc/traktor-controller-manager-metrics-service 8443:8443
curl -k https://localhost:8443/metricsCopyright 2026 GDX Cloud.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
If you find this project useful, please consider giving it a star! β
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Artifact Hub: traktor on Artifact Hub
- Helm Repository: https://gdxbsv.github.io/traktor
- Email: support@gdxcloud.net
- Website: https://gdxcloud.net
Built with β€οΈ using Kubebuilder