Skip to main content
KubeLB uses code generation extensively to maintain consistency between API definitions and generated artifacts like CRDs, RBAC manifests, and boilerplate code.

When to Run Code Generation

Run code generation after:

Modifying CRD Types

Adding/changing fields in api/ce/kubelb.k8c.io/v1alpha1/ or api/ee/kubelb.k8c.io/v1alpha1/

Adding Kubebuilder Markers

Adding validation markers like +kubebuilder:validation:Required

Changing RBAC

Modifying RBAC markers in controller comments (//+kubebuilder:rbac)

Adding New Controllers

Creating new controller files that need generated code

Full Code Generation Pipeline

make update-codegen
This runs the complete pipeline:
1

Generate DeepCopy methods

Generates DeepCopy, DeepCopyInto, and DeepCopyObject methods for all API types.
2

Generate CRD manifests

Creates CustomResourceDefinition YAML files from Go structs and kubebuilder markers.
3

Generate RBAC manifests

Creates ClusterRole and Role manifests from controller RBAC markers.
4

Generate reconciliation helpers

Creates helper functions for resource reconciliation.
5

Generate Helm documentation

Updates README files for Helm charts.
6

Generate metrics documentation

Creates documentation for Prometheus metrics.
7

Format code

Runs go fmt on all generated code.
8

Run vet

Runs go vet to catch common mistakes.
9

Tidy dependencies

Runs go mod tidy to clean up go.mod.

Individual Generation Commands

DeepCopy Generation

Generate DeepCopy methods for API types:
make generate
This uses controller-gen to generate code in zz_generated.deepcopy.go files:
// DeepCopy is an autogenerated deepcopy function
func (in *LoadBalancer) DeepCopy() *LoadBalancer {
    if in == nil {
        return nil
    }
    out := new(LoadBalancer)
    in.DeepCopyInto(out)
    return out
}
Configuration:
  • Header template: hack/boilerplate/boilerplate.go.txt
  • Processes all packages with //+kubebuilder:object:generate=true

CRD Manifest Generation

Generate CRD YAML files:
make manifests
This generates:
  • config/crd/bases/*.yaml - Base CRD definitions
  • charts/kubelb-manager/crds/*.yaml - Helm chart CRDs
  • charts/kubelb-ccm/crds/kubelb.k8c.io_syncsecrets.yaml - CCM CRDs
CRD Generation Path:
CRD_CODE_GEN_PATH = "./api/ce/..."

RBAC Generation

Generate RBAC manifests from controller markers:
make manifests  # Includes RBAC generation
Output files:
  • config/kubelb/rbac/role.yaml - Manager cluster role
  • config/ccm/rbac/role.yaml - CCM cluster role
RBAC Markers Example:
//+kubebuilder:rbac:groups=kubelb.k8c.io,resources=loadbalancers,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=kubelb.k8c.io,resources=loadbalancers/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=kubelb.k8c.io,resources=loadbalancers/finalizers,verbs=update
//+kubebuilder:rbac:groups="",resources=services,verbs=get;list;watch
//+kubebuilder:rbac:groups="",resources=nodes,verbs=get;list;watch

func (r *LoadBalancerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    // Controller logic
}

Reconciliation Helper Generation

Generate resource reconciliation helpers:
make reconciler-gen
This generates internal/resources/reconciling/zz_generated_reconcile.go based on:
  • Configuration: hack/reconciling.yaml
  • Library: k8c.io/reconciler
Generated helper example:
// ServiceReconciler creates or updates a Service
func ServiceReconciler(existing *corev1.Service, creator ServiceCreator) (*corev1.Service, error) {
    if existing == nil {
        existing = &corev1.Service{}
    }
    return creator(existing)
}

Kubebuilder Markers

Kubebuilder markers are special comments that control code generation.

Common Type Markers

// +kubebuilder:validation:Required
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=253
// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
Host string `json:"host"`

// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=65535
Port int32 `json:"port"`

// +kubebuilder:validation:Enum=TCP;UDP
Protocol string `json:"protocol"`

RBAC Markers

RBAC markers go above the Reconcile method:
// Service controller reconciles Service objects
//+kubebuilder:rbac:groups="",resources=services,verbs=get;list;watch;update;patch
//+kubebuilder:rbac:groups="",resources=services/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=kubelb.k8c.io,resources=loadbalancers,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups="",resources=nodes,verbs=get;list;watch
//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch

func (r *ServiceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    // ...
}
RBAC Marker Syntax:
  • groups: API group (empty string for core resources)
  • resources: Resource type (use /status or /finalizers for subresources)
  • verbs: Allowed operations

Webhook Markers

// +kubebuilder:webhook:path=/validate-kubelb-k8c-io-v1alpha1-loadbalancer,mutating=false,failurePolicy=fail,groups=kubelb.k8c.io,resources=loadbalancers,verbs=create;update,versions=v1alpha1,name=vloadbalancer.kb.io,sideEffects=None,admissionReviewVersions=v1

func (r *LoadBalancer) ValidateCreate() error {
    // Validation logic
}

Tool Versions

KubeLB uses specific tool versions (defined in Makefile):
ToolVersionPurpose
controller-toolsv0.20.1CRD/RBAC/webhook generation
kustomizev5.8.1Kubernetes manifest management
helm-docsv1.14.2Helm chart documentation
crd-ref-docsv0.3.0API reference docs
go1.25.7Go version

Helm Chart Documentation

Generate Helm chart README files:
make generate-helm-docs
This reads chart metadata and values to generate:
  • charts/kubelb-manager/README.md
  • charts/kubelb-ccm/README.md
  • charts/kubelb-addons/README.md
Configuration: Each chart’s values.yaml includes doc comments:
# -- Number of replicas for the controller
replicaCount: 1

# -- Image pull policy
imagePullPolicy: IfNotPresent

Metrics Documentation

Generate Prometheus metrics reference:
make generate-metricsdocs
This generates docs/metrics.md by parsing metric definitions in internal/metrics/. Example metric definition:
package metrics

import "github.com/prometheus/client_golang/prometheus"

var (
    // LoadBalancerReconciliations tracks reconciliation count
    LoadBalancerReconciliations = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Namespace: "kubelb",
            Subsystem: "manager",
            Name:      "loadbalancer_reconciliations_total",
            Help:      "Total number of LoadBalancer reconciliations",
        },
        []string{"result"},
    )
)

Gateway API CRDs

Update Gateway API CRDs:
make update-gateway-api-crds
This downloads the latest Gateway API CRDs:
  • Standard channel: internal/resources/crds/gatewayapi/standard/
  • Experimental channel: internal/resources/crds/gatewayapi/experimental/
Configuration:
GATEWAY_API_VERSION ?= v1.4.1
GATEWAY_RELEASE_CHANNEL ?= standard

Verification Commands

After code generation, verify correctness:
# Check copyright headers
make verify-boilerplate

Troubleshooting

”controller-gen: not found”

Solution: Install controller-gen:
make controller-gen

CRDs not updating after API changes

Solution: Run full generation pipeline:
make manifests generate

RBAC permissions missing

Cause: Missing or incorrect RBAC markers Solution:
  1. Add RBAC markers above Reconcile method
  2. Run make manifests
  3. Check generated config/*/rbac/role.yaml

Import order violations

Solution: Run gimps to fix import order:
go install github.com/xrstf/gimps@latest
gimps -w .
Or run verification:
make verify-imports

Best Practices

make update-codegen
This ensures all generated code is up-to-date.
Files with zz_generated or DO NOT EDIT in their name/header are auto-generated.Generated files:
  • **/zz_generated.*.go
  • config/crd/bases/*.yaml
  • config/*/rbac/*.yaml
  • charts/*/README.md
After modifying CRDs:
make manifests install
kubectl get crd loadbalancers.kubelb.k8c.io -o yaml
Add descriptions to fields for better CRD documentation:
// Port is the port number for the service (1-65535)
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=65535
// +kubebuilder:validation:Required
Port int32 `json:"port"`

Next Steps

API Reference

View the complete API reference

Controller-gen

Learn more about controller-gen markers

Build docs developers (and LLMs) love