Hello World

A new project may be scaffolded for a user by running kubebuilder init and then scaffolding anew API with kubebuilder create api. More on this topic inProject Creation and Structure

This chapter shows a simple Controller implementation using thecontroller-runtime builderlibraries to do most of the Controller configuration.

While Kubernetes APIs have typically have 3 components, (Resource, Controller, Manager), thisexample uses an existing Resource (ReplicaSet) and the builder package to hide many of the setup details.

For a more detailed look at creating Resources and Controllers that may be more complex,see the Resource, Controller andManager examples.

ReplicaSet Controller Setup

The example main program configures a new ReplicaSetController to watch forcreate/update/delete events for ReplicaSets and Pods.

  • On ReplicaSet create/update/delete events - Reconcile the ReplicaSet
  • On Pod create/update/delete events - Reconcile the ReplicaSet that created the Pod
  • Reconcile by calling ReplicaSetController.Reconcile with the Namespace and Name ofReplicaSet
  1. func main() {
  2. a, err := builder.SimpleController()
  3. // ReplicaSet is the Application type that
  4. // is Reconciled Respond to ReplicaSet events.
  5. ForType(&appsv1.ReplicaSet{}).
  6. // ReplicaSet creates Pods. Trigger
  7. // ReplicaSet Reconciles for Pod events.
  8. Owns(&corev1.Pod{}).
  9. // Call ReplicaSetController with the
  10. // Namespace / Name of the ReplicaSet
  11. Build(&ReplicaSetController{})
  12. if err != nil {
  13. log.Fatal(err)
  14. }
  15. log.Fatal(mrg.Start(signals.SetupSignalHandler()))
  16. }
  17. // ReplicaSetController is a simple Controller example implementation.
  18. type ReplicaSetController struct {
  19. client.Client
  20. }

ReplicaSet Implementation

ReplicaSetController implements reconcile.Reconciler. It takes the Namespace and Name fora ReplicaSet object and makes the state of the cluster match what is specified in the ReplicaSetat the time Reconcile is called. This typically means using a client.Client to readthe same of multiple objects, and perform create / update / delete as needed.

  • Implement InjectClient to get a client.Client from the application.Builder
  • Read the ReplicaSet object using the provided Namespace and Name
  • List the Pods matching the ReplicaSet selector
  • Set a Label on the ReplicaSet with the matching Pod countBecause the Controller watches for Pod events, the count will be updated any timea Pod is created or deleted.
  1. // InjectClient is called by the application.Builder
  2. // to provide a client.Client
  3. func (a *ReplicaSetController) InjectClient(
  4. c client.Client) error {
  5. a.Client = c
  6. return nil
  7. }
  8. // Reconcile reads the Pods for a ReplicaSet and writes
  9. // the count back as an annotation
  10. func (a *ReplicaSetController) Reconcile(
  11. req reconcile.Request) (reconcile.Result, error) {
  12. // Read the ReplicaSet
  13. rs := &appsv1.ReplicaSet{}
  14. err := a.Get(context.TODO(), req.NamespacedName, rs)
  15. if err != nil {
  16. return reconcile.Result{}, err
  17. }
  18. // List the Pods matching the PodTemplate Labels
  19. pods := &corev1.PodList{}
  20. err = a.List(context.TODO(),
  21. client.InNamespace(req.Namespace).
  22. MatchingLabels(rs.Spec.Template.Labels),
  23. pods)
  24. if err != nil {
  25. return reconcile.Result{}, err
  26. }
  27. // Update the ReplicaSet
  28. rs.Labels["selector-pod-count"] =
  29. fmt.Sprintf("%v", len(pods.Items))
  30. err = a.Update(context.TODO(), rs)
  31. if err != nil {
  32. return reconcile.Result{}, err
  33. }
  34. return reconcile.Result{}, nil
  35. }