



{"id":1662,"date":"2023-11-02T02:20:26","date_gmt":"2023-11-02T02:20:26","guid":{"rendered":"https:\/\/www.w3computing.com\/articles\/?p=1662"},"modified":"2023-11-02T02:20:31","modified_gmt":"2023-11-02T02:20:31","slug":"kubernetes-custom-resource-definitions-crds-implementation","status":"publish","type":"post","link":"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/","title":{"rendered":"Kubernetes Custom Resource Definitions (CRDs) Implementation"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Kubernetes has taken the tech world by storm, thanks to its robust platform for managing containerized applications in a clustered environment. It&#8217;s a hit among developers and system administrators for its ability to ensure that cloud-native applications run smoothly and reliably. A key player in this orchestration magic is the Custom Resource Definition (CRD), a potent feature that allows users to create their own customized extensions of the Kubernetes API.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide aims to shed light on how to implement CRDs in a Kubernetes setup. And also to empower you with the knowledge and skills to design, deploy, and manage your Custom Resource Definitions like a pro. We&#8217;re targeting individuals with a decent grasp on Kubernetes basics, who want to explore the custom resources to tailor Kubernetes to their needs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Before we hit the road, let&#8217;s make sure we&#8217;ve got our gear in check. You&#8217;ll need:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A working knowledge of Kubernetes basics, including Pods, Deployments, and Services.<\/li>\n\n\n\n<li>Familiarity with YAML syntax and basic scripting.<\/li>\n\n\n\n<li>A Kubernetes cluster where you can flex your CRD muscles &#8211; you can set one up on your machine using Minikube or use a cloud-based solution like Google Kubernetes Engine (GKE).<\/li>\n\n\n\n<li>A comfy seat, a cup of coffee (or tea, if that\u2019s your jam), and an explorer\u2019s spirit.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding Custom Resource Definitions (CRDs)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Definition and Use Cases of CRDs<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Custom Resource Definitions (CRDs) are an exciting extension of the Kubernetes API that empower users to create their own bespoke Kubernetes objects. Imagine you\u2019re crafting a complex application that has unique operational needs, something the standard Kubernetes objects like Pods or Deployments can&#8217;t quite handle. This is where CRDs come into play, offering a customizable framework to define your objects, mirroring the behavior of native Kubernetes objects.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Some compelling use cases of CRDs include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Configuring Custom Software:<\/strong> CRDs allow for the configuration of custom software components running within your Kubernetes cluster.<\/li>\n\n\n\n<li><strong>Managing Operational Processes:<\/strong> CRDs can encapsulate operational logic, helping manage processes like backups, restores, or updates in a Kubernetes-native way.<\/li>\n\n\n\n<li><strong>Abstracting Infrastructure Setups:<\/strong> Through CRDs, users can abstract away complex infrastructure setups, providing a simplified interface to manage underlying resources.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Comparison of CRDs with Built-in Kubernetes Objects<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Now, let\u2019s draw a comparison between CRDs and built-in Kubernetes objects to better understand their distinctions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Bespoke Versus Standard:<\/strong> Built-in objects like Pods, Services, and Deployments are standard across all Kubernetes installations. They cater to common orchestration tasks and are supported out-of-the-box. On the flip side, CRDs are tailor-made, designed by users to serve specific needs within their Kubernetes environments.<\/li>\n\n\n\n<li><strong>API Extensibility:<\/strong> CRDs extend the Kubernetes API, allowing for the creation of new types of objects with custom schemas. Built-in objects, however, are predefined within the Kubernetes API and adhere to fixed schemas.<\/li>\n\n\n\n<li><strong>Maintenance:<\/strong> Built-in objects are maintained by the Kubernetes community, ensuring stability and support across versions. Conversely, the maintenance of CRDs rests on the shoulders of the users or teams that create them. This includes ensuring compatibility with different Kubernetes versions and handling upgrades or deprecations.<\/li>\n\n\n\n<li><strong>Tooling:<\/strong> Kubernetes\u2019 built-in tooling like kubectl and dashboard work seamlessly with built-in objects. For CRDs, you might need to develop or adapt tooling to manage and visualize your custom resources effectively.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Setting Up The Environment<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To begin we need a conducive environment. In this section, we&#8217;ll set up our toolkit, spin up a Kubernetes cluster, and ensure everything is in tip-top shape.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tools and Resources Required<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Kubernetes Cluster:<\/strong> You can either set one up locally using Minikube or Kind, or opt for a cloud-based solution like Google Kubernetes Engine (GKE), Azure Kubernetes Service (AKS), or Amazon Elastic Kubernetes Service (EKS).<\/li>\n\n\n\n<li><strong>Kubectl:<\/strong> This is your trusty command-line tool for interacting with your Kubernetes cluster.<\/li>\n\n\n\n<li><strong>Code Editor:<\/strong> Any text editor or Integrated Development Environment (IDE) you&#8217;re comfortable with. Visual Studio Code, or IntelliJ IDEA are solid choices.<\/li>\n\n\n\n<li><strong>Version Control System:<\/strong> A tool like Git to track changes to your configuration files and code.<\/li>\n\n\n\n<li><strong>Docker:<\/strong> As Kubernetes is a container orchestrator, you&#8217;ll need Docker to create and manage your container images.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Setting up a Kubernetes Cluster<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Local Setup using Minikube:<\/strong>\n<ul class=\"wp-block-list\">\n<li>Install <a href=\"https:\/\/minikube.sigs.k8s.io\/docs\/start\/\">Minikube<\/a>.<\/li>\n\n\n\n<li>Start a Minikube instance with the command <code>minikube start<\/code>.<\/li>\n\n\n\n<li>Once the instance is up, you can interact with it using <code>kubectl<\/code>.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Cloud-based Setup (e.g., using GKE):<\/strong>\n<ul class=\"wp-block-list\">\n<li>Create an account or log in to the <a href=\"https:\/\/cloud.google.com\/\">Google Cloud Platform<\/a>.<\/li>\n\n\n\n<li>Navigate to the Kubernetes Engine and create a new cluster.<\/li>\n\n\n\n<li>Connect to your cluster using <code>kubectl<\/code> by following the provided instructions.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Verifying the Setup<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Now that our Kubernetes cluster is up and humming, let\u2019s ensure everything&#8217;s operational:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Check Cluster Status:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl cluster-info<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Verify Nodes:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl get nodes<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Check System Pods:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl get pods --namespace kube-system<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If all the nodes are in a Ready state and system pods are running fine, your Kubernetes environment is set, you&#8217;re ready for the next step.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating Your First Custom Resource Definition<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The magic of Custom Resource Definitions (CRDs) unfurls as you design your own Kubernetes objects. Let\u2019s roll up our sleeves and create our first CRD, shall we?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Designing a CRD Schema<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A CRD schema is the blueprint of your custom resource. It defines the structure, types, and validation of data. For our example, let\u2019s create a CRD for a fictional &#8220;Planet&#8221; resource, where each planet has a name, a type (gas or rocky), and a number of moons.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Identify the Properties:<\/strong>\n<ul class=\"wp-block-list\">\n<li>Name: string<\/li>\n\n\n\n<li>Type: enum (gas, rocky)<\/li>\n\n\n\n<li>MoonCount: integer<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Set Validation Rules:<\/strong>\n<ul class=\"wp-block-list\">\n<li>Name: 1-40 characters, required<\/li>\n\n\n\n<li>Type: one of the predefined values, required<\/li>\n\n\n\n<li>MoonCount: non-negative integer, optional<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Writing a CRD Manifest<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create a file named <code>planet-crd.yaml<\/code> and pop in the following content:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-attr\">apiVersion:<\/span> <span class=\"hljs-string\">apiextensions.k8s.io\/v1<\/span>\r\n<span class=\"hljs-attr\">kind:<\/span> <span class=\"hljs-string\">CustomResourceDefinition<\/span>\r\n<span class=\"hljs-attr\">metadata:<\/span>\r\n  <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">planets.astronomy.example.com<\/span>\r\n<span class=\"hljs-attr\">spec:<\/span>\r\n  <span class=\"hljs-attr\">group:<\/span> <span class=\"hljs-string\">astronomy.example.com<\/span>\r\n  <span class=\"hljs-attr\">versions:<\/span>\r\n    <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">v1<\/span>\r\n      <span class=\"hljs-attr\">served:<\/span> <span class=\"hljs-literal\">true<\/span>\r\n      <span class=\"hljs-attr\">storage:<\/span> <span class=\"hljs-literal\">true<\/span>\r\n  <span class=\"hljs-attr\">scope:<\/span> <span class=\"hljs-string\">Namespaced<\/span>\r\n  <span class=\"hljs-attr\">names:<\/span>\r\n    <span class=\"hljs-attr\">plural:<\/span> <span class=\"hljs-string\">planets<\/span>\r\n    <span class=\"hljs-attr\">singular:<\/span> <span class=\"hljs-string\">planet<\/span>\r\n    <span class=\"hljs-attr\">kind:<\/span> <span class=\"hljs-string\">Planet<\/span>\r\n  <span class=\"hljs-attr\">validation:<\/span>\r\n    <span class=\"hljs-attr\">openAPIV3Schema:<\/span>\r\n      <span class=\"hljs-attr\">properties:<\/span>\r\n        <span class=\"hljs-attr\">spec:<\/span>\r\n          <span class=\"hljs-attr\">properties:<\/span>\r\n            <span class=\"hljs-attr\">name:<\/span>\r\n              <span class=\"hljs-attr\">type:<\/span> <span class=\"hljs-string\">string<\/span>\r\n              <span class=\"hljs-attr\">minLength:<\/span> <span class=\"hljs-number\">1<\/span>\r\n              <span class=\"hljs-attr\">maxLength:<\/span> <span class=\"hljs-number\">40<\/span>\r\n            <span class=\"hljs-attr\">type:<\/span>\r\n              <span class=\"hljs-attr\">type:<\/span> <span class=\"hljs-string\">string<\/span>\r\n              <span class=\"hljs-attr\">enum:<\/span>\r\n                <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">gas<\/span>\r\n                <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">rocky<\/span>\r\n            <span class=\"hljs-attr\">moonCount:<\/span>\r\n              <span class=\"hljs-attr\">type:<\/span> <span class=\"hljs-string\">integer<\/span>\r\n              <span class=\"hljs-attr\">minimum:<\/span> <span class=\"hljs-number\">0<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Applying the CRD Manifest to the Kubernetes Cluster:<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Time to bring our CRD to life in the Kubernetes cluster:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl apply -f planet-crd.yaml<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Verifying the CRD Creation:<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Now let\u2019s ensure our new CRD is alive and kicking:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>List CRDs:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl get crds<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Describe CRD:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl describe crd planets.astronomy.example.com<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Upon successful verification, you&#8217;ll see the <code>planets.astronomy.example.com<\/code> CRD listed, and the <code>describe<\/code> command will provide detailed information about the CRD schema and other configurations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Custom Resource (CR) Operations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">With our CRD for planets set up, we can now perform typical CRUD (Create, Read, Update, Delete) operations on custom resource (CR) instances. Additionally, we\u2019ll explore how to watch for changes to our custom resources using the Kubernetes API.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Creating Instances of the Custom Resource:<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Creating a Planet Resource:<\/strong> Create a file named <code>planet-earth.yaml<\/code> with the following content to represent planet Earth:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-attr\">apiVersion:<\/span> <span class=\"hljs-string\">astronomy.example.com\/v1<\/span>\r\n<span class=\"hljs-attr\">kind:<\/span> <span class=\"hljs-string\">Planet<\/span>\r\n<span class=\"hljs-attr\">metadata:<\/span>\r\n  <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">earth<\/span>\r\n<span class=\"hljs-attr\">spec:<\/span>\r\n  <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">Earth<\/span>\r\n  <span class=\"hljs-attr\">type:<\/span> <span class=\"hljs-string\">rocky<\/span>\r\n  <span class=\"hljs-attr\">moonCount:<\/span> <span class=\"hljs-number\">1<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Apply this manifest to create the Earth resource:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl apply -f planet-earth.yaml<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Reading, Updating, and Deleting Custom Resource Instances:<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Reading a Custom Resource:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl get planet earth<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Updating a Custom Resource:<\/strong> Update the <code>moonCount<\/code> field in <code>planet-earth.yaml<\/code> to <code>2<\/code> (just for fun), then apply the change:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl apply -f planet-earth.yaml<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Verify the update:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl get planet earth -o yaml<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Deleting a Custom Resource:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl delete planet earth<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Watching Changes to Custom Resources using Kubernetes API<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Kubernetes provides a watch API to observe changes to resources in real-time. This is quite handy to track updates to our custom resources.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Watching CRs from the Command Line:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl get planets --watch<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Now, in a separate terminal, create, update or delete a planet resource and observe the changes in the watch terminal.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Watching CRs Programmatically:<\/strong> For a more advanced and programmatic approach, you can use client libraries like client-go to watch for changes to your custom resources within your application code. Here\u2019s a simplified example in Go:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">import (\r\n    <span class=\"hljs-string\">\"context\"<\/span>\r\n    <span class=\"hljs-string\">\"fmt\"<\/span>\r\n    <span class=\"hljs-string\">\"k8s.io\/apimachinery\/pkg\/apis\/meta\/v1\"<\/span>\r\n    <span class=\"hljs-string\">\"k8s.io\/client-go\/kubernetes\"<\/span>\r\n    <span class=\"hljs-string\">\"k8s.io\/client-go\/rest\"<\/span>\r\n)\r\n\r\nfunc <span class=\"hljs-function\"><span class=\"hljs-title\">watchPlanets<\/span><\/span>() {\r\n    config, err := rest.InClusterConfig()\r\n    <span class=\"hljs-keyword\">if<\/span> err != nil {\r\n        panic(err)\r\n    }\r\n    clientset, err := kubernetes.NewForConfig(config)\r\n    <span class=\"hljs-keyword\">if<\/span> err != nil {\r\n        panic(err)\r\n    }\r\n\r\n    planetWatcher, err := clientset.ExtensionsV1beta1().CustomResourceDefinitions().Watch(context.TODO(), v1.ListOptions{})\r\n    <span class=\"hljs-keyword\">if<\/span> err != nil {\r\n        panic(err)\r\n    }\r\n\r\n    <span class=\"hljs-keyword\">for<\/span> event := range planetWatcher.<span class=\"hljs-function\"><span class=\"hljs-title\">ResultChan<\/span><\/span>() {\r\n        fmt.Printf(<span class=\"hljs-string\">\"Event: %v\\n\"<\/span>, event.Type)\r\n    }\r\n}\r\n\r\nfunc <span class=\"hljs-function\"><span class=\"hljs-title\">main<\/span><\/span>() {\r\n    watchPlanets()\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">In this section, we\u2019ve explored the basic operations you can perform on custom resources and how to keep an eye on changes to these resources.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementing Custom Controllers<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Custom controllers are the driving force behind the operational logic of your CRDs. They observe the state of your resources and take actions to steer the system towards the desired state. Let&#8217;s see how we can create a custom controller for our Planet CRD.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Understanding the Controller Pattern in Kubernetes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In Kubernetes, controllers are control loops that watch the state of your system, and then make or request changes where necessary. They operate on a reconciliation model, continuously ensuring that the current state matches the desired state defined by the CRD.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Designing and Implementing a Custom Controller for the CRD<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Creating a custom controller involves several steps:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Set Up Your Development Environment:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Install <a href=\"https:\/\/golang.org\/doc\/install\">Go<\/a>.<\/li>\n\n\n\n<li>Set up the <a href=\"https:\/\/book.kubebuilder.io\/quick-start.html\">Kubebuilder<\/a> toolchain, which provides scaffolding for your controller project.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Create a New Controller Project:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubebuilder init --domain example.com --repo github.com\/example\/astronomy<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Create a Controller for the Planet CRD:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubebuilder create api --group astronomy --version v1 --kind Planet<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Implement Your Controller Logic:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Open the generated controller file located at <code>controllers\/planet_controller.go<\/code>.<\/li>\n\n\n\n<li>Implement the Reconcile method to add the logic for creating, updating, and deleting planets.<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-params\">(r *PlanetReconciler)<\/span> <span class=\"hljs-title\">Reconcile<\/span><span class=\"hljs-params\">(ctx context.Context, req ctrl.Request)<\/span> <span class=\"hljs-params\">(ctrl.Result, error)<\/span><\/span> {\r\n    <span class=\"hljs-comment\">\/\/ Your reconciliation logic here...<\/span>\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Register Your Controller:<\/strong> In the <code>main.go<\/code> file, ensure your controller is set up with the manager.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span><\/span> {\r\n    mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\r\n        Scheme:             scheme,\r\n        MetricsBindAddress: metricsAddr,\r\n        Port:               <span class=\"hljs-number\">9443<\/span>,\r\n        LeaderElection:     enableLeaderElection,\r\n        LeaderElectionID:   <span class=\"hljs-string\">\"f1c5cede.astronomy.example.com\"<\/span>,\r\n    })\r\n    <span class=\"hljs-keyword\">if<\/span> err != <span class=\"hljs-literal\">nil<\/span> {\r\n        setupLog.Error(err, <span class=\"hljs-string\">\"unable to start manager\"<\/span>)\r\n        os.Exit(<span class=\"hljs-number\">1<\/span>)\r\n    }\r\n\r\n    <span class=\"hljs-keyword\">if<\/span> err = (&amp;controllers.PlanetReconciler{\r\n        Client: mgr.GetClient(),\r\n        Log:    ctrl.Log.WithName(<span class=\"hljs-string\">\"controllers\"<\/span>).WithName(<span class=\"hljs-string\">\"Planet\"<\/span>),\r\n        Scheme: mgr.GetScheme(),\r\n    }).SetupWithManager(mgr); err != <span class=\"hljs-literal\">nil<\/span> {\r\n        setupLog.Error(err, <span class=\"hljs-string\">\"unable to create controller\"<\/span>, <span class=\"hljs-string\">\"controller\"<\/span>, <span class=\"hljs-string\">\"Planet\"<\/span>)\r\n        os.Exit(<span class=\"hljs-number\">1<\/span>)\r\n    }\r\n\r\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Verifying the Custom Controller\u2019s Functionality:<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Build and Deploy Your Controller:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">make docker-build docker-push IMG=&lt;your-image-tag&gt;\r\nmake deploy IMG=&lt;your-image-tag&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Test Your Controller:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create, update, and delete Planet resources to observe how your controller reacts to these changes.<\/li>\n\n\n\n<li>Check the controller logs for any errors or information messages that can help verify its functionality.<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl logs -l control-plane=controller-manager -n system --tail=-1<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Verify Desired Behavior:<\/strong> Based on the logic implemented in your controller, verify if the system&#8217;s state transitions correctly according to the changes in the Planet resources.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With a custom controller in play, your Planet CRD is now powered with the operational logic to manage the lifecycle of planet instances, making your Kubernetes setup more intelligent and self-reliant.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Validating Custom Resources<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Validation is a crucial step to ensure that the custom resources conform to the desired specifications. By enforcing a well-defined structure and rules, we can catch errors early and maintain a healthy state within our Kubernetes cluster. Let\u2019s explore how to implement validation for our Planet CRD and test it with different custom resource instances.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Implementing Validation Logic in CRD Manifest<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ve already set up basic validation in our Planet CRD manifest earlier, enforcing certain field types and value ranges. However, let&#8217;s expand the validation to ensure the <code>name<\/code> field is not empty and <code>moonCount<\/code> is non-negative.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Update your <code>planet-crd.yaml<\/code> with the following validation block:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\">  <span class=\"hljs-attr\">validation:<\/span>\r\n    <span class=\"hljs-attr\">openAPIV3Schema:<\/span>\r\n      <span class=\"hljs-attr\">properties:<\/span>\r\n        <span class=\"hljs-attr\">spec:<\/span>\r\n          <span class=\"hljs-attr\">properties:<\/span>\r\n            <span class=\"hljs-attr\">name:<\/span>\r\n              <span class=\"hljs-attr\">type:<\/span> <span class=\"hljs-string\">string<\/span>\r\n              <span class=\"hljs-attr\">minLength:<\/span> <span class=\"hljs-number\">1<\/span>\r\n              <span class=\"hljs-attr\">maxLength:<\/span> <span class=\"hljs-number\">40<\/span>\r\n              <span class=\"hljs-attr\">pattern:<\/span> <span class=\"hljs-string\">'^&#91;a-zA-Z0-9]+(?:&#91; -]&#91;a-zA-Z0-9]+)*$'<\/span>\r\n            <span class=\"hljs-attr\">type:<\/span>\r\n              <span class=\"hljs-attr\">type:<\/span> <span class=\"hljs-string\">string<\/span>\r\n              <span class=\"hljs-attr\">enum:<\/span>\r\n                <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">gas<\/span>\r\n                <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">rocky<\/span>\r\n            <span class=\"hljs-attr\">moonCount:<\/span>\r\n              <span class=\"hljs-attr\">type:<\/span> <span class=\"hljs-string\">integer<\/span>\r\n              <span class=\"hljs-attr\">minimum:<\/span> <span class=\"hljs-number\">0<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">In the above block:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>We added a <code>pattern<\/code> to the <code>name<\/code> field to ensure it follows a specific regex pattern.<\/li>\n\n\n\n<li>The <code>enum<\/code> for the <code>type<\/code> field ensures that only specified values are accepted.<\/li>\n\n\n\n<li>The <code>minimum<\/code> constraint on <code>moonCount<\/code> ensures a non-negative value.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Apply the updated CRD manifest:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl apply -f planet-crd.yaml<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Testing Validation with Different Custom Resource Instances:<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Now, let\u2019s test our validation logic by creating different Planet resource instances.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Valid Resource:<\/strong> Create a file named <code>planet-jupiter.yaml<\/code> with the following content:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-attr\">apiVersion:<\/span> <span class=\"hljs-string\">astronomy.example.com\/v1<\/span>\r\n<span class=\"hljs-attr\">kind:<\/span> <span class=\"hljs-string\">Planet<\/span>\r\n<span class=\"hljs-attr\">metadata:<\/span>\r\n  <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">jupiter<\/span>\r\n<span class=\"hljs-attr\">spec:<\/span>\r\n  <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">Jupiter<\/span>\r\n  <span class=\"hljs-attr\">type:<\/span> <span class=\"hljs-string\">gas<\/span>\r\n  <span class=\"hljs-attr\">moonCount:<\/span> <span class=\"hljs-number\">79<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Apply the manifest:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl apply -f planet-jupiter.yaml<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You should see a success message indicating the resource has been created.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Invalid Resource &#8211; Negative Moon Count:<\/strong> Create a file named <code>planet-negative-moon.yaml<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-attr\">apiVersion:<\/span> <span class=\"hljs-string\">astronomy.example.com\/v1<\/span>\r\n<span class=\"hljs-attr\">kind:<\/span> <span class=\"hljs-string\">Planet<\/span>\r\n<span class=\"hljs-attr\">metadata:<\/span>\r\n  <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">negative-moon<\/span>\r\n<span class=\"hljs-attr\">spec:<\/span>\r\n  <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">Negative<\/span> <span class=\"hljs-string\">Moon<\/span>\r\n  <span class=\"hljs-attr\">type:<\/span> <span class=\"hljs-string\">rocky<\/span>\r\n  <span class=\"hljs-attr\">moonCount:<\/span> <span class=\"hljs-number\">-5<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Try to apply the manifest:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">kubectl<\/span> <span class=\"hljs-selector-tag\">apply<\/span> <span class=\"hljs-selector-tag\">-f<\/span> <span class=\"hljs-selector-tag\">planet-negative-moon<\/span><span class=\"hljs-selector-class\">.yaml<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You should see an error message indicating the <code>moonCount<\/code> cannot be negative.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Invalid Resource &#8211; Invalid Type:<\/strong> Create a file named <code>planet-invalid-type.yaml<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-attr\">apiVersion:<\/span> <span class=\"hljs-string\">astronomy.example.com\/v1<\/span>\r\n<span class=\"hljs-attr\">kind:<\/span> <span class=\"hljs-string\">Planet<\/span>\r\n<span class=\"hljs-attr\">metadata:<\/span>\r\n  <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">invalid-type<\/span>\r\n<span class=\"hljs-attr\">spec:<\/span>\r\n  <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">Invalid<\/span> <span class=\"hljs-string\">Type<\/span>\r\n  <span class=\"hljs-attr\">type:<\/span> <span class=\"hljs-string\">unknown<\/span>\r\n  <span class=\"hljs-attr\">moonCount:<\/span> <span class=\"hljs-number\">0<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Try to apply the manifest:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl apply -f planet-invalid-type.yaml<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You should see an error message indicating the <code>type<\/code> field has an invalid value.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Versioning and Updating CRDs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">As your project evolves, you may need to change the structure of your custom resources. Versioning and updating CRDs in a backward-compatible manner is essential to ensure a smooth transition and to prevent disruptions in your system.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Strategies for Versioning CRDs<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Semantic Versioning:<\/strong> Adopt a <a href=\"https:\/\/semver.org\/\">semantic versioning<\/a> scheme to clearly communicate the changes in different versions of your CRD.<\/li>\n\n\n\n<li><strong>API Versioning:<\/strong> Utilize the <code>apiVersion<\/code> field to indicate the version of your CRD, e.g., <code>v1<\/code>, <code>v2<\/code>, etc.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Updating a CRD Schema<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Non-breaking Changes:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Add new optional fields or new accepted values for existing fields.<\/li>\n\n\n\n<li>Apply the updated CRD manifest using <code>kubectl apply<\/code>.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">bashCopy code<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>kubectl apply -f updated-planet-crd.yaml<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Breaking Changes:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create a new version of your CRD, say <code>v2<\/code>, without removing the old version.<\/li>\n\n\n\n<li>Update your controllers to handle the new version.<\/li>\n\n\n\n<li>Encourage users to transition to the new version over time.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Managing CRD Backward Compatibility<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Conversion Webhooks:<\/strong> Implement conversion webhooks to translate between different versions of your CRD. This way, you can support multiple versions at the same time.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-30\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-attr\">apiVersion:<\/span> <span class=\"hljs-string\">apiextensions.k8s.io\/v1<\/span>\r\n<span class=\"hljs-attr\">kind:<\/span> <span class=\"hljs-string\">CustomResourceDefinition<\/span>\r\n<span class=\"hljs-comment\"># ...<\/span>\r\n<span class=\"hljs-attr\">spec:<\/span>\r\n  <span class=\"hljs-attr\">conversion:<\/span>\r\n    <span class=\"hljs-attr\">strategy:<\/span> <span class=\"hljs-string\">Webhook<\/span>\r\n    <span class=\"hljs-attr\">webhook:<\/span>\r\n      <span class=\"hljs-attr\">clientConfig:<\/span>\r\n        <span class=\"hljs-attr\">service:<\/span>\r\n          <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">webhook-service<\/span>\r\n          <span class=\"hljs-attr\">namespace:<\/span> <span class=\"hljs-string\">default<\/span>\r\n          <span class=\"hljs-attr\">path:<\/span> <span class=\"hljs-string\">\"\/convert\"<\/span>\r\n      <span class=\"hljs-attr\">conversionReviewVersions:<\/span> <span class=\"hljs-string\">&#91;\"v1\",<\/span> <span class=\"hljs-string\">\"v2\"<\/span><span class=\"hljs-string\">]<\/span>\r\n<span class=\"hljs-comment\"># ...<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-30\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Deprecation Notices:<\/strong> If a field or an entire CRD version is being deprecated, communicate this clearly through deprecation notices in the CRD manifest and your project documentation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Support Multiple Versions:<\/strong> Keep support for older versions for a reasonable period, allowing users to transition to the newer version.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-31\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-comment\"># ...<\/span>\r\n<span class=\"hljs-attr\">spec:<\/span>\r\n  <span class=\"hljs-attr\">versions:<\/span>\r\n    <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">v1<\/span>\r\n      <span class=\"hljs-attr\">served:<\/span> <span class=\"hljs-literal\">true<\/span>\r\n      <span class=\"hljs-attr\">storage:<\/span> <span class=\"hljs-literal\">false<\/span>\r\n    <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">v2<\/span>\r\n      <span class=\"hljs-attr\">served:<\/span> <span class=\"hljs-literal\">true<\/span>\r\n      <span class=\"hljs-attr\">storage:<\/span> <span class=\"hljs-literal\">true<\/span>\r\n<span class=\"hljs-comment\"># ...<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-31\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">By carefully managing the versioning and updating of your CRDs, you ensure a stable and reliable system, even as your custom resources evolve over time. This practice is vital for the longevity and maintainability of your Kubernetes setup.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Debugging and Monitoring CRD Implementations<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Inevitably, you may encounter issues or unexpected behavior with your CRD implementations. Being adept at debugging and monitoring is crucial to diagnose and resolve such issues efficiently.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Common Issues and Troubleshooting Steps:<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>CRD Validation Errors:<\/strong> Check the error messages for details about the validation failure. Verify the CRD manifest for any syntax errors or incorrect field specifications.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Custom Controller Failures:<span style=\"background-color: rgb(255, 255, 255); font-weight: 300;\"> Inspect the controller logs for any errors or warnings.<\/span><\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-32\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl logs -l control-plane=controller-manager -n system --tail=-1<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-32\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Ensure the controller is running and has the necessary RBAC permissions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Resource Synchronization Issues: <span style=\"background-color: rgb(255, 255, 255); font-weight: 300;\">Check the status and events of the custom resource for any synchronization or reconciliation errors.<\/span><\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-33\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl describe &lt;kind&gt; &lt;name&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-33\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Custom Resource Creation Failures:<\/strong> Ensure that the CRD is correctly installed and the API version matches the one specified in the custom resource manifest.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Monitoring Custom Resources and Controllers using Kubernetes Tools:<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Logging:<\/strong> Configure logging levels in your controllers to capture necessary information. Use centralized logging systems like ELK Stack (Elasticsearch, Logstash, Kibana) or Splunk to aggregate and analyze logs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Metrics:<\/strong> Expose custom metrics from your controllers using libraries like <a href=\"https:\/\/prometheus.io\/\">Prometheus<\/a>. Monitor these metrics using Grafana or other monitoring tools to get insights into the performance and behavior of your CRD implementations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Events: <span style=\"background-color: rgb(255, 255, 255); font-weight: 300;\">Emit Kubernetes events from your controllers to signal significant occurrences.<\/span><\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-34\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">eventBroadcaster := record.NewBroadcaster()\r\neventBroadcaster.StartRecordingToSink(&amp;v1core.EventSinkImpl{Interface: kubeClientset.CoreV1().Events(<span class=\"hljs-string\">\"\"<\/span>)})\r\nrecorder := eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: controllerName})\r\nrecorder.Event(customResource, corev1.EventTypeWarning, <span class=\"hljs-string\">\"FailedSync\"<\/span>, <span class=\"hljs-string\">\"Failed to sync the custom resource\"<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-34\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Dashboards:<\/strong> Utilize Kubernetes dashboards to monitor the state of your custom resources and controllers. Customize dashboards to include information specific to your CRD implementations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Alerting:<\/strong> Set up alerting rules based on the metrics and events to get notified about critical issues or abnormal behavior.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Audit Logs:<\/strong> Utilize Kubernetes audit logs to track changes to your custom resources and monitor access to your CRD API.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Best Practices<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Adhering to best practices is crucial for the maintainability, security, and performance of your CRD implementations. Here are some key areas:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Naming Conventions:<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Consistent Naming:<\/strong> Employ a consistent naming convention for your CRDs, custom resources, and controllers. This includes using descriptive names and following the camelCase or kebab-case conventions as appropriate.<\/li>\n\n\n\n<li><strong>Domain-Specific Naming:<\/strong> Utilize a domain-specific naming scheme to avoid conflicts with other resources. For example, using a unique API group name for your CRDs.<\/li>\n\n\n\n<li><strong>Version Naming:<\/strong> Stick to conventional version naming practices like <code>v1<\/code>, <code>v2<\/code>, etc., for clarity and consistency.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Security Considerations:<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>RBAC:<\/strong> Implement Role-Based Access Control (RBAC) to define who has access to what in your Kubernetes cluster. This is crucial for protecting your CRD data and operations.<\/li>\n\n\n\n<li><strong>Namespace Isolation:<\/strong> Where possible, use namespaces to isolate your CRDs and custom resources, especially in multi-tenant environments.<\/li>\n\n\n\n<li><strong>Validation:<\/strong> Implement thorough validation in your CRD manifests to prevent erroneous or malicious data entry.<\/li>\n\n\n\n<li><strong>Audit Logging:<\/strong> Enable audit logging to track who did what and when, which is crucial for post-incident analysis and compliance.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Performance Optimization Tips:<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Indexing:<\/strong> Utilize indexing in your controllers to efficiently lookup and list resources, which is especially important as the number of custom resources grows.<\/li>\n\n\n\n<li><strong>Rate Limiting:<\/strong> Implement rate limiting in your controllers to avoid overwhelming the Kubernetes API server, especially in error scenarios.<\/li>\n\n\n\n<li><strong>Resource Efficiency:<\/strong> Be mindful of the resources (CPU, memory) your controllers consume and optimize your code for efficiency.<\/li>\n\n\n\n<li><strong>Parallelization:<\/strong> Where possible, parallelize operations in your controllers to improve performance, but do so with caution to avoid race conditions.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Real-World CRD Implementation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In this section, let&#8217;s explore a real-world use case of CRD implementation by looking at a simplified version of managing database clusters within a Kubernetes environment.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Overview of a Real-World Use Case:<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine a scenario where you are tasked with managing multiple database clusters in a Kubernetes environment. Each database cluster has its unique configuration, including the database version, the number of replicas, storage size, and credentials. A Custom Resource Definition (CRD) can be a perfect solution to model and manage these database clusters.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step-by-step Walkthrough of the CRD Implementation:<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Designing the CRD Schema:<\/strong> Identify the properties required for each database cluster, such as <code>dbVersion<\/code>, <code>replicaCount<\/code>, <code>storageSize<\/code>, <code>username<\/code>, and <code>password<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Creating the CRD Manifest:<\/strong> Define a CRD with a schema that matches the identified properties.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-35\" data-shcb-language-name=\"Go\" data-shcb-language-slug=\"go\"><span><code class=\"hljs language-go\">apiVersion: apiextensions.k8s.io\/v1\r\nkind: CustomResourceDefinition\r\nmetadata:\r\n  name: dbclusters.database.example.com\r\nspec:\r\n  group: database.example.com\r\n  versions:\r\n    - name: v1\r\n      served: <span class=\"hljs-literal\">true<\/span>\r\n      storage: <span class=\"hljs-literal\">true<\/span>\r\n  scope: Namespaced\r\n  names:\r\n    plural: dbclusters\r\n    singular: dbcluster\r\n    kind: DbCluster\r\n  validation:\r\n    openAPIV3Schema:\r\n      properties:\r\n        spec:\r\n          properties:\r\n            dbVersion:\r\n              <span class=\"hljs-keyword\">type<\/span>: <span class=\"hljs-keyword\">string<\/span>\r\n            replicaCount:\r\n              <span class=\"hljs-keyword\">type<\/span>: integer\r\n            storageSize:\r\n              <span class=\"hljs-keyword\">type<\/span>: <span class=\"hljs-keyword\">string<\/span>\r\n            username:\r\n              <span class=\"hljs-keyword\">type<\/span>: <span class=\"hljs-keyword\">string<\/span>\r\n            password:\r\n              <span class=\"hljs-keyword\">type<\/span>: <span class=\"hljs-keyword\">string<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-35\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Go<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">go<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Applying the CRD Manifest:<\/strong> Apply the CRD manifest to the Kubernetes cluster using <code>kubectl apply<\/code>.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-36\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl apply -f dbcluster-crd.yaml<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-36\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Implementing the Custom Controller:<\/strong> Create a custom controller that watches for changes to <code>DbCluster<\/code> resources. Implement reconciliation logic to create, update, or delete database clusters based on the <code>DbCluster<\/code> resource state.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Deploying the Custom Controller:<\/strong> Build and deploy your custom controller to the Kubernetes cluster.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Creating DbCluster Resources:<\/strong> Create <code>DbCluster<\/code> resources for each database cluster you want to manage. The custom controller should react to these resources, managing the database clusters accordingly.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-37\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-attr\">apiVersion:<\/span> <span class=\"hljs-string\">database.example.com\/v1<\/span>\r\n<span class=\"hljs-attr\">kind:<\/span> <span class=\"hljs-string\">DbCluster<\/span>\r\n<span class=\"hljs-attr\">metadata:<\/span>\r\n  <span class=\"hljs-attr\">name:<\/span> <span class=\"hljs-string\">production-db<\/span>\r\n<span class=\"hljs-attr\">spec:<\/span>\r\n  <span class=\"hljs-attr\">dbVersion:<\/span> <span class=\"hljs-string\">\"12.4\"<\/span>\r\n  <span class=\"hljs-attr\">replicaCount:<\/span> <span class=\"hljs-number\">3<\/span>\r\n  <span class=\"hljs-attr\">storageSize:<\/span> <span class=\"hljs-string\">\"10Gi\"<\/span>\r\n  <span class=\"hljs-attr\">username:<\/span> <span class=\"hljs-string\">admin<\/span>\r\n  <span class=\"hljs-attr\">password:<\/span> <span class=\"hljs-string\">secret<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-37\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-38\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">kubectl apply -f production-db.yaml<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-38\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Monitoring and Management:<\/strong> Monitor the state of your database clusters through Kubernetes tools and custom metrics exposed by your controller. Utilize the Kubernetes API to manage the lifecycle of your database clusters through <code>DbCluster<\/code> resources.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Through this real-world example, you can see how CRDs and custom controllers enable a declarative approach to managing complex systems within a Kubernetes environment. This pattern can be extended to manage a wide variety of resources and configurations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The knowledge and practices discussed in this guide equip you with the foundation to explore and implement CRDs in your own projects. Whether you&#8217;re managing database clusters, network configurations, or any other complex systems, CRDs provide a powerful and flexible framework to extend the Kubernetes ecosystem according to your needs.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Kubernetes has taken the tech world by storm, thanks to its robust platform for managing containerized applications in a clustered environment. It&#8217;s a hit among developers and system administrators for its ability to ensure that cloud-native applications run smoothly and reliably. A key player in this orchestration magic is the Custom Resource Definition (CRD), a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[21],"tags":[],"class_list":["post-1662","post","type-post","status-publish","format-standard","category-containers","entry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Kubernetes Custom Resource Definitions (CRDs) Implementation<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Kubernetes Custom Resource Definitions (CRDs) Implementation\" \/>\n<meta property=\"og:description\" content=\"Kubernetes has taken the tech world by storm, thanks to its robust platform for managing containerized applications in a clustered environment. It&#8217;s a hit among developers and system administrators for its ability to ensure that cloud-native applications run smoothly and reliably. A key player in this orchestration magic is the Custom Resource Definition (CRD), a [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-11-02T02:20:26+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-02T02:20:31+00:00\" \/>\n<meta name=\"author\" content=\"w3compadmin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"w3compadmin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/kubernetes-custom-resource-definitions-crds-implementation\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/kubernetes-custom-resource-definitions-crds-implementation\\\/\"},\"author\":{\"name\":\"w3compadmin\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"headline\":\"Kubernetes Custom Resource Definitions (CRDs) Implementation\",\"datePublished\":\"2023-11-02T02:20:26+00:00\",\"dateModified\":\"2023-11-02T02:20:31+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/kubernetes-custom-resource-definitions-crds-implementation\\\/\"},\"wordCount\":2857,\"commentCount\":0,\"articleSection\":[\"Containers\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/kubernetes-custom-resource-definitions-crds-implementation\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/kubernetes-custom-resource-definitions-crds-implementation\\\/\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/kubernetes-custom-resource-definitions-crds-implementation\\\/\",\"name\":\"Kubernetes Custom Resource Definitions (CRDs) Implementation\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\"},\"datePublished\":\"2023-11-02T02:20:26+00:00\",\"dateModified\":\"2023-11-02T02:20:31+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/kubernetes-custom-resource-definitions-crds-implementation\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/kubernetes-custom-resource-definitions-crds-implementation\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/kubernetes-custom-resource-definitions-crds-implementation\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Articles Home\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Containers\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/containers\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Kubernetes Custom Resource Definitions (CRDs) Implementation\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\",\"name\":\"Developer Articles Hub\",\"description\":\"\",\"alternateName\":\"Developer Articles\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\",\"name\":\"w3compadmin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457\",\"contentUrl\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457\",\"caption\":\"w3compadmin\"},\"sameAs\":[\"http:\\\/\\\/w3computing.com\\\/articles\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Kubernetes Custom Resource Definitions (CRDs) Implementation","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/","og_locale":"en_US","og_type":"article","og_title":"Kubernetes Custom Resource Definitions (CRDs) Implementation","og_description":"Kubernetes has taken the tech world by storm, thanks to its robust platform for managing containerized applications in a clustered environment. It&#8217;s a hit among developers and system administrators for its ability to ensure that cloud-native applications run smoothly and reliably. A key player in this orchestration magic is the Custom Resource Definition (CRD), a [&hellip;]","og_url":"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/","article_published_time":"2023-11-02T02:20:26+00:00","article_modified_time":"2023-11-02T02:20:31+00:00","author":"w3compadmin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"w3compadmin","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/#article","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/"},"author":{"name":"w3compadmin","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"headline":"Kubernetes Custom Resource Definitions (CRDs) Implementation","datePublished":"2023-11-02T02:20:26+00:00","dateModified":"2023-11-02T02:20:31+00:00","mainEntityOfPage":{"@id":"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/"},"wordCount":2857,"commentCount":0,"articleSection":["Containers"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/","url":"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/","name":"Kubernetes Custom Resource Definitions (CRDs) Implementation","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/#website"},"datePublished":"2023-11-02T02:20:26+00:00","dateModified":"2023-11-02T02:20:31+00:00","author":{"@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"breadcrumb":{"@id":"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.w3computing.com\/articles\/kubernetes-custom-resource-definitions-crds-implementation\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Articles Home","item":"https:\/\/www.w3computing.com\/articles\/"},{"@type":"ListItem","position":2,"name":"Containers","item":"https:\/\/www.w3computing.com\/articles\/containers\/"},{"@type":"ListItem","position":3,"name":"Kubernetes Custom Resource Definitions (CRDs) Implementation"}]},{"@type":"WebSite","@id":"https:\/\/www.w3computing.com\/articles\/#website","url":"https:\/\/www.w3computing.com\/articles\/","name":"Developer Articles Hub","description":"","alternateName":"Developer Articles","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.w3computing.com\/articles\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561","name":"w3compadmin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457","url":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457","contentUrl":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781957457","caption":"w3compadmin"},"sameAs":["http:\/\/w3computing.com\/articles"]}]}},"featured_image_src":null,"featured_image_src_square":null,"author_info":{"display_name":"w3compadmin","author_link":"https:\/\/www.w3computing.com\/articles\/author\/w3compadmin\/"},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/1662","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/comments?post=1662"}],"version-history":[{"count":4,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/1662\/revisions"}],"predecessor-version":[{"id":1666,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/1662\/revisions\/1666"}],"wp:attachment":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/media?parent=1662"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/categories?post=1662"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/tags?post=1662"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}