Extending Kubernetes: Custom Resource Definitions (CRDs) and the Operator Pattern
Packaging human operational domain knowledge into automated Kubernetes controllers.
Part 18 in Series — Catch up on the previous article: Cluster Security & Authorization: RBAC, ServiceAccounts, and Admission Webhooks (Part 17) before diving into this post.
An enterprise data infrastructure team manages 50 production PostgreSQL database clusters.
Whenever a primary database node fails or requires a schema backup, a senior Database Administrator (DBA) follows a 15-step manual playbook:
- Promote secondary replica to primary.
- Update application connection strings.
- Trigger a point-in-time WAL backup to cloud object storage.
- Verify replication lag across surviving nodes.
Executing this playbook manually during outages takes 45 minutes, and human error risks data loss.
When the engineering team introduces a Custom Database Operator:
apiVersion: databases.example.com/v1alpha1
kind: PostgresCluster
metadata:
name: production-db
spec:
version: "15"
replicas: 3
storageSize: 500Gi
backupSchedule: "0 2 * * *"
The human DBA’s operational domain knowledge is codified inside a Custom Controller.
When a node fails, the Custom Operator detects the failure, executes the failover playbook, updates internal endpoints, and triggers backups automatically in 4 seconds.
How do Custom Resource Definitions (CRDs) and The Operator Pattern extend Kubernetes beyond basic containers into intelligent, self-managing application platforms?
1. What Is a Custom Resource Definition (CRD)?
Out of the box, Kubernetes understands core native resources (Pods, Services, Deployments, ConfigMaps).
A Custom Resource Definition (CRD) is a built-in mechanism that allows developers to register brand new, custom API endpoints directly into the kube-apiserver schema catalog:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: postgresclusters.databases.example.com
spec:
group: databases.example.com
versions:
- name: v1alpha1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
replicas:
type: integer
storageSize:
type: string
scope: Namespaced
names:
plural: postgresclusters
singular: postgrescluster
kind: PostgresCluster
shortNames:
- pg
What Happens When You Apply a CRD?
- The API Server registers new REST endpoints:
/apis/databases.example.com/v1alpha1/namespaces/default/postgresclusters. kubectlimmediately understands the new resource (kubectl get postgresclustersorkubectl get pg).- Custom resource manifests applied to the cluster are validated against the defined OpenAPI v3 Schema and persisted natively in
etcd.
2. What Is The Operator Pattern?
Registering a CRD stores desired state in etcd, but a CRD alone does nothing. Applying a CRD without a controller is just storing static data in a database.
The Operator Pattern combines a Custom Resource Definition (CRD) with a Custom Controller:
+-------------------------------------------------------------------+
| 1. Custom Resource Manifest (e.g., kind: PostgresCluster) |
| Specifies desired database state |
+-------------------------------------------------------------------+
|
v Stored in etcd via kube-apiserver
+-------------------------------------------------------------------+
| 2. Custom Operator Controller (Go / Java / Python) |
| Runs continuous reconciliation loop: |
| - Observes PostgresCluster spec & actual DB state |
| - Manages underlying Deployments, StatefulSets, Services, PVCs |
| - Executes operational domain tasks (Backups, Failovers) |
+-------------------------------------------------------------------+
3. How an Operator Reconciles Stateful Applications
Consider what the PostgresCluster Operator does under the hood when a user applies replicas: 3:
User applies: `kind: PostgresCluster, spec: { replicas: 3 }`
|
v
[ Custom Operator Reconciliation Loop ]
1. Reads PostgresCluster Spec.
2. Checks if Headless Service exists -> If missing, creates Service!
3. Checks if StatefulSet exists -> If missing, creates StatefulSet!
4. Checks if Backup CronJob exists -> If missing, creates CronJob!
5. Evaluates replication lag across database nodes.
6. Writes current database health status into PostgresCluster `status` block.
Instead of requiring human engineers to manually coordinate StatefulSets, PVCs, and backup scripts, the Operator translates high-level domain intents into low-level Kubernetes primitives automatically.
4. Popular Enterprise Operators
The Operator Pattern powers the modern cloud-native ecosystem:
- Prometheus Operator: Manages monitoring scrapers, alert rules, and Grafana dashboards.
- Strimzi Kafka Operator: Automates Apache Kafka cluster provisioning, topic creation, and user ACL configuration.
- Zalando Postgres Operator: Manages high-availability PostgreSQL clusters with automated WAL archiving.
- Cert-Manager Operator: Automates ACME / Let’s Encrypt TLS certificate issuance and renewal.
Native Resources vs Custom Operators Comparison
| Feature | Native Resources (Deployment, Service) | Custom Operator (PostgresCluster) |
|---|---|---|
| API Endpoints | Standard Kubernetes APIs (/api/v1) | Custom API Extension (/apis/domain/v1) |
| Domain Knowledge | Basic container lifecycle & rolling updates | Deep domain-specific operations (DB backups, failovers) |
| Managed Primitives | Individual containers | Multi-resource stacks (StatefulSet + PVC + Service + CronJob) |
| Implementation Language | Built into kube-controller-manager (Go) | External controller written in Go (Kubebuilder), Java, or Python |
Summary & Next Steps
CRDs and Operators allow developers to extend Kubernetes into a custom cloud platform:
- Custom Resource Definitions (CRDs) register custom API types and OpenAPI v3 schemas into
kube-apiserver. - The Operator Pattern pairs a CRD with a Custom Controller running an automated reconciliation loop.
- Operators codify human operational playbooks into self-healing software code.
In the next article, we examine Production Debugging and Operations: Event Loops, Pending Pods, and OOMKilled Analysis.
References & Further Reading
- Cloud Native Computing Foundation. Dynamic Admission Control (Validating and Mutating Webhooks). CNCF Docs.
- CNCF Kyverno Project. Kyverno Native Policy Management Architecture for Kubernetes. Kyverno Docs.
- CNCF OPA Project. Open Policy Agent (OPA) Gatekeeper Architecture. Gatekeeper Docs.
Part 19: Production Debugging and Operations: Event Loops, Pending Pods, and OOMKilled Analysis
Continue to Part 19 →