



























Kubernetes provides an extension mechanism that allows you to add custom API resources to your cluster without modifying the core Kubernetes codebase. Custom Resource Definitions (CRDs) form the foundation of this extensibility, enabling you to define your own resource types that behave like native Kubernetes objects.
In this guide, we'll explore CRDs, providing some practical examples that will help you to understand it better.
Custom Resource Definitions serve as the schema that defines a new resource type in Kubernetes. When you create a CRD, you're essentially teaching the Kubernetes API server about a new kind of object that can be managed using standard kubectl commands and stored in etcd alongside native resources like Pods and Services.
A CRD consists of three main components:
The API Group and Version: Every CRD belongs to an API group (such as stable.devoriales.com) and has one or more versions (like v1, v2alpha1). This structure follows the same versioning pattern as built-in Kubernetes resources.
The Resource Names: Each CRD defines plural and singular forms of the resource name (crontabs and crontab), a Kind (CronTab), and optional short names (ct) for convenient kubectl usage.
The Schema: The OpenAPI v3 validation schema specifies what fields your custom resource can contain, their types, and validation rules. This schema ensures that instances of your custom resource meet your specifications.
CRDs accomplish several objectives in Kubernetes:

API Extension Without Code Modification: CRDs allow you to extend the Kubernetes API declaratively. You define new resource types using YAML manifests rather than writing Go code and compiling custom API servers.
Native Kubernetes Integration: Resources created from CRDs integrate with the Kubernetes. You can use kubectl to create, read, update, and delete custom resources. Role-Based Access Control (RBAC) rules apply to custom resources just as they do to native resources.
Persistence and Lifecycle Management: Custom resources are stored in etcd, the same distributed key-value store that holds all Kubernetes cluster data. They participate in the standard Kubernetes object lifecycle, including garbage collection and owner references.
Validation and Defaulting: CRDs support OpenAPI v3 validation schemas that enforce constraints on field values. You can specify required fields, set minimum and maximum values, define regular expression patterns, and provide default values.
When you create a CustomResourceDefinition object in Kubernetes, several processes occur:
API Endpoint Creation: The API server automatically creates RESTful API endpoints for your custom resource. For a namespaced CRD with group stable.devoriales.com and version v1, the endpoint becomes /apis/stable.devoriales.com/v1/namespaces/*/crontabs/....
Schema Registration: The API server registers your OpenAPI schema and begins validating incoming custom resource objects against it. Any attempt to create or update a custom resource that violates the schema is rejected with detailed error messages.
Storage in etcd: Custom resources are persisted in etcd using the same mechanisms as native resources. The API server handles serialization, versioning, and retrieval.
Field Pruning: By default, the API server removes (prunes) any fields in a custom resource that aren't defined in the schema. This prevents unexpected data from being stored and ensures schema compliance.
The answer depends on what you want to accomplish with your custom resources.
CRDs Alone: A CRD by itself only extends the Kubernetes API with a new resource type. You can create, read, update, and delete instances of your custom resource using kubectl, but these objects don't do anything by themselves. They're simply stored in etcd.
Adding Behavior with Controllers: To make your custom resources functional, you need a controller (often called an operator when it manages complex applications). The controller watches for changes to your custom resources and takes actions to reconcile the desired state with the actual state.
For example, you might create a CRD for a CronTab resource that specifies a schedule and a container image. Without a controller, this is just data. With a controller, you can write code that:
CronTab objectsCronTab object changesCronTab is deletedYou need to understand how to create and manage CRDs themselves which this article is about. You should be comfortable with CRD creation, validation, and basic troubleshooting.
❗In this article, we'll focus on CRDs themselves and cover how to write an operator in another article or video.
Understanding what Custom Resource Definitions exist in your cluster is a fundamental skill for cluster administrators. Kubernetes provides several methods to discover and inspect CRDs, which becomes particularly useful when working with clusters that have multiple operators and extensions installed.
The most straightforward approach to view all CRDs is using kubectl:
kubectl get customresourcedefinitions # or use short name crd
You can also describe an existing CRD like in the following example:
kubectl describe crd traefikservices.traefik.containo.us
Let's build a complete example that demonstrates CRD creation and usage. This example appears frequently in Kubernetes documentation and provides a solid foundation for understanding CRDs.
The user story:
You, a platform engineer at DevOriales, manage dozens of scheduled backup and maintenance jobs across multiple namespaces. Your team uses native Kubernetes CronJobs, but creating them requires writing lengthy YAML manifests with numerous fields. Developers frequently make mistakes with the cron syntax or forget to set resource limits.
The Solution:
You need to create a CronTab CRD that simplifies scheduled job creation. Instead of dealing with complex CronJob specifications, developers only need to provide three essential fields:
The Benefits:
stable.devoriales.com makes it clear these are custom company resourcesThe Controller (to be built):
Your team will develop a controller that watches for CronTab resources and automatically creates properly configured Kubernetes CronJobs with:
Now developers can create scheduled jobs in seconds instead of copying and modifying complex templates.
Create a file named crontab-crd.yaml:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.devoriales.com
spec:
group: stable.devoriales.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
image:
type: string
replicas:
type: integer
minimum: 1
maximum: 10
required:
- cronSpec
- image
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
Understanding the Schema:
The group field (stable.devoriales.com) defines the API group. In production, use a domain you control.
The versions array supports multiple API versions. Each version has a served flag (whether the API server exposes this version) and a storage flag (which version is stored in etcd).
The openAPIV3Schema defines the structure of your custom resource. In this example:
cronSpec must be a string matching a cron pattern (validated with a regular expression)image is a string field for the container imagereplicas is an integer between 1 and 10The scope can be either Namespaced or Cluster. Namespaced resources belong to a specific namespace, while cluster-scoped resources are global.
The names section defines how you'll refer to this resource. You can use kubectl get crontabs, kubectl get crontab, or kubectl get ct.
Apply the CustomResourceDefinition to your cluster:
kubectl apply -f crontab-crd.yaml
Verify the CRD was created:
kubectl get crd crontabs.stable.devoriales.com
You should see output indicating the CRD exists and when it was created.
Now that the CRD exists, you can create instances of your custom resource.
Create a file named my-crontab.yaml:
apiVersion: stable.devoriales.com/v1
kind: CronTab
metadata:
name: backup-crontab
spec:
cronSpec: "0 2 * * *"
image: backup-utility:v1.0
replicas: 3
Apply this custom resource:
kubectl apply -f my-crontab.yaml
Use standard kubectl commands to interact with your custom resources:
# List all crontabs
kubectl get crontabs
# Get detailed information
kubectl get crontab backup-crontab -o yaml
# Use the short name
kubectl get ct
# Describe the resource
kubectl describe crontab backup-crontab
# Delete the resource
kubectl delete crontab backup-crontab
The CRD includes validation rules.
Try creating an invalid custom resource in invalid-crontab.yaml:
apiVersion: stable.devoriales.com/v1
kind: CronTab
metadata:
name: invalid-crontab
spec:
cronSpec: "invalid cron pattern"
image: test-image:latest
replicas: 15
Apply the file:
kubectl apply -f invalid-crontab.yaml
You'll receive validation errors because:
cronSpec doesn't match the required patternreplicas value exceeds the maximum of 10When you delete a CRD, Kubernetes removes the resource type from the API server and also deletes all instances of that type, since they can no longer be validated or managed without their defining schema. Understanding this relationship is fundamental to working with Kubernetes extensibility.
Example:
In the following video, we're creating a custom resource. Then we actually delete the CRD.
The result is, the actual resource will be deleted too.

CRDs support two special subresources that add advanced capabilities:
Status Subresource: Enables separation between the desired state (spec) and the observed state (status). When enabled:
spec:
versions:
- name: v1
served: true
storage: true
subresources:
status: {}
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
replicas:
type: integer
status:
type: object
properties:
availableReplicas:
type: integer
With this configuration:
/status only modify the status fields.metadata.generation field increments only when spec changesScale Subresource: Allows your custom resource to work with kubectl scale and Horizontal Pod Autoscaler:
subresources:
scale:
specReplicasPath: .spec.replicas
statusReplicasPath: .status.replicas
labelSelectorPath: .status.labelSelector
This enables commands like:
kubectl scale crontab backup-crontab --replicas=5
Kubernetes 1.29 introduced CEL validation rules, providing more expressive validation capabilities:
openAPIV3Schema:
type: object
properties:
spec:
type: object
x-kubernetes-validations:
- rule: "self.minReplicas <= self.replicas"
message: "replicas must be greater than or equal to minReplicas"
- rule: "self.replicas <= self.maxReplicas"
message: "replicas must be less than or equal to maxReplicas"
properties:
minReplicas:
type: integer
replicas:
type: integer
maxReplicas:
type: integer
CEL rules provide:
oldSelf to validate updatesReal-world CRDs often need to support multiple API versions as they evolve:
spec:
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
# v1 schema
- name: v1beta1
served: true
storage: false
schema:
openAPIV3Schema:
# v1beta1 schema
Only one version can be the storage version (storage: true). All other versions are converted to the storage version before being saved in etcd.
storage: true/false?The storage field determines which version of your custom resource is actually saved in etcd (Kubernetes' database).
storage: true - This is the "version of record"storage: falseCustomize the output of kubectl get commands by defining additional columns:
versions:
- name: v1
served: true
storage: true
additionalPrinterColumns:
- name: Schedule
type: string
description: The cron schedule
jsonPath: .spec.cronSpec
- name: Replicas
type: integer
description: The number of replicas
jsonPath: .spec.replicas
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
Structural Schema Requirements: CRDs must have a structural schema. Ensure every field has a type defined, and avoid constructs that don't specify types clearly.
Field Pruning: By default, fields not in the schema are removed. If you need to preserve unknown fields, use x-kubernetes-preserve-unknown-fields: true, but be aware of the implications.
CRD Name Format: The CRD name must follow the format <plural>.<group>. If they don't match, the CRD creation will fail.
Version Storage Flag: Exactly one version must be marked as the storage version. Having zero or multiple storage versions causes errors.
Resource Name Conflicts: Ensure your CRD names don't conflict with existing resources in the cluster, either from Kubernetes itself or from other CRDs.
Custom Resource Definitions provide a mechanism for extending Kubernetes without modifying its core.
While CRDs alone only store data, they become powerful when combined with controllers that implement business logic.
The CRD alone is not doing anything, you need to write an operator that performs the business logic.
That will be covered in another content. Stay Tuned!
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。