CRDs
Custom Resource Definitions (CRDs) allow you to extend the Kubernetes API with your own resource types. Understanding CRDs is important because they enable you to model your applications and infrastructure as native Kubernetes resources, integrate external systems, and build domain-specific abstractions.
Think of CRDs like adding new forms to a filing system. Kubernetes comes with standard forms (Pods, Services, Deployments), but sometimes you need custom forms for your specific needs. CRDs let you define new forms (resource types) that work just like the built-in ones—you can create them, list them, watch them, and manage them with kubectl.
What are CRDs?
A Custom Resource Definition (CRD) is a way to extend the Kubernetes API by defining new resource types. Once you create a CRD, you can create, read, update, and delete instances of that resource type just like built-in resources.
Custom Resources vs Built-in Resources
Built-in resources (Pods, Services, Deployments):
- Defined in Kubernetes core code
- Available in all clusters
- Can’t be modified or removed
Custom resources (defined via CRDs):
- Defined by you
- Specific to your cluster
- Can be created, modified, or deleted
- Work like built-in resources
Why Use CRDs?
CRDs enable several powerful use cases:
Domain-Specific Abstractions
Model your applications and infrastructure as Kubernetes resources:
apiVersion: example.com/v1
kind: Database
metadata:
name: my-database
spec:
type: postgresql
version: "14"
replicas: 3
storage: 100Gi
API Integration
Integrate external systems into Kubernetes:
apiVersion: networking.example.com/v1
kind: LoadBalancer
metadata:
name: my-lb
spec:
provider: aws
type: application
listeners:
- port: 80
protocol: HTTP
Application-Specific Resources
Define resources specific to your applications:
apiVersion: apps.example.com/v1
kind: WebApplication
metadata:
name: my-app
spec:
frontend:
image: my-frontend:1.0
replicas: 3
backend:
image: my-backend:1.0
replicas: 2
database:
type: postgresql
CRD Structure
A CRD defines:
- API group and version - Where the resource lives
- Resource name - Plural and singular names
- Scope - Namespaced or cluster-scoped
- Schema - Structure of the resource (spec, status)
- Validation - Rules for valid resources
- Subresources - Status, scale, etc.
Example CRD
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: databases.example.com
spec:
group: example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
type:
type: string
version:
type: string
replicas:
type: integer
storage:
type: string
status:
type: object
properties:
phase:
type: string
scope: Namespaced
names:
plural: databases
singular: database
kind: Database
shortNames:
- db
Custom Resources
Once you create a CRD, you can create custom resources:
apiVersion: example.com/v1
kind: Database
metadata:
name: my-database
namespace: production
spec:
type: postgresql
version: "14"
replicas: 3
storage: 100Gi
status:
phase: Running
endpoints:
- my-database-0.example.com:5432
This works just like built-in resources:
# Create
kubectl create -f database.yaml
# List
kubectl get databases
# Get details
kubectl get database my-database -o yaml
# Update
kubectl apply -f database.yaml
# Delete
kubectl delete database my-database
CRDs and Controllers
CRDs by themselves just define the resource structure. To make them useful, you typically need controllers (operators) that:
- Watch for custom resources
- Reconcile desired state with actual state
- Create other Kubernetes resources
- Manage external systems
- Update status based on actual state
Common CRD Use Cases
Operators
Operators use CRDs to manage complex applications:
- Database operators - Manage database instances
- Monitoring operators - Deploy and manage monitoring stacks
- CI/CD operators - Manage CI/CD pipelines
- Application operators - Manage application lifecycles
Infrastructure as Code
Model infrastructure as Kubernetes resources:
- Load balancers - Define load balancers as resources
- DNS records - Manage DNS as resources
- Storage - Define storage configurations
- Networking - Model network topologies
GitOps Integration
Use CRDs with GitOps tools:
- ArgoCD Applications - Application CRDs
- Flux Sources - Git/Helm source CRDs
- Custom workflows - Define workflows as resources
CRD Best Practices
Schema Design
- Define clear spec and status sections
- Use OpenAPI schema for validation
- Version your CRDs appropriately
- Plan for schema evolution
Naming
- Use clear, descriptive names
- Follow Kubernetes naming conventions
- Use appropriate API groups
- Choose good shortNames
Validation
- Validate input in CRD schema
- Use admission webhooks for complex validation
- Provide clear error messages
- Validate early and often
Versioning
- Plan for API versioning
- Support multiple versions during transitions
- Deprecate old versions properly
- Document version changes
CRD Limitations
CRDs have some limitations:
- No defaulting - Can’t set defaults in CRD (use webhooks)
- Limited validation - Complex validation requires webhooks
- No subresources by default - Status subresource must be enabled
- Schema evolution - Changing schemas requires care
- Performance - Large numbers of CRDs can impact API server
When to Use CRDs
Good Use Cases
✅ Domain-specific abstractions - Model your domain ✅ Application operators - Manage complex applications ✅ Infrastructure modeling - Model infrastructure as resources ✅ API integration - Integrate external systems ✅ GitOps workflows - Define workflows as resources
When Not to Use
❌ Simple configuration - Use ConfigMaps instead ❌ Simple deployments - Use Deployments instead ❌ No controller needed - CRDs without controllers are limited ❌ Over-engineering - Don’t create CRDs for everything
CRDs vs Operators
CRDs - Define the resource structure Operators - Provide the logic to manage resources
You typically use both together:
- CRD defines what the resource looks like
- Operator (controller) provides the management logic
Key Takeaways
- CRDs extend the Kubernetes API with custom resource types
- Custom resources work like built-in resources
- CRDs define structure, controllers provide logic
- Common use cases include operators and infrastructure modeling
- CRDs enable domain-specific abstractions
- Plan for schema evolution and versioning
- Use CRDs when you need custom abstractions, not for simple cases
See Also
- API Objects - Understanding Kubernetes resources
- APIs & Access - How CRDs extend the API
- Discovery & OpenAPI - CRDs in API discovery
- Extensibility & Interfaces - Extending Kubernetes
- Operators - Building operators with CRDs