Skip to content

CRDs

Kubernetes allows users to extend its API through Custom Resource Definitions (CRDs), enabling the creation of domain-specific resources tailored to applications or workflows. CRDs are essential for scenarios like managing stateful applications, defining custom controllers, or integrating with external systems. This section explains how to define and implement CRDs to extend Kubernetes' capabilities.


Understanding Custom Resource Definitions (CRDs)

A Custom Resource Definition is a YAML file that defines a new resource type, specifying its structure, behavior, and API version. CRDs are stored in the crd.k8s.io API group and are managed by the Kubernetes API server. Each CRD defines a kind (e.g., MyDatabase) and includes a spec (desired state) and status (observed state) for instances of the resource.

Key Components of a CRD

  • apiVersion: Specifies the API group and version (e.g., crd.k8s.io/v1).
  • kind: The type of resource (e.g., CustomResourceDefinition).
  • spec: Defines the structure of the custom resource, including:
  • scope: Namespaced or Cluster (determines visibility).
  • names: The plural and singular names for the resource (e.g., databases and database).
  • validation: Rules for validating custom resource instances.
  • additionalProperties: Optional fields for extensibility.

Example: A CRD for a custom Database resource:

apiVersion: crd.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: databases.example.com
spec:
  scope: Namespaced
  names:
    plural: databases
    singular: database
    kind: Database
  validation:
    openAPIV3Schema:
      properties:
        spec:
          properties:
            size: {type: integer}
            engine: {type: string}


Creating a Custom Resource Definition

To create a CRD, apply the YAML file using kubectl:

kubectl apply -f database-crd.yaml
After creation, the CRD becomes available in the Kubernetes API, allowing users to create instances of the custom resource.


Using Custom Resources

Once a CRD is defined, users can create instances of the custom resource. For example, to create a Database resource:

apiVersion: example.com/v1
kind: Database
metadata:
  name: my-database
spec:
  size: 10
  engine: PostgreSQL
Apply this resource with:
kubectl apply -f my-database.yaml
The Kubernetes API will validate the resource against the CRD's validation rules and store it as a normal Kubernetes object.


Managing Custom Resources with Controllers

CRDs are often paired with controllers that reconcile the actual state of resources with the desired state. A controller typically: 1. Watches for changes to the custom resource. 2. Applies business logic to update related resources (e.g., provisioning a database). 3. Updates the status field to reflect the current state.

Example: A basic controller in Go using the Kubernetes client library:

func main() {
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err)
    }

    // Watch for Database resources
    informer := informers.NewSharedInformerFactory(clientset, 0)
    dbInformer := informer.InformerFor(&corev1.Database{}, func() cache.StoreProvider {
        return cache.NewStore(cache.MetaNamespaceKeyFunc)
    })

    // Reconcile logic
    dbInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
        Update: func(oldObj, newObj any) {
            // Logic to update database state
        },
    })

    informer.Start(context.TODO())
    informer.WaitForCacheSync(context.TODO())
}


Best Practices and Considerations

  • Versioning: Use semantic versioning for CRD APIs to manage backward compatibility.
  • Validation: Define strict validation rules in the validation field to prevent invalid configurations.
  • Namespacing: Use Namespaced scope for most custom resources to avoid global pollution.
  • Security: Restrict access to CRDs using Kubernetes Role-Based Access Control (RBAC).
  • Testing: Validate CRDs in isolated environments before deploying to production.

Key takeaways

  • CRDs allow you to extend Kubernetes' API with domain-specific resources.
  • A CRD defines the structure and behavior of a custom resource type.
  • Controllers are essential for managing the lifecycle of custom resources.
  • Follow best practices like versioning, validation, and RBAC to ensure robustness.
  • CRDs are a foundational tool for building custom controllers and workflows in Kubernetes.