Skip to main content
You need a WebApp custom resource type in your operator. Starting from an empty Go project, Kubebuilder scaffolds the Go types, controller, and CRD manifest for you in the expected project layout so you can quickly run kubectl apply.
The image shows the Visual Studio Code interface with a file explorer on the left displaying project files, and an open terminal on the right.
This lesson walks through scaffolding a WebApp API (group webapp, version v1, kind WebApp) and shows how Kubebuilder wires everything together.

Project overview before scaffolding

When you open the project you should already see:
  • PROJECT file describing the repository and domain.
  • cmd directory (entry point).
  • config tree for manifests and kustomize overlays.
Run the Kubebuilder command to scaffold the API (this also creates a controller and resource):
With the project domain set to kodekloud.com in PROJECT, the full API group becomes: webapp.kodekloud.com/v1.

What Kubebuilder generates

After running the scaffold command, Kubebuilder creates the new API types and controller skeleton. The two primary locations are: Kubebuilder also updates the PROJECT metadata used for future scaffolding. Example PROJECT-style metadata:
When scaffolding runs, you’ll see informative logs about files created and dependency updates, for example:

Generated Go types (example)

Kubebuilder scaffolds api/v1/webapp_types.go with placeholder fields. The WebAppSpec currently contains a Foo example field and WebAppStatus includes a Conditions slice prepared for status conditions. Keep these placeholders while following this lesson; a later lab replaces Foo with real fields such as image and replicas. Example generated types:
Kubebuilder marker comments such as +kubebuilder:object:root=true and +kubebuilder:subresource:status are directives for the code generator (controller-gen). They control what gets generated in the CRD YAML and client code.

Generate CRD YAML from types

To convert the Go types (the single source of truth) into a Kubernetes CustomResourceDefinition (CRD) YAML, run:
Under the hood, make manifests runs controller-gen which parses the Kubebuilder markers and writes the CRD base file into config/crd/bases. Kubebuilder names the CRD file using the group and plural form, for example: config/crd/bases/webapp.kodekloud.com_webapps.yaml A small excerpt of the generated CRD (shows identity and inferred schema):
From this CRD YAML you can immediately read:
  • metadata name: webapps.webapp.kodekloud.com
  • group: webapp.kodekloud.com
  • kind: WebApp, listKind: WebAppList
  • plural: webapps, singular: webapp
  • version v1 and status subresource enabled

Verify compilation & development loop

Before editing types and controller logic, ensure the scaffold builds cleanly. A typical development loop is:
  1. Scaffold the API:
  2. Regenerate CRD manifests:
  3. Build and test the controller:

Next steps

  • Re-run kubebuilder create api if you need to add more APIs for the same project.
  • Replace placeholder fields in api/v1/webapp_types.go with real spec fields (for example image and replicas).
  • Implement controller logic in internal/controller to create and manage child resources such as Service, Deployment, and ConfigMap for each WebApp.
Recommended references:

Watch Video

Practice Lab