Open emsixteeen opened 7 months ago
It can be implemented with
mpiJobInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{FilterFunc: ...
in the enqeue process.
If we need it, I'd like to contribute.
It seems that cache.FilteringResourceEventHandler
will filter items once they have already been [successfully] listed / retrieved from the API server.
The use-case / issue here is when the mpi-operator
might not have permissions to list items in some namespace to begin with.
As a feature of functionality, FilteringResourceEventHandler
is the right way to run controller in a subset of namespaces, while the RBAC staffs is quite another thing.
@kuizhiqing totally agree that filtering is the way to go – assuming that RBAC permissions already allows for resources to be listed in all namespaces.
The current use-case / problem is that the Kubernetes cluster has a really restrictive RBAC configuration. With that being the case, because the controller is unable to list certain objects in the namespace to begin with (such as Secrets
), getting to to filtering can never happen (classic chicken-and-egg situation: to filter we need to list, but to list, we need RBAC permissions, and RBAC is restricting those operations).
In trying to solve this issue, I came across https://github.com/maistra/xns-informer, which (using codegen) creates a multi-namespace informer out of existing informers.
It seems that all the informers it generates are API-compatible with client-go
and mpi-operator
informers, and I've done some testing to validate that here: https://github.com/emsixteeen/mpi-operator/tree/xns-informers.
On the bright side, using these generated multi-namespace informers looks like it can solve this issue, but on the darker side, bringing in this third-party library, along with all it's dependencies and codegen is [probably] non-starter!
It would be better to contribute to client-go
project for the informer part if it worth doing so.
Doing a bit of light research^1 on the topic leads me to believe that there is no appetite for doing this in client-go
😞 ...
Been doing a bit more thinking about this and I'm wondering if having a level of abstraction / indirection when creating Informers could be an acceptable approach? 😕
In other words abstract the creation of an Informer to something more pluggable. When creating an Informer (such as here, instead of calling <package>.NewSharedInformerFactoryWithOptions()
, it would instead call a function that would return the desired <package>.SharedInformerFactory
interface. That way if one wanted to use something like generated multi-namespace Informers in place of the default Informer, as long as the interface returned was API compatible, then it could work.
I'll work on mocking something up to validate this idea, and [hopefully] update the issue with a prototype ...
Currently it doesn't seem possible to run the
mpi-operator
in a subset of namespaces. It's either all namespaces or a specific (single) namespace.This limitation looks like it comes from Kubernetes itself, where [generated] Informers are either scoped to a single namespace using
<factory>.WithNamespace(...)
, or if no namespace is provider, defaults tometav1.NamespaceAll
.An example (real-world) use-case for running the
mpi-operator
in subset of namespaces is when it's deployed to a Kubernetes cluster with tightly controlled cluster-wide permissions. E.g. when obtaining cluster-wide access toSecrets
is non-starter. In such a case, it's still possible to create a namespace-localRoleBinding
, whereby access can be granted to the Service Account running thempi-operator
for namespace-local secrets. However, because thempi-operator
operates only in either all namespaces or a single namespace, using namespace-localRoleBindings
isn't expandable beyond a single namespace.