K8s Namespace Sync is a Kubernetes controller that automatically synchronizes Secrets and ConfigMaps across multiple namespaces within a Kubernetes cluster.
- Automatic synchronization of Secrets and ConfigMaps across namespaces
- Automatic detection and synchronization of changes in source namespace
- Support for selective namespace targeting
- Automatic exclusion of system namespaces (kube-system, kube-public, etc.)
- Support for manually excluding specific namespaces
- Prometheus metrics support
- Synchronization status monitoring
- Resource filtering support with glob pattern matching
- Selective resource synchronization based on name patterns
The controller:
- Watches for changes in the source namespace's Secrets and ConfigMaps
- Automatically syncs changes to all target namespaces
- Maintains consistency by cleaning up resources when source is deleted
- Uses finalizers to ensure proper cleanup during deletion
kubectl apply -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/install.yaml
apiVersion: v1
kind: Secret
metadata:
name: test-secret
namespace: default
type: Opaque
stringData:
username: admin
password: secret123
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test-configmap
namespace: default
data:
key1: value1
key2: value2
if you want to test with multiple resources, you can apply the following resources:
kubectl apply -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/test-configmap-secret/test-configmap.yaml
kubectl apply -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/test-configmap-secret/test-configmap2.yaml
kubectl apply -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/test-configmap-secret/test-secret.yaml
kubectl apply -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/test-configmap-secret/test-secret2.yaml
- Important Note: Each CR should be tested individually to avoid conflicts. After testing each CR, make sure to delete it before testing the next one.
Basic synchronization (sync to all namespaces):
apiVersion: sync.nsync.dev/v1
kind: NamespaceSync
metadata:
name: namespacesync-sample
finalizers:
- namespacesync.nsync.dev/finalizer
spec:
sourceNamespace: default
configMapName:
- test-configmap
secretName:
- test-secret
Basic apply and test:
kubectl apply -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/sync_v1_namespacesync.yaml
# Check the resources in the target namespaces
k get namespacesyncs.sync.nsync.dev
# Delete the CR after testing
kubectl delete -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/sync_v1_namespacesync.yaml
With specific target namespaces:
apiVersion: sync.nsync.dev/v1
kind: NamespaceSync
metadata:
name: namespacesync-sample-targets
finalizers:
- namespacesync.nsync.dev/finalizer
spec:
sourceNamespace: default
targetNamespaces: # Only sync to these namespaces
- test-ns1
- test-ns2
configMapName:
- test-configmap
secretName:
- test-secret
Target apply and test:
kubectl apply -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/sync_v1_namespacesync_target.yaml
# Check the resources in the target namespaces
kubectl get namespacesyncs.sync.nsync.dev
# Create target namespaces
kubectl create ns test-ns1
kubectl create ns test-ns2
# Check the resources in the target namespaces
kubectl get secret,configmap -n test-ns1
kubectl get secret,configmap -n test-ns2
# Check the resources in the another namespace
kubectl get secret,configmap -n <another-namespace>
# Delete the CR after testing
kubectl delete -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/sync_v1_namespacesync_target.yaml
With excluded namespaces:
apiVersion: sync.nsync.dev/v1
kind: NamespaceSync
metadata:
name: namespacesync-sample
finalizers:
- namespacesync.nsync.dev/finalizer
spec:
sourceNamespace: default
configMapName:
- test-configmap
- test-configmap2
secretName:
- test-secret
- test-secret2
exclude:
- test-ns2
- test-ns3
Exclude apply and test:
kubectl apply -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/sync_v1_namespacesync_exclude.yaml
# Check the resources in the target namespaces
k get namespacesyncs.sync.nsync.dev
# Create target namespaces
kubectl create ns test-ns2
kubectl create ns test-ns3
# Check the resources in the target namespaces
kubectl get secret,configmap -n test-ns2
kubectl get secret,configmap -n test-ns3
# Check the resources in the another namespace
kubectl get secret,configmap -n <another-namespace>
# Delete the CR after testing
kubectl delete -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/sync_v1_namespacesync_exclude.yaml
With resource filters:
apiVersion: sync.nsync.dev/v1
kind: NamespaceSync
metadata:
name: namespacesync-filter-sample
finalizers:
- namespacesync.nsync.dev/finalizer
spec:
sourceNamespace: default
configMapName:
- test-configmap
- test-configmap2
secretName:
- test-secret
- test-secret2
resourceFilters:
configMaps:
# include:
# - "test-configmap*" # All ConfigMaps starting with test-configmap
exclude:
- "*2" # Exclude ConfigMaps ending with 2
secrets:
# include:
# - "test-secret*" # All Secrets starting with test-secret
exclude:
- "*2" # Exclude Secrets ending with 2
exclude:
- test-ns2
- test-ns3
Filter apply and test:
kubectl apply -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/sync_v1_namespacesync_filter.yaml
# Check the resources in the target namespaces
kubectl get namespacesyncs.sync.nsync.dev
# Create target namespaces
kubectl create ns test-ns2
kubectl create ns test-ns3
# Check the resources in the target namespaces
kubectl get secret,configmap -n test-ns2
kubectl get secret,configmap -n test-ns3
# Check the resources in the another namespace
# Check the resources in the filtered configmap
kubectl get secret,configmap -n <another-namespace>
# Delete the CR after testing
kubectl delete -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/examples/sync_v1_namespacesync_filter.yaml
- If
targetNamespaces
is not specified, resources will be synced to all namespaces (except excluded ones) - If
targetNamespaces
is specified, resources will only be synced to the listed namespaces - System namespaces and source namespace are always excluded
exclude
list takes precedence overtargetNamespaces
- Changes in source resources are automatically detected and synced in real-time
- Deleting a resource from the source namespace will remove it from all synced namespaces
- Labels and annotations from the source resources are preserved in synced resources
- When the NamespaceSync CR is deleted, all synced resources are automatically cleaned up
- Finalizer ensures proper cleanup of synced resources before CR deletion
- Supports both include and exclude patterns for ConfigMaps and Secrets
- Uses glob pattern matching (e.g., "*" for any characters)
- Include patterns specify which resources to sync
- Exclude patterns specify which resources to skip
- If both include and exclude patterns are specified, exclude takes precedence
- Patterns are matched against resource names
- Can be combined with namespace targeting and exclusion
kubectl get namespacesync namespacesync-sample -o yaml
kubectl get secret test-secret -n target-namespace
kubectl get configmap test-configmap -n target-namespace
The following namespaces are automatically excluded from synchronization:
- kube-system
- kube-public
- kube-node-lease
- k8s-namespace-sync-system
Additionally, you can manually exclude specific namespaces using the exclude
field in the NamespaceSync CR.
Common issues and solutions:
-
Resources not syncing:
- Check if namespace is in exclude list
- Verify controller logs:
kubectl logs -n namespacesync-system -l control-plane=controller-manager
- Check NamespaceSync status:
kubectl get namespacesync <name> -o yaml
-
Permission issues:
- Ensure RBAC permissions are properly configured
- Check if ServiceAccount has necessary permissions
-
Cleanup issues:
- Ensure finalizer is present in CR
- Check controller logs for cleanup errors
- Delete the ConfigMap and Secret resources:
kubectl delete configmap test-configmap
kubectl delete secret test-secret
kubectl delete configmap test-configmap2
kubectl delete secret test-secret2
- Remove the NamespaceSync CR:
kubectl delete namespacesync --all
- Remove the controller:
kubectl delete -f https://raw.githubusercontent.com/somaz94/k8s-namespace-sync/main/release/install.yaml
All required tools will be automatically downloaded to ./bin
directory when running:
make install-tools
Or you can install individual tools:
# Install controller-gen
make controller-gen # v0.16.4
# Install kustomize
make kustomize # v5.5.0
# Install setup-envtest
make envtest # v0.19.0
# Install golangci-lint
make golangci-lint # v1.61.0
Manual installation locations:
- All tools will be installed in
./bin
directory - Specific versions:
- controller-gen v0.16.4
- kustomize v5.5.0
- setup-envtest v0.19.0
- golangci-lint v1.61.0
Note: The binary directory (./bin
) is git-ignored and will be created when needed.
Issues and pull requests are welcome.
This project is licensed under the MIT License - see the LICENSE file for details.