Working with Custom Resource Definitions

1. Understanding CRD Handling

MethodBehavior
crds/ directoryInstalled once before templates; not templated, not upgraded, not deleted
templates/ with hooksUse pre-install/pre-upgrade + helm.sh/resource-policy: keep for upgrade support

2. Installing CRDs with Charts

FlagEffect
DefaultCRDs in crds/ installed automatically
--skip-crdsSkip CRD installation (assumes pre-installed)

3. Creating CRD Templates

Example: crds/myresource.yaml (NOT templated)

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: myresources.example.com
spec:
  group: example.com
  scope: Namespaced
  names:
    plural: myresources
    singular: myresource
    kind: MyResource
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object

4. Managing CRD Versions

StrategyDetail
Separate chartManage CRDs in a chart consumed by app charts
Multiple versionsstorage: true on exactly one version; others served: true for compatibility
Conversion webhooksRequired when promoting storage version

5. Handling CRD Upgrades

Warning: CRDs in crds/ are NEVER upgraded by Helm. For evolving CRDs, place them in templates/ with helm.sh/resource-policy: keep and pre-upgrade hooks.
MethodWorkflow
Templated CRDsAllow updates; risk of breaking running CRs
Hook-managedpre-install,pre-upgrade hook applies CRDs first
ManualApply CRDs via kubectl outside chart, install with --skip-crds

6. Avoiding CRD Deletion on Uninstall

AnnotationEffect
helm.sh/resource-policy: keepRetains resource on helm uninstall
CRDs in crds/Always retained (Helm never deletes)

7. Validating CRD Schemas

ToolUse
kubeconform --strictValidate CRs against CRD schemas
kubectl apply --dry-run=serverLive admission validation
CEL validation rulesInline schema with x-kubernetes-validations

8. Using CRDs with Operators

Example: Operator chart layout

operator-chart/
├── Chart.yaml
├── crds/                  # CRDs installed first
│   └── myresource.yaml
├── templates/
│   ├── deployment.yaml    # Operator pod
│   ├── rbac.yaml
│   └── examples/          # Sample CRs (optional)
└── values.yaml

9. Testing CRD Installation

Example: Verify CRD post-install

helm install op ./chart
kubectl get crd myresources.example.com
kubectl explain MyResource.spec

10. Troubleshooting CRD Issues

IssueFix
CRD missing during template installCRDs install before templates — check timing if using webhooks
CRD not upgradedHelm crds/ never updates; use kubectl apply -f crds/ manually
Stuck on uninstallCRs reference CRD; delete CRs first or set finalizer policy
Schema validation failsRun kubectl get crd ... -o yaml + check openAPIV3Schema