How to Create Kubernetes CRDs Using Golang and Master Controller Programming ️

How to Create Kubernetes CRDs Using Golang and Master Controller Programming ️


Kubernetes has revolutionized the way we manage containerized applications, but what happens when you need to extend its capabilities to fit your unique use case? Enter Custom Resource Definitions (CRDs) and Controllers! With these powerful tools, you can define your own resources and automate their management in Kubernetes. 🌟

In this article, we’ll explore how to create Kubernetes CRDs using Golang and dive into the world of controller programming with the Watcher-Informer model. Whether you’re building a custom operator or extending Kubernetes for your organization, this guide will help you get started. Let’s dive in! 💻

🤔 Why Create Custom Resources and Controllers?

Before we jump into the how, let’s talk about the why. Here are a few reasons you might want to create CRDs and controllers:

  1. Custom Workflows : You need to manage resources that Kubernetes doesn’t natively support.

  2. Automation : You want to automate complex tasks like provisioning, scaling, or healing.

  3. Extending Kubernetes : You’re building a platform or tool that integrates deeply with Kubernetes.

If any of these resonate with you, it’s time to roll up your sleeves and start building! 🛠️

🧰 What You’ll Need

Before we begin, make sure you have the following tools installed:

  • Go (Golang): We’ll use Go to write our CRD and controller. Install it from golang.org.

  • Kubebuilder or Operator SDK : These frameworks simplify the process of building Kubernetes operators. Install one of them.

  • Kubernetes Cluster : You’ll need a cluster to test your CRD and controller. Minikube or Kind are great for local development.

  • kubectl : The Kubernetes CLI tool for interacting with your cluster.

🚀 Step 1: Define Your Custom Resource (CRD)

Let’s create a CRD for a “Widget” resource.

  1. Scaffold Your Project :
    Use Kubebuilder to set up your project.
kubebuilder init --domain mydomain.com --repo github.com/yourusername/widget-operator  
kubebuilder create api --group widgets --version v1 --kind Widget

This generates the files you need for your CRD and controller.

2. Define the Widget Schema :
Open api/v1/widget_types.go and define your Widget resource.

package v1  

import (  
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"  
)  

// WidgetSpec defines the desired state of Widget  
type WidgetSpec struct {  
    Name string `json:"name"`  
    Description string `json:"description,omitempty"`  
    Replicas int32 `json:"replicas"`  
}  

// WidgetStatus defines the observed state of Widget  
type WidgetStatus struct {  
    AvailableReplicas int32 `json:"availableReplicas"`  
}  

//+kubebuilder:object:root=true  
//+kubebuilder:subresource:status  

// Widget is the Schema for the widgets API  
type Widget struct {  
    metav1.TypeMeta `json:",inline"`  
    metav1.ObjectMeta `json:"metadata,omitempty"`  

    Spec WidgetSpec `json:"spec,omitempty"`  
    Status WidgetStatus `json:"status,omitempty"`  
}  

//+kubebuilder:object:root=true  

// WidgetList contains a list of Widget  
type WidgetList struct {  
    metav1.TypeMeta `json:",inline"`  
    metav1.ListMeta `json:"metadata,omitempty"`  
    Items []Widget `json:"items"`  
}  

func init() {  
    SchemeBuilder.Register(&Widget{}, &WidgetList{})  
}
  1. Generate and Apply the CRD :
    Run these commands to generate and apply your CRD.
make manifests  
kubectl apply -f config/crd/bases/

Boom! Your CRD is now live in the cluster. 🎉

🛠️ Step 2: Build the Controller

Now, let’s build the controller to manage your Widgets.

  1. Understand the Watcher-Informer Model :
  • Watcher : Watches for changes to resources. 👀

  • Informer : Caches resource state and triggers events. 🤖

2. Implement the Reconcile Loop :
Open controllers/widget_controller.go and add your logic.

package controllers  

import (  
    "context"  
    "fmt"  

    "github.com/go-logr/logr"  
    "k8s.io/apimachinery/pkg/runtime"  
    ctrl "sigs.k8s.io/controller-runtime"  
    "sigs.k8s.io/controller-runtime/pkg/client"  

    widgetv1 "github.com/yourusername/widget-operator/api/v1"  
)  

// WidgetReconciler reconciles a Widget object  
type WidgetReconciler struct {  
    client.Client  
    Log logr.Logger  
    Scheme *runtime.Scheme  
}  

func (r *WidgetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {  
    log := r.Log.WithValues("widget", req.NamespacedName)  

    // Fetch the Widget  
    var widget widgetv1.Widget  
    if err := r.Get(ctx, req.NamespacedName, &widget); err != nil {  
        return ctrl.Result{}, client.IgnoreNotFound(err)  
    }  

    // Your logic here  
    log.Info("Reconciling Widget", "name", widget.Name)  
    fmt.Printf("Widget Spec: %+v\n", widget.Spec)  

    // Update status  
    widget.Status.AvailableReplicas = widget.Spec.Replicas  
    if err := r.Status().Update(ctx, &widget); err != nil {  
        return ctrl.Result{}, err  
    }  

    return ctrl.Result{}, nil  
}  

func (r *WidgetReconciler) SetupWithManager(mgr ctrl.Manager) error {  
    return ctrl.NewControllerManagedBy(mgr).  
        For(&widgetv1.Widget{}).  
        Complete(r)  
}
  1. Run the Controller :
    Start your controller locally to test it.
make run

🧪 Step 3: Test Your CRD and Controller

  1. Create a Widget Resource :
    Create a widget-example.yaml file:
apiVersion: widgets.mydomain.com/v1  
kind: Widget  
metadata:  
  name: example-widget  
spec:  
  name: "example-widget"  
  description: "This is an example widget."  
  replicas: 3
  1. Apply the Resource :
    Use kubectl to apply it.
kubectl apply -f widget-example.yaml
  1. Check the Logs :
    Watch your controller logs to see the magic happen! ✨

🚀 Step 4: Deploy Your Controller

Once it works locally, deploy it to your cluster.

  1. Build and Push the Docker Image :
make docker-build docker-push IMG=<your-docker-image>
  1. Deploy the Controller
make deploy IMG=<your-docker-image>

🎉 You Did It!

You’ve just:
✅ Created a Custom Resource Definition (CRD)
✅ Built a Controller using the Watcher-Informer model
✅ Automated your custom resources like a pro! 🚀

Now go forth and extend Kubernetes to fit YOUR needs! 🌟