That blog post is about some basics how to extend a Custom Resource Definition
in a GO Operator.
For an Operator implementation you need a Custom Resource Definition
and a controller implementation.
The Custom Resource Definition
for an operator is the basic first step to extend the Kubernetes API with your own functionalities. Usually you create a Custom Resource Definition
before you write the controller for your operator.
That blog post is structured in:
- Understand a bit how the Operator SDK supports you during the implementation of a
Custom Resource Definition
works - Extend an existing
Custom Resource Definition
by adding a new section and a new attribute
The 45 min live stream about “Debugging a GO Operator and extend spec section of a custom resource definition” also cover the topic in that blog post.
Understand how the Operator SDK supports you during the implementation of Custom Resource Definition
¶ works
The Operator SDK creates for you all needed code to write your own Custom Resource Definition
for your Operator. I use as an example for the usage of the Operator SDK the code in the GitHub project Example Tenancy Frontend Operator.
In that example code you find a file called tenancyfrontend_types.go
. In that file we define the content of our Custom Resource Definition
. The concrete Custom Resource Definition
is saved in the file tenancyfrontends.multitenancy.example.net
. The tenancyfrontends.multitenancy.example.net
will be automated created for you by the Operator SDK.
The following code is an extraction of the tenancyfrontends.multitenancy.example.net
file.
REMEMBER: You never have to touch that, because this file is automatically created for you.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: tenancyfrontends.multitenancy.example.net
spec:
group: multitenancy.example.net
names:
kind: TenancyFrontend
listKind: TenancyFrontendList
plural: tenancyfrontends
singular: tenancyfrontend
You find an example outline for creating a Kubernetes object for your Custom Resource Definition
in the file multitenancy_v1alpha1_tenancyfrontend.yaml
. You just use the kubectl apply -f
to create an object based on your Custom Resource Definition
. The following code shows an example to create an object of the TenancyFrontend Custom Resource Definition
in Kubernetes.
apiVersion: multitenancy.example.net/v1alpha1
kind: TenancyFrontend
metadata:
name: tenancyfrontendsample
spec:
# TODO(user): Add fields here
size: 1
displayname: MyFrontendDisplayname
The following diagram extracts some content of the tenancyfrontend_types.go
file. The focus of this diagram is to display the dependencies of the structs which do represent the Custom Resource Definition
in the GO source code.
With that understanding we will later extend the TenancyFrontend
Custom Resource Definition
.

- The
TenancyFrontend
contains meta definitions for theCustom Resource Definition
for the Operator and links to own defined sections (for example the sections “spec
” and “status
” are predefined when you create a GO project with the Operator SDK)- The following code example is an extract of the
multitenancy_v1alpha1_tenancyfrontend.yaml
- The following code example is an extract of the
kind: TenancyFrontend
metadata:
name: tenancyfrontendsample
- The
TenancyFrontendStatus
andTenancyFrontendSpec
to contain the own defined values you plan to use inside your controller implementation of the Operator. When an object of theTenancyFrontend
Custom Resource Definition
will be created, the controller will create one Pod for the application and the headline of the frontend application will display the text MyFrontendDisplayname.
spec:
# TODO(user): Add fields here
size: 1
displayname: MyFrontendDisplayname
Extend an existing Custom Resource Definition
by adding a new section and a new attribute ¶
In this example we just want to add an additional section into our existing specification. You find the final example code in the following GitHub project: Example Tenancy Frontend Operator in the cdr-def-example
branch.
The image below does reflect the changes in dependencies which will be made in the next steps, when you add the MySection to the Custom Resource Definition
.

Step 1: Create a new struct called TenancyFrontendMySection
in the tenancyfrontend_types.go
file¶
// TenancyFrontendMySection defines the desired state of TenancyFrontend
type TenancyFrontendMySection struct {
MyValue string `json:"myvalue,omitempty"`
}
Step 2: Add the name of the struct TenancyFrontendMySection
to the TenancyFrontend
struct in the tenancyfrontend_types.go
file¶
// TenancyFrontend is the Schema for the tenancyfrontends API
type TenancyFrontend struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec TenancyFrontendSpec `json:"spec,omitempty"`
Status TenancyFrontendStatus `json:"status,omitempty"`
MySection TenancyFrontendMySection `json:"mysection,omitempty"`
}
Step 3: Run make generate
command¶
make generate
That command changes the zz_generated.deepcopy.go
file for you.
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TenancyFrontend) DeepCopyInto(out *TenancyFrontend) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
out.Status = in.Status
out.MySection = in.MySection
}
...
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TenancyFrontendMySection) DeepCopyInto(out *TenancyFrontendMySection) {
*out = *in
}
...
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenancyFrontendMySection.
func (in *TenancyFrontendMySection) DeepCopy() *TenancyFrontendMySection {
if in == nil {
return nil
}
out := new(TenancyFrontendMySection)
in.DeepCopyInto(out)
return out
}
Step 4: Run make manifests
command¶
make manifests
That command changes the file multitenancy_v1alpha1_tenancyfrontend.yaml
mysection:
description: TenancyFrontendMySection defines the desired state of TenancyFrontend
properties:
myvalue:
type: string
type: object
Step 5: Use the newly defined entry in the controller reconcile function of the Operator¶

- Example code:
...
logger.Info("Info: The new vaule [" + tenancyfrontend.MySection.MyValue + "]")
...
Step 6: Update the multitenancy_v1alpha1_tenancyfrontend.yaml
file¶
apiVersion: multitenancy.example.net/v1alpha1
kind: TenancyFrontend
metadata:
name: tenancyfrontendsample
mysection:
myvalue: Hello-this-is-my-value-for-the-new-section
spec:
# TODO(user): Add fields here
size: 1
displayname: MyFrontendDisplayname
Step 7: Start the operator locally and ensure you are connect to a Kubernetes Cluster¶
make install run
Step 8: Apply a new Custom Resource object¶
kubectl apply -f config/samples/multitenancy_v1alpha1_tenancyfrontend.yaml
Step 9: Verify the new value for your section is shown¶
1.647000486675238e+09 INFO controller.tenancyfrontend Verify if a CRD of TenancyFrontend exists {"reconciler group": "multitenancy.example.net", "reconciler kind": "TenancyFrontend", "name": "tenancyfrontendsample", "namespace": "default"}
1.647000762421584e+09 INFO controller.tenancyfrontend Info: The new vaule [Hello-this-is-my-value-for-the-new-section] {"reconciler group": "multitenancy.example.net", "reconciler kind": "TenancyFrontend", "name": "tenancyfrontendsample", "namespace": "default"}
- Example when you use debug

Summary¶
It is awesome and powerful how easy it is to customize the content for the Custom Resource Definition
when you use the Operator SDK.
I hope this was useful to you and let’s see what’s next?
Greetings,
Thomas
#operator, #go, #operatorsdk, #kubernetes, #buildlabs4saas, #crd, #customresourcedefinition, #operatorlearningjourney
Leave a Reply