What's the difference between a CRD-based Operator and a Helm chart?
Quick Answer
A Helm chart is a one-time, or repeated on-demand, templating and installation mechanism. You run helm install/helm upgrade, and once the resulting resources are applied, Helm's job is done until you explicitly run another command. An Operator is a continuously running controller that keeps actively reconciling and reacting to the live state of the software it manages, indefinitely, without needing a human to trigger each reconciliation. They solve genuinely different problems and are often used together: Helm to package and install the Operator itself, and the Operator to then provide ongoing, automated lifecycle management of the actual application afterward.
Detailed Answer
Helm — a packaging and installation-time tool
helm install my-postgres bitnami/postgresql --set replicaCount=3
Helm renders templates into concrete Kubernetes manifests and applies them once, at the moment you run install or upgrade. After that, Helm itself has no ongoing, running presence in the cluster reacting to changes. If the underlying PostgreSQL Pod crashes, or a replica falls out of sync, Helm does nothing about it — that's the job of whatever controller is managing the resulting objects, typically just a StatefulSet's own basic reconciliation, with no PostgreSQL-specific operational awareness.
Operator — a continuously running, domain-aware controller
apiVersion: postgresql.example.com/v1
kind: PostgresCluster
metadata:
name: my-postgres
spec:
replicas: 3
Once this custom resource exists, the Operator's controller is continuously watching it, and the real state of the PostgreSQL cluster it manages, indefinitely, not just at the moment of initial creation. If a replica becomes unhealthy, the primary fails, or the spec is edited to request a version upgrade, the Operator reacts and takes appropriate, software-specific action, on an ongoing basis, with no human needing to run any command to trigger each reaction.
The key distinction: point-in-time templating vs. ongoing reconciliation
| Helm | Operator | |
|---|---|---|
| When it acts | Only when you explicitly run install/upgrade/rollback | Continuously, in response to any relevant change or failure |
| What it knows | How to render and apply YAML templates | Deep, software-specific operational logic (failover, upgrades, backups) |
| Ongoing presence in the cluster | None (no running component after install completes) | A running controller Pod (or Deployment), watching indefinitely |
| Handles a replica crashing at 3am | No — relies on whatever it deployed (e.g., a plain StatefulSet) to handle this on its own, generically | Yes — this is exactly the kind of scenario Operators are built to actively manage |
Why they're commonly used together, not as competing choices
A very common real-world pattern: use Helm to install the Operator itself (the Operator's own Deployment, its CRDs, its RBAC rules) as a one-time setup step, and then interact with the application going forward purely through the Operator's custom resources (kubectl apply -f postgres-cluster.yaml), letting the now-running Operator handle all further lifecycle management continuously. This isn't a contradiction. Helm and Operators solve different layers of the same overall problem — installing software vs. operating it long-term — and combining them is the standard, not an unusual choice.
The distinction to articulate clearly: Helm is fundamentally a templating and installation-time tool with no ongoing runtime presence, while an Operator is a continuously running controller with real operational awareness of the software it manages. Conflating "a Helm chart that installs a complex application" with "an Operator that manages that application's ongoing lifecycle" is a common surface-level misunderstanding a precise answer should specifically avoid.