You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: contributors/devel/sig-api-machinery/controllers.md
+39-33Lines changed: 39 additions & 33 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,9 +18,9 @@ Watches, etc, are all merely optimizations of this logic.
18
18
19
19
When you're writing controllers, there are few guidelines that will help make sure you get the results and performance you're looking for.
20
20
21
-
1. Operate on one item at a time. If you use a `workqueue.Interface`, you'll be able to queue changes for a particular resource and later pop them in multiple “worker” gofuncs with a guarantee that no two gofuncs will work on the same item at the same time.
21
+
1. Operate on one item at a time. If you use a `workqueue.Interface`, you'll be able to queue references to particular objects and later pop them in multiple “worker” goroutines with a guarantee that no two goroutines will work on the same item at the same time.
22
22
23
-
Many controllers must trigger off multiple resources (I need to "check X if Y changes"), but nearly all controllers can collapse those into a queue of “check this X” based on relationships. For instance, a ReplicaSet controller needs to react to a pod being deleted, but it does that by finding the related ReplicaSets and queuing those.
23
+
Many controllers must trigger off multiple resources (I need to "check X if Y changes"), but nearly all controllers can collapse those into a queue of “check this X” based on relationships. For instance, a ReplicaSet controller needs to react to a pod being deleted, but it does that by finding the related ReplicaSets and queuing references to those.
24
24
25
25
1. Random ordering between resources. When controllers queue off multiple types of resources, there is no guarantee of ordering amongst those resources.
26
26
@@ -44,17 +44,19 @@ When you're writing controllers, there are few guidelines that will help make su
44
44
45
45
1. Wait for your secondary caches. Many controllers have primary and secondary resources. Primary resources are the resources that you'll be updating `Status` for. Secondary resources are resources that you'll be managing (creating/deleting) or using for lookups.
46
46
47
-
Use the `framework.WaitForCacheSync` function to wait for your secondary caches before starting your primary sync functions. This will make sure that things like a Pod count for a ReplicaSet isn't working off of known out of date information that results in thrashing.
47
+
Use the `cache.WaitForCacheSync` function to wait for your secondary caches before starting your primary sync functions. This will make sure that things like a Pod count for a ReplicaSet isn't working off of known out of date information that results in thrashing.
48
48
49
49
1. There are other actors in the system. Just because you haven't changed an object doesn't mean that somebody else hasn't.
50
50
51
51
Don't forget that the current state may change at any moment--it's not sufficient to just watch the desired state. If you use the absence of objects in the desired state to indicate that things in the current state should be deleted, make sure you don't have a bug in your observation code (e.g., act before your cache has filled).
52
52
53
+
1. Failures happen, and their detection in Kubernetes is imperfect. Run multiple copies of your controller pod (e.g., via a `Deployment`), with one copy active and the other(s) ready to take over at a moment's notice. Use `k8s.io/client-go/tools/leader-election` for that. Even leader election is imperfect; even when using leader election it is still possible --- although very unlikely --- that multiple copies of your controller may be active.
54
+
53
55
1. Percolate errors to the top level for consistent re-queuing. We have a `workqueue.RateLimitingInterface` to allow simple requeuing with reasonable backoffs.
54
56
55
-
Your main controller func should return an error when requeuing is necessary. When it isn't, it should use `utilruntime.HandleError` and return nil instead. This makes it very easy for reviewers to inspect error handling cases and to be confident that your controller doesn't accidentally lose things it should retry for.
57
+
Your main controller func should return an error when requeuing is necessary. When it isn't, it should use `utilruntime.HandleErrorWithContext` and return nil instead. This makes it very easy for reviewers to inspect error handling cases and to be confident that your controller doesn't accidentally lose things it should retry for.
56
58
57
-
1.Watches and Informers will “sync”. Periodically, they will deliver every matching object in the cluster to your `Update` method. This is good for cases where you may need to take additional action on the object, but sometimes you know there won't be more work to do.
59
+
1. Informers can periodically “resync”. This means to call the Update event handler on every object in the informer's local cache. This is good for cases where you may need to take additional action on the object, but sometimes you know there won't be more work to do.
58
60
59
61
In cases where you are *certain* that you don't need to requeue items when there are no new changes, you can compare the resource version of the old and new objects. If they are the same, you skip requeuing the work. Be careful when you do this. If you ever skip requeuing your item on failures, you could fail, not requeue, and then never retry that item again.
60
62
@@ -80,7 +82,7 @@ type Controller struct {
80
82
81
83
// queue is where incoming work is placed to de-dup and to allow "easy"
0 commit comments