Viewing legacy documentation for Kubebuilder, check out the latest documentation instead.

Resource Example

This chapter walks through the definition of a new Resource call ContainerSet. ContainerSet contains the image and replicas fields, and ensures a Deployment with matching image and replicas it running in the cluster.

Create the scaffolding for a new resource using the kubebuilder cli:

$ kubebuilder create api --group workloads --version v1beta1 --kind ContainerSet

This creates several files, including the Resource schema definition in:


Type Definition

ContainerSet has 4 fields:

  • Spec contains the desired cluster state specified by the object. While much of the Spec is defined by users, unspecified parts may be filled in with defaults or by Controllers such as autoscalers.
  • Status contains only observed cluster state and is only written by controllers Status is not the source of truth for any information, but instead aggregates and publishes observed state.
  • TypeMeta contains metadata about the API itself - such as Group, Version, Kind.
  • ObjectMeta contains metadata about the specific object instance - such as the name, namespace, labels and annotations. ObjectMeta contains data common to most objects.
// +genclient

// ContainerSet creates a new Deployment running multiple replicas of a single container with the given
// image.
// +k8s:openapi-gen=true
// +resource:path=containersets
type ContainerSet struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    // spec contains the desired behavior of the ContainerSet
    Spec   ContainerSetSpec   `json:"spec,omitempty"`

    // status contains the last observed state of the ContainerSet
    Status ContainerSetStatus `json:"status,omitempty"`

Comment annotation directives

The definition contains several comment annotations of the form // +something. These are used to configure code generators to run against this code. The code generators will generate boilerplate functions and types to complete the Resource definition.

To learn more about how to use annotations in kubebuilder, refer to Generating CRD.


The ContainerSetSpec contains the container image and replica count, which should be read by the controller and used to create and manage a new Deployment. The Spec field contains desired state defined by the user or, if unspecified, field defaults or Controllers set values. An example of an unspecified field that could be owned by a Controller would be the replicas field, which may be set by autoscalers.

// ContainerSetSpec defines the desired state of ContainerSet
type ContainerSetSpec struct {
  // replicas is the number of replicas to maintain
  Replicas *int32 `json:"replicas,omitempty"`

  // image is the container image to run.  Image must have a tag.
  // +kubebuilder:validation:Pattern=.+:.+
  Image string `json:"image,omitempty"`


The ContainerSetStatus contains the number of healthy replicas, and should be set by the controller each time the ContainerSet is reconciled.

This field is propagated from the DeploymentStatus, and so the controller must watch for Deployment events to update the field.

// ContainerSetStatus defines the observed state of ContainerSet
type ContainerSetStatus struct {
  HealthyReplicas *int32 `json:"healthyReplicas,omitempty"`

Running Code Generators

While users don't directly modify generated code, the code must be regenerated after resources are modified by adding or removing fields. This is automatically done when running make.

Scaffolded Boilerplate

Kubebuilder scaffolds boilerplate code to register resources with the runtime.Scheme used to map go structs to GroupVersionKinds.

  • SchemeGroupVersion is the GroupVersion for the APIs in this package
  • SchemeBuilder should have every API in the package type added to it
var (    
  // SchemeGroupVersion is group version used to register these objects
  SchemeGroupVersion = schema.GroupVersion{Group: "", Version: "v1beta1"}

  // SchemeBuilder is used to add go types to the GroupVersionKind scheme
  SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion})
func init() {
  // Register the types with the SchemeBuilder
  SchemeBuilder.Register(&v1.ContainerSet{}, &v1.ContainerSetList{})