Controller Watch Functions

This chapter describes how to use the controller package functions to configure Controllers to watchResources.

Link to reference documentation

Watching the Controller Resource

Controllers may watch Resources and trigger Reconcile calls with the key of theobject from the watch event.

This example configures a controller to watch for Pod events, and call Reconcile withthe Pod key.

If Pod default/foo is created, updated or deleted, then Reconcile will be called withnamespace: default, name: foo

  1. // Annotation for generating RBAC role to Watch Pods
  2. // +kubebuilder:rbac:groups="",resources=pods,verbs=get;watch;list
  1. // Watch for Pod events, and enqueue a reconcile.Request to trigger a Reconcile
  2. err := c.Watch(
  3. &source.Kind{Type: &v1.Pod{}},
  4. &handler.EnqueueRequestForObject{})
  5. if err != nil {
  6. return err
  7. }
  1. // You can also watch unstructured objects
  2. u := &unstructured.Unstructured{}
  3. u.SetGroupVersionKind(schema.GroupVersionKind{
  4. Kind: "Pod",
  5. Group: "",
  6. Version: "v1",
  7. })
  8. err = c.Watch(&source.Kind{Type: u}, &handler.EnqueueRequestForObject{})

Watching Created Resources

Controllers may watch Resources of types they create and trigger Reconcile calls with the key ofthe Owner of the object.

This example configures a Controller to watch for Pod events, and call Reconcile withthe Owner ReplicaSet key. This is done by looking up the object referred to by the Owner referencefrom the watch event object.

  • Define a function to lookup the Owner from the key
  • Call WatchControllerOf with the Owned object and the function to lookup the ownerIf Pod default/foo-pod was created by ReplicaSet default/foo-rs, and the Pod is(re)created, updated or deleted, then Reconcile will be called with namespace: default, name: foo-rs

Note: This requires adding the following annotations to your Controller struct to ensure thecorrect RBAC rules are in place and informers have been started.

  1. // Annotation to generate RBAC roles to watch and update Pods
  2. // +kubebuilder:rbac:groups="",resources=pods,verbs=get;watch;list;create;update;delete
  1. // Watch for Pod events, and enqueue a reconcile.Request for the ReplicaSet in the OwnerReferences
  2. err := c.Watch(
  3. &source.Kind{Type: &corev1.Pod{}},
  4. &handler.EnqueueRequestForOwner{
  5. IsController: true,
  6. OwnerType: &appsv1.ReplicaSet{}})
  7. if err != nil {
  8. return err
  9. }

Watching Arbitrary Resources

Controllers may watch arbitrary Resources and map them to a key of the Resource managed by thecontroller. Controllers may even map an event to multiple keys, triggering Reconciles foreach key.

Example: To respond to cluster scaling events (e.g. the deletion or addition of Nodes),a Controller would watch Nodes and map the watch events to keys of objects managed bythe controller.

This simple example configures a Controller to watch for Pod events, and then reconciles objects withnames derived from the Pod's name.

If Pod default/foo is created, updated or deleted, then Reconcile will be called fornamespace: default, name: foo-parent-1 and for namespace: default, name: foo-parent-2.

Note: This requires adding the following annotations to your Controller struct to ensure thecorrect RBAC rules are in place and informers have been started.

  1. // +kubebuilder:rbac:groups="",resources=pods,verbs=get;watch;list
  1. // Define a mapping from the object in the event to one or more
  2. // objects to Reconcile
  3. mapFn := handler.ToRequestsFunc(
  4. func(a handler.MapObject) []reconcile.Request {
  5. return []reconcile.Request{
  6. {NamespacedName: types.NamespacedName{
  7. Name: a.Meta.GetName() + "-1",
  8. Namespace: a.Meta.GetNamespace(),
  9. }},
  10. {NamespacedName: types.NamespacedName{
  11. Name: a.Meta.GetName() + "-2",
  12. Namespace: a.Meta.GetNamespace(),
  13. }},
  14. }
  15. })
  16. // 'UpdateFunc' and 'CreateFunc' used to judge if a event about the object is
  17. // what we want. If that is true, the event will be processed by the reconciler.
  18. p := predicate.Funcs{
  19. UpdateFunc: func(e event.UpdateEvent) bool {
  20. // The object doesn't contain label "foo", so the event will be
  21. // ignored.
  22. if _, ok := e.MetaOld.GetLabels()["foo"]; !ok {
  23. return false
  24. }
  25. return e.ObjectOld != e.ObjectNew
  26. },
  27. CreateFunc: func(e event.CreateEvent) bool {
  28. if _, ok := e.Meta.GetLabels()["foo"]; !ok {
  29. return false
  30. }
  31. return true
  32. },
  33. }
  34. // Watch Deployments and trigger Reconciles for objects
  35. // mapped from the Deployment in the event
  36. err := c.Watch(
  37. &source.Kind{Type: &appsv1.Deployment{}},
  38. &handler.EnqueueRequestsFromMapFunc{
  39. ToRequests: mapFn,
  40. },
  41. // Comment it if default predicate fun is used.
  42. p)
  43. if err != nil {
  44. return err
  45. }

Watching Channels

Controllers may trigger Reconcile for events written to Channels. This is useful if the Controllerneeds to trigger a Reconcile in response to something other than a create / update / delete eventto a Kubernetes object. Note: in most situations this case is better handled by updating a Kubernetesobject with the external state that would trigger the Reconcile.

  1. events := make(chan event.GenericEvent)
  2. err := ctrl.Watch(
  3. &source.Channel{Source: events},
  4. &handler.EnqueueRequestForObject{},
  5. )
  6. if err != nil {
  7. return err
  8. }