Representing application state in the custom API
Let's begin by inspecting the generated api/v1alpha1/memcached_types.go
file for our Memcached API:
cat api/v1alpha1/memcached_types.go
In Kubernetes, every object (with some exceptions, like ConfigMap) includes spec
and status
fields. Kubernetes functions by reconciling actual cluster state (status
) with the desired state (spec
).
Also notice the +kubebuilder
comment markers found throughout the file. operator-sdk
makes use of a tool called controller-gen from the controller-tools project to generate utility code and Kubernetes YAML. More information on markers for configuring code generation can be found in the kubebuilder markers reference.
Modify the MemcachedSpec
and MemcachedStatus
of the Memcached
Custom Resource (CR) in the file api/v1alpha1/memcached_types.go
Change the boilerplate code to match the excerpt below:
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// MemcachedSpec defines the desired state of Memcached
type MemcachedSpec struct {
// +kubebuilder:validation:Minimum=0
// Size is the size of the memcached deployment
Size int32 `json:"size"`
}
// MemcachedStatus defines the observed state of Memcached
type MemcachedStatus struct {
// Nodes are the names of the memcached pods
Nodes []string `json:"nodes"`
}
Add the +kubebuilder:subresource:status
marker to add a status subresource to the CRD manifest so that the controller can update the CR status without changing the rest of the CR object:
// Memcached is the Schema for the memcacheds API
// +kubebuilder:printcolumn:JSONPath=".spec.size",name=Desired,type=string
// +kubebuilder:printcolumn:JSONPath=".status.nodes",name=Nodes,type=string
// +kubebuilder:subresource:status
type Memcached struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec MemcachedSpec `json:"spec,omitempty"`
Status MemcachedStatus `json:"status,omitempty"`
}
func init() {
SchemeBuilder.Register(&Memcached{}, &MemcachedList{})
}
After modifying any *_types.go
types definition file, run the following command to update the zz_generated.deepcopy.go
file:
make generate
The makefile target generate will invoke controller-gen to update the api/v1alpha1/zz_generated.deepcopy.go file to ensure the custom API's Go type definitions implement the runtime.Object interface that anything of type Kind must implement.
Now the make manifests
command can generate a customized CRD and YAML manifests for Operator objects.
The manifests
target will invoke controller-gen
to generate the CRD manifests at config/crd/bases/cache.example.com_memcacheds.yaml
. Because of the comment markers, notice there is a newly generated CRD yaml that reflects the spec.size
and status.nodes
OpenAPI v3 schema validation and customized print columns.
cat config/crd/bases/cache.example.com_memcacheds.yaml
Deploy your Memcached Custom Resource Definition to a running Kubernetes cluster:
kubectl apply -f config/crd/bases/cache.example.com_memcacheds.yaml
Confirm the CRD was successfully created:
kubectl get crd memcacheds.cache.example.com -o yaml