DevOps Dictionary

Kubernetes CustomResourceDefinition (CRD)

Kubernetes CustomResourceDefinition (CRD) is a Kubernetes API extension that lets you add your own resource types to a cluster. In practical terms, a CRD lets teams manage domain-specific objects, such as databases, certificates, cloud resources, backups, or application environments, using the same Kubernetes API patterns they already use for Pods, Services, and Deployments.

What a CRD does

A CRD adds a new resource kind to the Kubernetes API. Once installed, users can create, read, update, delete, and watch that custom resource with tools such as kubectl, GitOps controllers, CI/CD pipelines, and Kubernetes clients.

For example, after installing a CRD for a managed database, you might create a resource like:

apiVersion: database.example.com/v1
kind: PostgresInstance
metadata:
  name: orders-db
spec:
  version: "15"
  storageGB: 100
  replicas: 2

Kubernetes stores this object in its API server, validates it against the CRD schema, and makes it available for controllers to act on.

How CRDs work

A CRD defines the shape and behavior of a custom Kubernetes resource. It tells the Kubernetes API server:

  • Group: The API group, such as database.example.com.
  • Version: The API version, such as v1alpha1, v1beta1, or v1.
  • Kind: The resource type, such as PostgresInstance.
  • Plural name: The name used in API paths and CLI commands, such as postgresinstances.
  • Schema: The allowed fields, types, defaults, and validation rules for spec and other fields.
  • Scope: Whether the resource is namespaced or cluster-wide.

A CRD alone usually defines the API, but it does not perform actions by itself. For automation, you normally pair it with a controller or operator. The controller watches custom resources and reconciles the real system to match the desired state in the resource’s spec.

CRDs and controllers

Most useful CRD-based systems follow the Kubernetes controller pattern:

  1. A user creates or updates a custom resource.
  2. A controller watches that resource type.
  3. The controller compares the desired state in spec with the actual state.
  4. The controller creates, updates, or deletes related resources.
  5. The controller writes current state back to status.

For example, a Certificate custom resource might cause a controller to request a TLS certificate, store it in a Secret, renew it before expiry, and update status fields when issuance succeeds or fails.

Common use cases

CRDs are common in production Kubernetes platforms because they let teams model higher-level workflows as Kubernetes resources.

  • Operators: Manage complex applications such as databases, message brokers, monitoring stacks, and CI systems.
  • Cloud infrastructure: Define cloud resources through Kubernetes, as seen in platforms such as Crossplane. For a practical example, see how teams can deploy AWS resources using Crossplane on Kubernetes.
  • GitOps workflows: Store custom resources in Git and let tools such as Argo CD or Flux apply them to clusters.
  • Policy and security: Define policies, constraints, scans, or exceptions as Kubernetes-native objects.
  • Platform abstractions: Give developers simple resources such as Application, Environment, or Database while platform teams handle the underlying implementation.
  • Data and workflow platforms: Package operational behavior for systems such as Airflow, Kafka, or Spark on Kubernetes. For example, teams running Airflow on EKS often combine Helm charts, controllers, and custom resources as part of the platform design, similar to patterns used when you deploy Apache Airflow on AWS Elastic Kubernetes Service.

Benefits of CRDs

  • Kubernetes-native interface: Teams can use kubectl, RBAC, admission control, audit logs, and GitOps tools with custom resources.
  • Declarative operations: Users define desired state, while controllers handle the steps needed to reach it.
  • Reusable platform APIs: Platform teams can create stable internal APIs for common engineering tasks.
  • Clear ownership model: Custom resources can expose simple fields to application teams while hiding provider-specific details.
  • Consistent automation: Controllers can handle retries, drift correction, status reporting, and cleanup.

Tradeoffs and limitations

CRDs are powerful, but they add operational responsibility. A poorly designed CRD can become hard to support across teams and cluster upgrades.

  • Controller dependency: If the controller is broken or missing, custom resources may sit unchanged.
  • API design matters: Field names, defaults, versioning, and validation choices can be difficult to change later.
  • Upgrade risk: CRDs and controllers must be compatible with your Kubernetes version. Plan this during cluster upgrades, especially in startup environments where platform teams are small. These practical tips for Kubernetes upgrades cover related planning concerns.
  • Security scope: CRDs may expose powerful actions. Use RBAC carefully, especially for resources that create cloud infrastructure or modify cluster-wide settings.
  • Debugging complexity: You may need to inspect the custom resource, controller logs, events, finalizers, and generated resources to understand failures.

CRD versus Custom Resource

A CRD defines a new type of Kubernetes resource. A custom resource is an instance of that type.

For example:

  • PostgresInstance as an API type is defined by a CRD.
  • orders-db as a specific database request is a custom resource.

This is similar to the difference between a class definition and an object instance in programming, but in Kubernetes API terms.

CRD versus built-in Kubernetes resource

Built-in resources, such as Pods, Services, Deployments, ConfigMaps, and Secrets, ship with Kubernetes. CRDs are added after the cluster is running.

Both can use the Kubernetes API, metadata, labels, annotations, RBAC, and watch behavior. The main difference is ownership: Kubernetes core components manage built-in resources, while custom controllers usually manage CRD-backed resources.

Real-world example

Say your platform team wants developers to request cloud databases without opening tickets or learning every cloud provider setting. The team can define a Database CRD with fields such as:

  • engine: PostgreSQL or MySQL
  • version: Database version
  • storageGB: Requested storage
  • backupRetentionDays: Backup policy
  • environment: dev, staging, or production

A developer commits a Database custom resource to Git. A GitOps controller applies it to the cluster. A platform controller provisions the database, creates credentials, stores connection data in a Secret, and updates the resource status.

This pattern is common with tools that manage infrastructure through Kubernetes APIs. Crossplane, for example, uses CRDs to represent cloud resources and compositions. You can see the pattern in a more complete workflow that deploys a Kubernetes app and AWS resource using Crossplane.

Managing CRDs with infrastructure tools

CRDs often sit at the boundary between application delivery and infrastructure management. Teams may install CRDs using Helm, Kustomize, GitOps, or Terraform, then manage custom resources through the same pipeline.

If your team already manages Kubernetes objects through Terraform, CRDs can become part of that workflow too. For a related approach, see how to deploy Kubernetes resources using Terraform.

Key takeaway

A Kubernetes CRD extends the Kubernetes API with your own resource types. It is the foundation for operators, platform APIs, GitOps abstractions, and Kubernetes-based infrastructure management. Use CRDs when you want a declarative, Kubernetes-native way to manage something beyond the built-in resource types, and pair them with well-designed controllers, validation, RBAC, and upgrade planning.

A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
Y
X
Z