TL;DR: A Kubernetes Operator extends Kubernetes with application-specific operational knowledge, allowing complex, stateful applications(like databases) to be managed declaratively through the native Kubernetes API.

When Kubernetes first emerged, its primary strength was orchestrating stateless applications.

If a web server Pod crashed, Kubernetes could recreate it. If traffic increased, a Deployment could scale to additional replicas. Individual Pods could generally be replaced because the application did not depend on the identity or internal state of a specific Pod.

Modern infrastructure, however, depends heavily on stateful systems like PostgreSQL, MySQL, Kafka, and Prometheus.

While Kubernetes provides primitives for running these workloads, the base Kubernetes API doesn’t inherently understand the internal operational requirements of each individual application.


The Limits of Native Orchestration

A standard Deployment assumes that its Pods are identical and interchangeable. For stateful workloads, Kubernetes provides the StatefulSet, which provides stable network identities, ordered operations, and stable storage associations through PersistentVolumeClaims.

However, a StatefulSet still doesn’t understand application semantics.

For instance, Kubernetes knows a PostgreSQL Pod is running, but it cannot answer critical operational questions:

  • Which database replica holds the most recent committed Write-Ahead Log (WAL)?
  • When can a standby instance safely be promoted to primary?
  • How do you perform failover without creating a split-brain condition?
  • How should application-specific backups, point-in-time restores, or schema migrations be coordinated?

Without automated domain logic, these tasks fall back on human SREs, complex shell scripts, or external management tools.


Enter the Kubernetes Operator

The Operator pattern, introduced by CoreOS in 2016, encodes human operational knowledge directly into software running inside the cluster.

An Operator pairs a Custom Resource Definition (CRD) which extends the Kubernetes API with new object types with a Custom Controller. This controller continuously monitors your custom resources, observes the real-world cluster state, and executes domain-specific code to reconcile differences.

Instead of manually managing low-level primitives like Pods or PersistentVolumeClaims, an Operator lets you define higher-level intent:

apiVersion: [database.example.com/v1](https://database.example.com/v1)
kind: PostgreSQLCluster
metadata:
  name: production-db
spec:
  replicas: 3
  version: "18"

The custom resource represents the desired state of the PostgreSQL cluster. The Kubernetes API stores that state, and the Operator’s controller takes the application-specific actions required to provision, configure, and maintain the cluster.

The relationship can be simplified as:

  • CRD defines a new Kubernetes API resource type.

  • Custom Resource declares the desired state of that resource.

  • Operator / Controller implements the application-specific logic required to reconcile that desired state with the actual state.

This is the important difference between simply running a stateful application on Kubernetes and having Kubernetes understand how to operate that application.

By embedding operational runbooks into a continuous reconciliation loop, an Operator can automate complex Day-2 operations such as failover, backups, recovery, and application-specific upgrades.


Back to Certified Cloud Native Platform Engineering Associate Preparation