Step-by-Step Guide: Creating a Kubernetes Custom Resource Definition (CRD) and Controller
Crafting Kubernetes Magic
Table of contents
- Introduction ⚙️
- Levelling Up PdfDocument with a Custom Controller 🚀
- Step 1: Set Up the Development Environment
- Step 2: Scaffold the Custom Resource and Controller
- Step 3: Update the Custom Resource Spec
- Step 4: Implement the Controller Logic
- Step 5: Create and apply the Custom Resource Definition (CRD) File
- Step 6: Build and Run the Controller
- Step 7: Create a PdfDocument Resource
- Step 8: Verify Controller Behavior
- Step 9: Access the Generated PDF
- Conclusion💡
Introduction ⚙️
Kubernetes is like a toolbox full of tools, but sometimes you need a special tool that isn't there. That's where Custom Resource Definitions (CRDs) come into play. They're like making your tool to get the job done. In this guide, we're going to build our special tool – a PdfDocument
resource. It might sound fancy, but it's just a way to make PDFs using Kubernetes magic.
Crafting PdfDocument - Oops, an Error!
We start by making our
PdfDocument
. Here's how it looks:kind: PdfDocument metadata: name: my-document spec: documentName: "MyDocument.pdf" text: "Hello, this is a sample PDF document."
Exciting, right? But guess what? There's a hiccup – an error message! Turns out we missed something called
apiVersion
. It's like an address for ourPdfDocument
, and we forgot to put it in the envelope.Solving the apiVersion Puzzle
apiVersion
might sound like tech lingo, but it's just telling Kubernetes where to find ourPdfDocument
. Think of it like GPS for your resource. We add it, try again, and boom – success! OurPdfDocument
is now part of the Kubernetes club.
We've tackled our first challenge. A tiny missing piece caused a big fuss. The next part is where the real fun begins. We're going to give life to our
PdfDocument
using a custom controller. It's like teaching our tool some tricks. Get ready for some real Kubernetes magic! 🪄 🍵Note: Remember, without a controller, a custom resource remains dormant and unfulfilled.
Levelling Up PdfDocument
with a Custom Controller 🚀
Step 1: Set Up the Development Environment
Ensure you have the necessary tools installed:
Docker
Minikube or Kind (for a local Kubernetes cluster)
Go programming language
kubectl
CLI toolkubebuilder
CLI tool (for scaffolding)
Step 2: Scaffold the Custom Resource and Controller
Initialize your project and create the PdfDocument API:
mkdir your-controller-repo cd your-controller-repo go mod init k8s.example.com/v1 kubebuilder init --domain example.com --repo your-controller-repo kubebuilder create api --group k8s.example.com --version v1 --kind PdfDocument
Step 3: Update the Custom Resource Spec
In your-controller-repo go to api/v1/pdfdocument_types.go
, add the desired fields to the PdfDocumentSpec
struct (e.g., DocumentName
and Text
).
// PdfDocumentSpec defines the desired state of PdfDocument
type PdfDocumentSpec struct {
DocumentName string `json:"documentName,omitempty"`
Text string `json:"text,omitempty"`
}
Step 4: Implement the Controller Logic
In your-controller-repo go to controllers/pdfdocument_controller.go
, implement the reconciliation logic using Reconcile
method. This logic includes creating a Job to convert the Markdown text to a PDF.
Here's a concise and straightforward breakdown of the process using two init containers:
Reading and Storing Text:
The first init container reads the
text
field from PdfDocument.Encodes and saves it as a markdown (.md) file on a shared volume.
PDF conversion:
The second init container uses a
pandoc
image for conversion.Converts markdown file to a PDF, and stores on the same shared volume.
Finalizing and Copying:
The main container sleeps, allowing PDF creation.
Copy the PDF from the shared volume to your local machine.
This smart orchestration automates text-to-PDF transformation, optimizing your custom PdfDocument
resource in Kubernetes. Refer to the image above.
Step 5: Create and apply the Custom Resource Definition (CRD) File
After you execute the kubebuilder create api
command, the Custom Resource Definition (CRD) for your PdfDocument resource will be automatically generated and placed in the config/crd/bases
directory.
Your CRD definition YAML file pdfdocuments.yaml
looks like this:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: pdfdocuments.k8s.example.com
spec:
group: k8s.example.com
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
# openAPIV3Schema is the schema for validating custom objects.
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
documentName:
type: string
text:
type: string
names:
plural: pdfdocuments
singular: pdfdocument
kind: PdfDocument
shortNames:
- pd
- pdf
- pdfs
Create the CRD by applying config/crd/bases/k8s.example.com_pdfdocuments.yaml
using kubectl
:
kubectl apply -f config/crd/bases/k8s.example.com_pdfdocuments.yaml
Then a new namespaced RESTful API endpoint is created at:
/apis/stable.example.com/v1/namespaces/*/pdfdocuments/...
Step 6: Build and Run the Controller
Before running the controller make sure to create the CRD.
make run
Step 7: Create a PdfDocument Resource
Now we can create a PdfDocument custom resource by applying a YAML file, e.g., pdfdocument-sample.yaml
:
apiVersion: k8s.example.com/v1
kind: PdfDocument
metadata:
name: my-document
spec:
documentName: "MyDocument.pdf"
text: "Hello, this is a sample PDF document."
Apply the custom resource:
kubectl apply -f pdfdocument-sample.yaml
You can then manage your CronTab objects using kubectl
. For example:
kubectl get pdfdocument
When you delete a CustomResourceDefinition, the server will uninstall the RESTful API endpoint and delete all custom objects stored in it.
kubectl delete -f CustomResourceDefinition.yaml
kubectl get pdfdocuments
Error from server (NotFound): Unable to list {"stable.example.com" "v1" "pdfdocuments"}: the server could not
find the requested resource (get pdfdocuments.stable.example.com)
If you later recreate the same CustomResourceDefinition, it will start out empty.
Step 8: Verify Controller Behavior
Check logs and resources to ensure the controller and custom resource are functioning as expected:
kubectl logs -l control-plane=controller-manager -n your-controller-namespace
kubectl get pdfdocuments
kubectl describe pdfdocument my-document
Step 9: Access the Generated PDF
Locate and copy the generated PDF document from the pod to your local machine:
kubectl cp <pod-name>:data/mytext.pdf .
open mytext.pdf
Get the <pod-name> using kubectl. Here /data is the shared volume where the markdown files and generated pdfs are stored.
Conclusion💡
Congratulations, you've successfully created a custom resource definition and controller to manage PdfDocument
resources in Kubernetes!
Reference link: Extend the Kubernetes API with CustomResourceDefinitions
Note: This guide provides a simplified overview and commands. Consider adding error handling, validation, and more advanced features for a production-grade implementation.
See you at the next one. Cheers!😁