sigs.k8s.io/controller-runtime@v0.18.2/FAQ.md (about) 1 # FAQ 2 3 ### Q: How do I know which type of object a controller references? 4 5 **A**: Each controller should only reconcile one object type. Other 6 affected objects should be mapped to a single type of root object, using 7 the `handler.EnqueueRequestForOwner` or `handler.EnqueueRequestsFromMapFunc` event 8 handlers, and potentially indices. Then, your Reconcile method should 9 attempt to reconcile *all* state for that given root objects. 10 11 ### Q: How do I have different logic in my reconciler for different types of events (e.g. create, update, delete)? 12 13 **A**: You should not. Reconcile functions should be idempotent, and 14 should always reconcile state by reading all the state it needs, then 15 writing updates. This allows your reconciler to correctly respond to 16 generic events, adjust to skipped or coalesced events, and easily deal 17 with application startup. The controller will enqueue reconcile requests 18 for both old and new objects if a mapping changes, but it's your 19 responsibility to make sure you have enough information to be able clean 20 up state that's no longer referenced. 21 22 ### Q: My cache might be stale if I read from a cache! How should I deal with that? 23 24 **A**: There are several different approaches that can be taken, depending 25 on your situation. 26 27 - When you can, take advantage of optimistic locking: use deterministic 28 names for objects you create, so that the Kubernetes API server will 29 warn you if the object already exists. Many controllers in Kubernetes 30 take this approach: the StatefulSet controller appends a specific number 31 to each pod that it creates, while the Deployment controller hashes the 32 pod template spec and appends that. 33 34 - In the few cases when you cannot take advantage of deterministic names 35 (e.g. when using generateName), it may be useful in to track which 36 actions you took, and assume that they need to be repeated if they don't 37 occur after a given time (e.g. using a requeue result). This is what 38 the ReplicaSet controller does. 39 40 In general, write your controller with the assumption that information 41 will eventually be correct, but may be slightly out of date. Make sure 42 that your reconcile function enforces the entire state of the world each 43 time it runs. If none of this works for you, you can always construct 44 a client that reads directly from the API server, but this is generally 45 considered to be a last resort, and the two approaches above should 46 generally cover most circumstances. 47 48 ### Q: Where's the fake client? How do I use it? 49 50 **A**: The fake client 51 [exists](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client/fake), 52 but we generally recommend using 53 [envtest.Environment](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest#Environment) 54 to test against a real API server. In our experience, tests using fake 55 clients gradually re-implement poorly-written impressions of a real API 56 server, which leads to hard-to-maintain, complex test code. 57 58 ### Q: How should I write tests? Any suggestions for getting started? 59 60 - Use the aforementioned 61 [envtest.Environment](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest#Environment) 62 to spin up a real API server instead of trying to mock one out. 63 64 - Structure your tests to check that the state of the world is as you 65 expect it, *not* that a particular set of API calls were made, when 66 working with Kubernetes APIs. This will allow you to more easily 67 refactor and improve the internals of your controllers without changing 68 your tests. 69 70 - Remember that any time you're interacting with the API server, changes 71 may have some delay between write time and reconcile time. 72 73 ### Q: What are these errors about no Kind being registered for a type? 74 75 **A**: You're probably missing a fully-set-up Scheme. Schemes record the 76 mapping between Go types and group-version-kinds in Kubernetes. In 77 general, your application should have its own Scheme containing the types 78 from the API groups that it needs (be they Kubernetes types or your own). 79 See the [scheme builder 80 docs](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/scheme) for 81 more information.