Skip to main content
Take a moment to review the path you’ve traveled building the WebApp operator. What started as a simple idea — “I want a single Kubernetes object to describe a small web application” — became a working controller pattern that turns intent into cluster behavior. At a high level, the operator you built contains these recurring elements:
  • A custom API (CRD) that expresses intent.
  • A controller with a reconcile loop that enforces that intent.
  • Child resources (Deployments, Services, ConfigMaps) that implement the desired state.
  • Lifecycle edges (finalizers, ownerReferences) to manage deletion and ownership.
  • Status and events to surface operator state to users.
  • Packaging/deployment for running the controller in a real cluster.
The first win: the API. A CustomResourceDefinition made WebApp a first-class resource. The spec lets users declare a promise (for example, which container image and how many replicas). This single object simplifies the user experience — they no longer need to assemble each Kubernetes detail manually. The controller gives that API a heartbeat. Reconcile loops watch WebApp objects, compare desired state to actual cluster state, and move the cluster toward the specification. That compare-and-fix loop is the center of the operator pattern: the user declares a desired state, and the controller works continuously to align reality with that request.
The image illustrates a cyclical process titled "The Controller's Heartbeat – Reconcile," showing four stages: CR (Contract), Reconcile (Repair), Managed work (Real resources), and Status/events (Signals), connected by a "core loop."
You implemented the child resources that make the web app real. A Deployment runs the application Pods, a Service provides a stable network entry, and a ConfigMap carries configuration. Those YAML manifests are no longer ad-hoc files — they are resources that the controller creates and maintains from the parent WebApp CR.
The image is a diagram showing a "WebApp" as the parent resource connected to three child resources: "Deployment," "Service," and "ConfigMap," each with their respective functions in a computing context.
OwnerReferences connected those children back to the parent CR. With ownerReferences in place, Kubernetes knows the ownership relationship and can garbage-collect or reason about the hierarchy instead of treating every object as unrelated.
The image illustrates a relationship diagram showing a "WebApp" as the parent linked to "Deployment," "Service," and "ConfigMap" via owner references.
Status and events make the operator readable from the outside. status fields report what the controller observed so users don’t need to inspect every child resource. Events are short, human-friendly signals recorded as separate Kubernetes Event objects when meaningful things happen (Events are not a subfield of status). Together, they turn an otherwise silent controller into something a user can understand quickly.
Use status for persistent operator-observed state (conditions, replica counts, URLs). Use Events for transient, human-readable signals like “Deployment created” or “ScalingReplicaSet”. Events are stored separately as Event objects in Kubernetes.
Example status snippet:
Example Events (Events are separate Kubernetes objects; shown here to illustrate typical messages):
Finalizers show how operators handle cleanup that Kubernetes cannot perform automatically. When deletion is requested, a finalizer pauses deletion until the controller can remove external state (DNS entries, cloud resources, or other dependencies). This lifecycle edge is common in production operators and one you have practiced.
Finalizers must be removed after cleanup completes. Leaving finalizers in place can permanently block resource deletion — ensure your controller handles cleanup and then removes the finalizer.
The image is a flowchart illustrating a "Finalizers – Clean Up Before Deletion" process with three stages: "Delete requested," "Deletion paused," and "Remove external state."
Validation prevents invalid states from entering the cluster in the first place. Use CRD schema validation and admission controls to reject malformed requests early — it’s much easier to prevent bad input than to reconcile it later.
You also pushed the operator beyond local development: you packaged and deployed the manager, compared different toolchains, and explored real, production operators like cert-manager and the Prometheus Operator. Seeing how other operators are structured expands your mental model — the same operator pattern can appear in a custom controller, a Helm-based operator, or a mature upstream operator.
The image lists six components to consider when understanding the shape of an operator: a custom API, the reconcile loop, child resources, lifecycle edges, status signals, and the packaging path.
Quick reference — core operator components and examples: There is a professional layer beyond this lesson, but it should read like “next steps” — not a judgement. Teams harden operators by adding more tests, tightening RBAC and permissions, monitoring metrics and logs, planning upgrades, and authoring runbooks and support notes. These practices make an operator trustworthy in shared environments.
The image outlines a professional layer concept titled "Next, Not a Verdict," featuring elements such as "More tests," "Tighter permissions," "Metrics and logs," "Support notes," and "Upgrade plans," centered around a "Foundation" built on these aspects. It is copyrighted by KodeKloud.
The best next steps are small and concrete. Pick one of these incremental improvements and ship it:
The image displays a sequence of four icons with labels: "New child resource," "Status condition," "End-to-end test," and "An ingress, or better manifests," with the caption "The Best Next Step Is Small."
Suggested small improvements:
  • Add a new child resource (e.g., a HorizontalPodAutoscaler or Ingress).
  • Add a status condition to represent a useful operator state.
  • Add one end-to-end test that verifies reconcile behavior.
  • Improve example manifests so another person can try the operator quickly.
You can now explain the operator promise in plain terms: a user declares desired state in Kubernetes, and a controller keeps the real cluster aligned with that promise. You built that path with the WebApp operator — and that foundation will help you read, extend, and trust other operators in the future. Links and references

Watch Video