3. kubebuilder

3.1. Install

$ curl -LO https://github.com/kubernetes-sigs/kubebuilder/releases/download/v4.6.0/kubebuilder_linux_amd64
$ chmod +x kubebuilder_linux_amd64
$ sudo cp kubebuilder_linux_amd64 /usr/local/bin/kubebuilder

Show version:

$ kubebuilder version
Version: cmd.version{KubeBuilderVersion:"4.6.0", KubernetesVendor:"1.33.0", GitCommit:"cd90bd82a2d692fbf63ba0231699e2e3dc0b6a08", BuildDate:"2025-05-24T23:24:02Z", GoOs:"linux", GoArch:"amd64"}

3.2. Usage

3.2.1. Init a project

$ mkdir k8app
$ cd k8app
$ kubebuilder init --domain lasyard.github.io --repo github.com/lasyard/coding-go/k8app
INFO Writing kustomize manifests for you to edit... 
INFO Writing scaffold for you to edit...          
INFO Get controller runtime:

INFO Update dependencies:

3.2.2. Create an API

$ kubebuilder create api --group app --version v1 --kind App
INFO Create Resource [y/n]                        
y
INFO Create Controller [y/n]                      
y
INFO Writing kustomize manifests for you to edit... 
INFO Writing scaffold for you to edit...          
INFO api/v1/app_types.go                          
INFO api/v1/groupversion_info.go                  
INFO internal/controller/suite_test.go            
INFO internal/controller/app_controller.go        
INFO internal/controller/app_controller_test.go   
INFO Update dependencies:

INFO Running make:

Generate manifests:

$ make manifests
/home/ubuntu/workspace/coding-go/k8app/bin/controller-gen rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases

3.2.3. Run on cluster

Build the image and push it to a repository:

$ make docker-build IMG=las3:443/lasyard.github.io/app:latest
$ make docker-push IMG=las3:443/lasyard.github.io/app:latest

Deploy the controller:

$ make deploy IMG=las3:443/lasyard.github.io/app:latest
/home/ubuntu/workspace/coding-go/k8app/bin/controller-gen rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
cd config/manager && /home/ubuntu/workspace/coding-go/k8app/bin/kustomize edit set image controller=las3:443/lasyard.github.io/app:latest
/home/ubuntu/workspace/coding-go/k8app/bin/kustomize build config/default | kubectl apply -f -
namespace/k8app-system created
customresourcedefinition.apiextensions.k8s.io/apps.lasyard.github.io created
serviceaccount/k8app-controller-manager created
role.rbac.authorization.k8s.io/k8app-leader-election-role created
clusterrole.rbac.authorization.k8s.io/k8app-app-admin-role created
clusterrole.rbac.authorization.k8s.io/k8app-app-editor-role created
clusterrole.rbac.authorization.k8s.io/k8app-app-viewer-role created
clusterrole.rbac.authorization.k8s.io/k8app-manager-role created
clusterrole.rbac.authorization.k8s.io/k8app-metrics-auth-role created
clusterrole.rbac.authorization.k8s.io/k8app-metrics-reader created
rolebinding.rbac.authorization.k8s.io/k8app-leader-election-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/k8app-manager-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/k8app-metrics-auth-rolebinding created
service/k8app-controller-manager-metrics-service created
deployment.apps/k8app-controller-manager created

Show the deployment:

$ k get all -n k8app-system
NAME                                            READY   STATUS    RESTARTS   AGE
pod/k8app-controller-manager-56cf8cdccc-nqwxv   1/1     Running   0          29s

NAME                                               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/k8app-controller-manager-metrics-service   ClusterIP   10.108.42.128   <none>        8443/TCP   29s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/k8app-controller-manager   1/1     1            1           29s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/k8app-controller-manager-56cf8cdccc   1         1         1       29s

Create an App:

$ kubectl apply -k config/samples/
app.lasyard.github.io/app-sample created

Show the logs of the pod:

$ kubectl logs k8app-controller-manager-56cf8cdccc-nqwxv -n k8app-system

2025-06-30T10:37:49Z    INFO    Starting Controller {"controller": "app", "controllerGroup": "lasyard.github.io", "controllerKind": "App"}
2025-06-30T10:37:49Z    INFO    Starting workers    {"controller": "app", "controllerGroup": "lasyard.github.io", "controllerKind": "App", "worker count": 1}
2025-06-30T10:37:50Z    INFO    controller-runtime.metrics  Serving metrics server  {"bindAddress": ":8443", "secure": true}
Reconciling App: default/app-sample

3.2.4. Clean up

$ make undeploy
/home/ubuntu/workspace/coding-go/k8app/bin/kustomize build config/default | kubectl delete --ignore-not-found=false -f -
namespace "k8app-system" deleted
customresourcedefinition.apiextensions.k8s.io "apps.lasyard.github.io" deleted
serviceaccount "k8app-controller-manager" deleted
role.rbac.authorization.k8s.io "k8app-leader-election-role" deleted
clusterrole.rbac.authorization.k8s.io "k8app-app-admin-role" deleted
clusterrole.rbac.authorization.k8s.io "k8app-app-editor-role" deleted
clusterrole.rbac.authorization.k8s.io "k8app-app-viewer-role" deleted
clusterrole.rbac.authorization.k8s.io "k8app-manager-role" deleted
clusterrole.rbac.authorization.k8s.io "k8app-metrics-auth-role" deleted
clusterrole.rbac.authorization.k8s.io "k8app-metrics-reader" deleted
rolebinding.rbac.authorization.k8s.io "k8app-leader-election-rolebinding" deleted
clusterrolebinding.rbac.authorization.k8s.io "k8app-manager-rolebinding" deleted
clusterrolebinding.rbac.authorization.k8s.io "k8app-metrics-auth-rolebinding" deleted
service "k8app-controller-manager-metrics-service" deleted
deployment.apps "k8app-controller-manager" deleted