惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Troy Hunt's Blog
P
Proofpoint News Feed
V
Vulnerabilities – Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
K
Kaspersky official blog
Cyberwarzone
Cyberwarzone
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
S
Securelist
L
Lohrmann on Cybersecurity
Security Latest
Security Latest
T
Threatpost
H
Heimdal Security Blog
W
WeLiveSecurity
A
Arctic Wolf
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
GRAHAM CLULEY
IT之家
IT之家
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
TaoSecurity Blog
TaoSecurity Blog
A
About on SuperTechFans
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
N
News and Events Feed by Topic
Hacker News - Newest:
Hacker News - Newest: "LLM"
Last Week in AI
Last Week in AI
T
The Blog of Author Tim Ferriss
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Azure Blog
Microsoft Azure Blog
Hugging Face - Blog
Hugging Face - Blog
Google DeepMind News
Google DeepMind News
量子位
Stack Overflow Blog
Stack Overflow Blog
Know Your Adversary
Know Your Adversary
B
Blog RSS Feed
阮一峰的网络日志
阮一峰的网络日志
WordPress大学
WordPress大学
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
AI
AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
GbyAI
GbyAI
Vercel News
Vercel News
C
Cyber Attacks, Cyber Crime and Cyber Security
Latest news
Latest news
D
Darknet – Hacking Tools, Hacker News & Cyber Security
大猫的无限游戏
大猫的无限游戏
Forbes - Security
Forbes - Security

Devoriales - DevOps and Python Tutorials

Cloud & DevOps & AI Digest: The Week of Jun 28, 2026 Cloud & DevOps & AI Digest: The Week of Jun 20, 2026 Ansible for DevOps Engineers: Architecture, Core Concepts, and Hands-On Lab Login Must-Have Kubernetes CLI Tools Every Platform Engineer Should Know Login Login Login Why Your Best Engineers Are Quitting (And How to Stop It) Login ArgoCD Vulnerability: How the ServerSideDiff Feature Exposes Kubernetes Secrets Login How Kubernetes Controls What Your Containers Can Do Login Multi-AZ Is Not Disaster Recovery: What the AWS Bahrain Outage Finally Proved Trivy Supply Chain Attack: When Your Security Scanner Becomes the Threat Is Claude Opus 4.6 Fast Mode Really Worth 6× the Price? Login Unlocking Higher Pod Density in EKS with Prefix Delegation AWS Regional NAT Gateway: What It Is and Why You Should Care Kubernetes 1.35 Timbernetes Release AWS re:Invent 2025: The Future of Kubernetes on EKS Debate Series: How Do We Control Deployment Order in Kubernetes? Debate Series: Should We Eliminate Kubernetes Secrets Entirely? Reduce Cloud Cross-Zone Data Transfer Costs with Kubernetes 1.33 trafficDistribution Building Custom Bitnami Images: A Guide for Self-Hosted Container Images New Features in Kubernetes 1.34: An Overview From Free to Fee: How Broadcom's Bitnami Monetization Disrupts DevOps Infrastructure Claude Code Cheat Sheet: The Reference Guide Kubernetes Loses Enterprise Slack Status: Discord Among Platforms Being Considered Understanding Container Security: A Guide to Docker and Pod Security Container Patterns in Kubernetes: Init Containers, Sidecars, and Co-located Containers Explained AWS Launches Serverless MCP Server: AI-Powered Development Gets a Serverless Boost Valve Responds to Alleged Steam Data Breach Reports: What Users Need to Know ArgoCD 3.0: The Evolution Toward Secure GitOps Redis Returns to Open Source: The AGPLv3 Licensing Decision New Features in Kubernetes 1.33: An Overview Prometheus: How We Slashed Memory Usage IngressNightmare: Critical Ingress-NGINX Vulnerabilities and How to Check Your Exposure New Features in Kubernetes 1.32: An Overview What to Consider If You're Not Signing Up for Bitnami Premium Certified Kubernetes Administrator (CKA) Exam Updates for 2025 DeepSeek AI and the Question of the AI Bubble Python Tops the Tiobe Index: The Most Popular Programming Languages - January 2025 2024 in Review: IT Trends, Startups, and What’s Next Inside Argo: The Open-Source Journey Captured in a CNCF Documentary Running Docker on macOS Without Docker Desktop - updated with Kubernetes installation HashiCorp Rolls Out Terraform 2.0 at HashiConf, Keeps IBM Acquisition in the Shadows Is the EU Falling Behind in the Global AI Race? Prometheus Essentials: Node Exporter And System Monitoring Prometheus Essentials: Install and Start Monitoring Your App Prometheus Essentials: Introduction To Metric Types Kubernetes Pod Scheduling Explained: Taints, Tolerations, and Node Affinity Retrieval Augmented Generation (RAG) Explained for Beginners Like Me Using Sealed Secrets with Your Kubernetes Applications
Kubernetes CRDs Explained: A Beginner-Friendly Guide to Extending the Kubernetes API
Aleksandro Matejic · 2025-11-23 · via Devoriales - DevOps and Python Tutorials

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.

What Are Custom Resource Definitions?

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.

The Purpose and Goals of CRDs

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.

How Kubernetes Handles CRDs

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.

Do You Need an Operator?

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:

  • Watches for new CronTab objects
  • Creates Kubernetes CronJobs based on the specifications
  • Updates those CronJobs when the CronTab object changes
  • Cleans up resources when a CronTab is deleted

You 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.

How To List Existing CRDs

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.

List All CRDs in the Cluster

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

Working Example: Creating a CronTab CRD

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:

  • Validation built-in: The CRD enforces valid cron patterns through regex validation
  • Safe defaults: Replica count must be between 1-10, preventing resource issues
  • Simplified interface: Developers only specify what matters: schedule, image, and scale
  • Consistent naming: Using stable.devoriales.com makes it clear these are custom company resources

The Controller (to be built):

Your team will develop a controller that watches for CronTab resources and automatically creates properly configured Kubernetes CronJobs with:

  • Resource limits (memory, CPU)
  • Monitoring labels
  • Alert configurations
  • Backup retention policies

Now developers can create scheduled jobs in seconds instead of copying and modifying complex templates.

Step 1: Define the CustomResourceDefinition

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 image
  • replicas is an integer between 1 and 10

The 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.

Step 2: Create the CRD

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.

Step 3: Create Custom Resource Instances

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

Step 4: Manage Custom Resources

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

Step 5: Test Validation

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:

  • The cronSpec doesn't match the required pattern
  • The replicas value exceeds the maximum of 10

What Happens When Deleting a CRD?

When 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.

Delete CRD

Advanced CRD Features

Subresources: Status and Scale

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:

  • Updates to /status only modify the status fields
  • Updates to the main resource endpoint don't affect status
  • The .metadata.generation field increments only when spec changes

Scale 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

Validation Rules with Common Expression Language (CEL)

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:

  • Cross-field validation (comparing multiple fields)
  • Complex logical expressions
  • Custom error messages
  • Transition rules using oldSelf to validate updates

Multiple Versions

Real-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.

What is storage: true/false?

The storage field determines which version of your custom resource is actually saved in etcd (Kubernetes' database).

Key Rules:

  • Exactly one version must have storage: true - This is the "version of record"
  • All other versions must have storage: false
  • The storage version is the canonical representation in the database

Additional Printer Columns

Customize 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

Common Pitfalls and Solutions

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.

Summary

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!