To create a Kubernetes custom resource, define its type in a CustomResourceDefinition (CRD), apply the CRD to the cluster, then create and inspect an object of that type. A CRD registers a schema and makes structured objects available through the Kubernetes API; it does not make those objects perform application-specific work. Add a controller only when you need ongoing reconciliation or automation.
Is a custom resource the right fit?
A custom resource is an instance of a resource type added to a Kubernetes installation through an API extension. It is a good fit when users should declare configuration or desired state using Kubernetes API conventions, kubectl, watches, or automation. Kubernetes documentation describes the boundary plainly: “On their own, custom resources let you store and retrieve structured data.” Kubernetes: Custom Resources
As an Amazon Associate I earn from qualifying purchases.
- Choose a CRD when the data deserves its own API type and benefits from Kubernetes clients, authorization, discovery, or automation.
- Choose a ConfigMap for existing file-oriented configuration that a workload consumes, especially when a new API type is unnecessary.
- Consider an aggregated API or standalone API when you need imperative request/response operations, nonstandard REST paths, sustained high-volume traffic, or storage for large end-user data. A CRD is not a general-purpose application database.
What belongs in the API design?
Before writing YAML, decide what the resource means to its users and how its lifecycle should work. A CRD definition is cluster-wide, while the custom objects it enables can be either namespaced or cluster-scoped. The CRD’s name is formed from the resource’s plural name and API group, so choose these identifiers deliberately.
- Group: a namespace for the API type, commonly expressed as a DNS-style domain.
- Plural and singular names: used for API and command-line discovery, such as
widgetsandwidget. - Kind: the object type name, such as
Widget. - Scope: whether each object belongs to a namespace or exists at cluster scope.
- Version and schema: the served API version and the fields, types, and validation rules clients may use.
Choose scope to match ownership
A namespaced custom object is tied to a namespace; deleting that namespace deletes its objects. This suits resources owned by a particular team or application namespace. A cluster-scoped object is not attached to a namespace and is appropriate only when its meaning and access pattern are genuinely cluster-wide. CRD definitions themselves are not namespaced.
#1 Best Overall
Make the schema express desired state
Define the fields users need and their types in the CRD’s OpenAPI v3 schema. Use schema validation to reject malformed values rather than accepting arbitrary input by default. A catch-all object can be appropriate when preserving arbitrary data is a requirement, but otherwise it weakens the API’s clarity and validation. Kubernetes also supports capabilities such as status subresources and admission webhooks; add them when they serve a defined API need, not simply because they are available.
How do I create my first Kubernetes custom resource?
The following minimal example defines a namespaced Widget type in the demo.example.com API group. Its schema requires a string field named message. Save the CRD as widget-crd.yaml:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: widgets.demo.example.com
spec:
group: demo.example.com
scope: Namespaced
names:
plural: widgets
singular: widget
kind: Widget
shortNames:
- wdg
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
message:
type: string
required:
- message
This example is for a cluster whose Kubernetes API supports apiextensions.k8s.io/v1. Confirm the target cluster’s release and the current CRD documentation before adapting manifests or relying on version-specific features.
- Apply the type definition: run
kubectl apply -f widget-crd.yaml. This registers the new API type; it does not create a controller. - Wait for it to be established: run
kubectl wait --for=condition=Established --timeout=60s crd/widgets.demo.example.com. - Check API discovery: run
kubectl api-resources --api-group=demo.example.com. The output should includewidgets. - Create an instance: save the following as
widget.yamland apply it withkubectl apply -f widget.yaml:
apiVersion: demo.example.com/v1
kind: Widget
metadata:
name: sample
namespace: default
spec:
message: hello
- Read the object: run
kubectl get widgets -n defaultorkubectl get widget sample -n default -o yaml. The API server should return the stored object.
The official Kubernetes task guide demonstrates applying a CRD and then working with its registered resource: Create a CustomResourceDefinition. These commands illustrate the basic flow; they do not replace checking the CRD schema and API behavior against your cluster version.
Do I need a controller for a CRD?
No, not to register, store, retrieve, or manage custom objects through the Kubernetes API. You do need a controller if users expect the declared state to trigger continuous action. A controller watches resources and reconciles the cluster or external systems toward the desired state. For example, a controller for a Widget might create or update other Kubernetes objects when a user changes spec.
| Approach | What it provides | What it does not provide by itself |
|---|---|---|
| CRD only | A registered API type with schema-backed structured data that can be stored and retrieved. | Application-specific automation or reconciliation. |
| CRD plus controller | The API type plus ongoing logic that observes declared state and acts on it. | A guarantee of correct behavior without implementing, operating, and securing that controller. |
An operator is a controller-based extension that encodes application-specific operational knowledge. If you decide that behavior is needed, the Kubernetes operator guide lists options including Kubebuilder, Operator Framework, Kopf, and Java Operator SDK; none is a universal choice. Kubernetes: Operator pattern
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.How should I plan versions and permissions?
Make versioning explicit
CRDs can define multiple versions. Mark which versions are served to clients and which version is used for storage. If versions have schema differences that require custom conversion, Kubernetes documents conversion webhooks as the mechanism for translating objects between versions. Treat version changes as API migrations: decide how clients move, how old objects are converted, and when an older version stops being served. Kubernetes: Versioning a CRD
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Grant access deliberately
Custom resources use Kubernetes authentication, authorization, and audit logging, but existing roles do not automatically grant users access to a newly introduced resource type. Add explicit RBAC rules for the API group and resource, and grant only the verbs and scope users or controllers actually require. Kubernetes: Using RBAC Authorization
Best Value
What should I verify before relying on it?
- Does the resource represent Kubernetes-style configuration or desired state rather than large application data or high-volume traffic?
- Are the group, names, kind, scope, version, and schema understandable to the people who will create and operate the object?
- Can the API server validate the inputs that matter, and is arbitrary data accepted only if that is intentional?
- Have you tested discovery, creation, retrieval, and invalid-field behavior on the Kubernetes release you target?
- Have you written the RBAC permissions required by both human users and any controller?
- If a package installs the CRD together with a controller, have you considered the controller’s third-party code, permissions, and operational lifecycle as a separate component?
Selectable fields for custom resources are stable starting in Kubernetes v1.32 and were first available in v1.30, according to the Kubernetes versioned documentation. This is a version-specific capability; check the documentation for the release you operate before depending on it. Kubernetes: Custom Resources
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




