feat: Multi Namespace support by camel-k operator, Namespace watcher …#6697
feat: Multi Namespace support by camel-k operator, Namespace watcher …#6697timmy-mathew-ah wants to merge 1 commit into
Conversation
…and fixed cluster wide RBAC issue
|
@squakez As discussed here's the PR I've created as inspiration for dynamic watching of namespace using labels. It was created before your fix was recently released with static namespaces so I haven't modified or merged that code here. |
squakez
left a comment
There was a problem hiding this comment.
Thanks for the work. It is interesting to see a different approach to solve the problem identified.
The goal of the recent works we're doing is to make the project lighter for an easier long term maintenance and I think that adding a new set of informers to watch namespaces is something that we should avoid for that reason. Also, the very same behavior can be easily performed with maintaining the static WATCH_NAMESPACE variable and updating the operator deployment when a new namespace has to be watched. If any, you can do a simple external sidecar container doing the same but separate from the main operator duties.
The goal of the new multi tenancy logic is to make sure the operator is picking the namespaces to watch by an admin, instead of letting the user picking them among any available. This is also a security measure we can discuss privately.
Summary
This PR is intended primarily as a proof of concept and a source of inspiration rather than something that is expected to be merged in its current form even though the implementation has been fully tested with the code before the release of this fix: #6616 which solves the issue but with a static list of namespaces rather than dynamic.
This PR introduces support for running a namespaced Camel K operator across multiple namespaces without requiring cluster-wide resource access. In addition to supporting a statically configured list of namespaces, the operator can dynamically discover namespaces based on Kubernetes labels and automatically adjust the set of watched namespaces as labels are added or removed.
Because
controller-runtimedoes not allow the watched namespace set to be modified after the manager has been created, the implementation uses a graceful self-restart strategy whenever the effective namespace set changes. This allows the operator to rebuild its caches with the updated namespace configuration while preserving the security benefits of namespaced RBAC.The implementation is fully compatible with the existing operator sharding mechanism and supports multiple operator shards watching the same dynamically discovered namespaces.
Detailed Design
This PR introduces two new, fully backward-compatible capabilities for the namespaced (non-global) Camel K operator:
WATCH_NAMESPACEnow accepts a comma-separated list of namespaces.WATCH_NAMESPACE_SELECTORenvironment variable enables the operator to automatically discover namespaces based on Kubernetes labels and update the watched namespace set as namespaces are added or removed.Motivation
On large multi-tenant clusters, running the operator in global mode requires cluster-wide access to workloads, secrets, and other resources, significantly increasing the blast radius if the operator is compromised. Conversely, the existing single-namespace deployment model does not scale well when many teams require their own namespaces.
This proposal provides a middle ground by allowing the operator to watch only explicitly authorized namespaces while keeping RBAC scoped to those namespaces instead of cluster level. Static namespace lists and dynamic label-based discovery are both supported.
Controller-runtime constraint
The design is primarily driven by a limitation of
controller-runtime. The namespace scope configured throughcache.Options.DefaultNamespacesis fixed when the manager is created and cannot be modified while the process is running. Although multiple namespaces are already supported, there is no supported mechanism for dynamically adding or removing namespaces from an existing cache.Several approaches were evaluated:
Cluster-scoped cache with filtering
Rejected because it requires cluster-wide resource permissions, defeating the primary security objective.
One cache per namespace managed dynamically
Rejected because it would require substantial changes to controller wiring and significantly increase implementation complexity.
Graceful restart when the watched namespace set changes
Chosen because it preserves scoped RBAC while allowing dynamic namespace discovery. When the effective watched namespace set changes, the operator gracefully shuts down, rebuilds its caches, and resumes reconciliation using the updated namespace configuration. Since reconciliation is level-based, no work is lost during the restart.
Implementation Overview
Static multi-namespace support
When
WATCH_NAMESPACEcontains multiple comma-separated namespaces (for exampleteam-a,team-b,team-c), the operator watches those namespaces together with its own installation namespace.WATCH_NAMESPACEempty or unset continues to enable global mode.RoleandRoleBindingresources in each watched namespace.Dynamic namespace discovery
When
WATCH_NAMESPACE_SELECTORis configured (for examplecamel-k-enabled=true), the operator computes its watched namespace set as the union of:WATCH_NAMESPACE, andA dedicated cluster-scoped namespace watcher monitors namespace events. When a namespace begins matching or stops matching the selector, the operator performs a graceful restart so that
controller-runtimerebuilds its caches using the updated namespace set.Before adding a namespace to the watched set, the operator performs a
SelfSubjectAccessReviewto verify that it has permission to watch Camel K resources in that namespace. Namespaces lacking the required RBAC are skipped with a warning rather than preventing the operator from starting or synchronizing its caches.To avoid excessive restarts, namespace changes are debounced and periodically re-evaluated. This also allows deployments where RBAC is installed after labels have already been applied to recover automatically without requiring any manual intervention.
The namespace watcher itself is leader-election aware, ensuring that only the active leader monitors namespace changes and initiates restarts.
Operator sharding compatibility
The implementation is fully compatible with the existing operator sharding model. Multiple operator shards can independently discover and watch the same label-selected namespaces while reconciling only resources assigned to their respective
operator.id.The accompanying RBAC helper also supports granting permissions to multiple operator ServiceAccounts within a single namespace, simplifying deployments that use multiple shards.
What this PR includes
WATCH_NAMESPACE.WATCH_NAMESPACE_SELECTOR.SelfSubjectAccessReview.The remaining sections describe the implementation details, installation examples, sharded deployment configuration, and related Helm changes.
Installing an operator that watches multiple namespaces by label
Install into the operator namespace (e.g.
camel-k) in dynamic mode:helm install camel-k ./helm/camel-k -n camel-k --create-namespace \ --set-string operator.global=false \ --set operator.watchNamespaceSelector="camel-k-enabled=true"This renders the operator + namespaced RBAC in
camel-k, plus a minimal cluster-scopednamespaces-readClusterRolebound to the operator SA.Onboard each team namespace — install the RBAC first, then label it (the label is the "ready"
signal):
The operator detects the change and self-restarts to watch
team-a. If you label before installingRBAC, the namespace is skipped with a warning and self-heals on the next periodic re-evaluation —
no re-labelling needed. Removing the label (or deleting the namespace) makes the operator stop
watching it; Integrations already running there keep running.
Static alternative (no cluster RBAC, fixed set, changes require
helm upgrade):helm install camel-k ./helm/camel-k -n camel-k --create-namespace \ --set-string operator.global=false \ --set "operator.watchNamespaces={team-a,team-b}" ./script/install_namespace_rbac.sh team-a camel-k camel-k-operator ./script/install_namespace_rbac.sh team-b camel-k camel-k-operatorCombining with multiple operator shards (optional)
Multiple operator releases can run side by side (each with a distinct
operator.operatorId, hence adistinct leader lease) and all watch the same label-selected namespaces, reconciling only the
resources whose
camel.apache.org/operator.idannotation matches their own id. For this model,grant every shard's ServiceAccount access in each watched namespace with a single multi-subject
binding: