...

Text file src/sigs.k8s.io/controller-runtime/FAQ.md

Documentation: sigs.k8s.io/controller-runtime

     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
     6affected objects should be mapped to a single type of root object, using
     7the `handler.EnqueueRequestForOwner` or `handler.EnqueueRequestsFromMapFunc` event
     8handlers, and potentially indices. Then, your Reconcile method should
     9attempt 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
    14should always reconcile state by reading all the state it needs, then
    15writing updates.  This allows your reconciler to correctly respond to
    16generic events, adjust to skipped or coalesced events, and easily deal
    17with application startup.  The controller will enqueue reconcile requests
    18for both old and new objects if a mapping changes, but it's your
    19responsibility to make sure you have enough information to be able clean
    20up 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
    25on 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
    40In general, write your controller with the assumption that information
    41will eventually be correct, but may be slightly out of date. Make sure
    42that your reconcile function enforces the entire state of the world each
    43time it runs.  If none of this works for you, you can always construct
    44a client that reads directly from the API server, but this is generally
    45considered to be a last resort, and the two approaches above should
    46generally 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),
    52but we generally recommend using
    53[envtest.Environment](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest#Environment)
    54to test against a real API server.  In our experience, tests using fake
    55clients gradually re-implement poorly-written impressions of a real API
    56server, 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
    76mapping between Go types and group-version-kinds in Kubernetes. In
    77general, your application should have its own Scheme containing the types
    78from the API groups that it needs (be they Kubernetes types or your own).
    79See the [scheme builder
    80docs](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/scheme) for
    81more information.

View as plain text