CRD Synchronization Process
This document explains the automated CRD synchronization process that keeps Helm chart CRDs in sync with kubebuilder-generated CRDs.
Overview
The homelab-autoscaler project uses kubebuilder to generate CRDs from Go struct definitions. These CRDs need to be synchronized with the Helm chart templates to ensure consistency between the Go code and the deployed resources.
Problem Solved
Previously, CRDs in the Helm chart (dist/chart/templates/crd/) were manually maintained and could become outdated when the Go struct definitions changed. This led to:
- Schema mismatches between Go structs and deployed CRDs
- E2E test failures due to incorrect CRD schemas
- Manual maintenance overhead
- Risk of deploying incompatible CRD versions
Solution Architecture
The automated CRD sync process integrates into the build pipeline:
Components
1. CRD Sync Script (hack/sync-helm-crds.sh)
Transforms kubebuilder-generated CRDs into Helm-templated versions:
- Input:
config/crd/bases/*.yaml(kubebuilder output) - Output:
dist/chart/templates/crd/*.yaml(Helm templates) - Transformations:
- Wraps CRDs with
{{- if .Values.crd.enable }}conditional - Adds Helm labels:
{{- include "chart.labels" . | nindent 4 }} - Adds conditional keep annotation:
{{- if .Values.crd.keep }} - Preserves the exact schema from kubebuilder
- Wraps CRDs with
2. Makefile Integration
helm-sync-crdstarget: Runs the sync script- Dependency chain:
manifests→helm-sync-crds→build→test-e2e - Automatic execution: CRDs are synced whenever manifests are generated
3. Validation Script (hack/validate-helm-crds.sh)
Validates that Helm chart CRDs match kubebuilder output:
- Compares schema sections between source and target CRDs
- Validates Helm templating is correctly applied
- Reports any inconsistencies or missing templates
Usage
Automatic Sync (Recommended)
The sync happens automatically when running standard build commands:
# Generate manifests and sync CRDs
make manifests
# Build project (includes CRD sync)
make build
# Run E2E tests (includes CRD sync)
make test-e2e
Manual Sync
To manually sync CRDs:
# Sync CRDs from kubebuilder to Helm chart
make helm-sync-crds
# Validate CRD consistency
./hack/validate-helm-crds.sh
Validation
To check if CRDs are in sync:
./hack/validate-helm-crds.sh
This will:
- Compare schemas between kubebuilder and Helm chart CRDs
- Validate Helm templating is correct
- Report any inconsistencies
Development Workflow
When modifying Go struct definitions:
- Modify Go structs in
api/infra/v1alpha1/ - Run
make manifests- This automatically:- Generates new CRDs via controller-gen
- Syncs CRDs to Helm chart
- Test changes with
make test-e2e - Commit both Go changes and updated Helm CRDs
File Structure
├── api/infra/v1alpha1/
│ ├── group_types.go # Go struct definitions
│ └── node_types.go
├── config/crd/bases/ # Kubebuilder-generated CRDs
│ ├── infra.homecluster.dev_groups.yaml
│ └── infra.homecluster.dev_nodes.yaml
├── dist/chart/templates/crd/ # Helm-templated CRDs
│ ├── infra.homecluster.dev_groups.yaml
│ └── infra.homecluster.dev_nodes.yaml
└── hack/
├── sync-helm-crds.sh # CRD sync script
└── validate-helm-crds.sh # CRD validation script
Helm Chart Integration
The synchronized CRDs integrate seamlessly with Helm chart features:
Conditional Installation
# CRDs are only installed if enabled
{{- if .Values.crd.enable }}
---
# CRD content here
{{- end -}}
Resource Policy
# CRDs can be preserved during uninstall
annotations:
{{- if .Values.crd.keep }}
"helm.sh/resource-policy": keep
{{- end }}
Labels
# CRDs get standard Helm chart labels
labels:
{{- include "chart.labels" . | nindent 4 }}
Configuration
CRD behavior is controlled via Helm values:
# values.yaml
crd:
# Enable/disable CRD installation
enable: true
# Keep CRDs when uninstalling chart
keep: true
Troubleshooting
CRD Schema Mismatch
If E2E tests fail with CRD schema errors:
- Check if CRDs are in sync:
./hack/validate-helm-crds.sh - Re-sync CRDs:
make helm-sync-crds - Verify the Go struct matches expected schema
Sync Script Failures
If the sync script fails:
- Ensure kubebuilder CRDs exist:
ls config/crd/bases/ - Run
make manifeststo generate CRDs - Check script permissions:
chmod +x hack/sync-helm-crds.sh
Validation Failures
If validation reports schema differences:
- Check for manual edits to Helm chart CRDs
- Re-run sync:
make helm-sync-crds - Verify Go struct changes are correct
Benefits
- Zero manual maintenance: CRDs automatically stay in sync
- Prevents schema drift: Helm chart always matches Go structs
- Reliable E2E tests: Tests use correct CRD schemas
- Preserves Helm features: Conditional installation, labels, annotations
- Developer friendly: No changes to development workflow
- Validation included: Built-in consistency checking
Future Enhancements
Potential improvements to consider:
- Pre-commit hooks: Ensure CRDs are synced before commits
- Schema versioning: Track CRD schema changes over time