---
title: "Kubernetes"
description: "Running the worker in a cluster today, and the operator that will manage it."
url: "https://saved.sh/docs/kubernetes"
---

There are two separate things under this heading, and only one of them exists.

|                         | Status      | What it is                                                                                                |
| ----------------------- | ----------- | --------------------------------------------------------------------------------------------------------- |
| **The worker in a pod** | Works today | A `Deployment` running the [worker image](/docs/workers/install/container), with its config in a `Secret` |
| **The operator**        | Not shipped | A controller that owns that Deployment for you, driven by a `LocalWorker` resource                        |

If you want backups from a cluster now, the first row is the answer and it is a page of YAML.
See [Install](/docs/kubernetes/install).

<Callout type="warn" title="The operator has not shipped">
  The repository holds the project layout, CI, and one alpha CRD. There is no reconcile logic
  behind it yet, so applying a `LocalWorker` resource does nothing. Everything on this page
  describing the operator is the intended design, not a description of running software.
</Callout>

## What the operator is for [#what-the-operator-is-for]

Running the worker as a Deployment is not hard, but it puts the interesting part in the wrong
place. The credential, the staging volume, the architecture constraint and the
one-process-per-credential rule all become YAML that every team copies and slowly gets wrong.

The operator's job is to own that shape. You declare which worker you want and where its
config lives; it owns the Deployment, the volume and the update strategy, including the parts
that are easy to get wrong and expensive to get wrong:

* **Never two replicas of one credential.** A run's steps hand each other a path to a file on
  local disk, so a rolling update that briefly runs two pods breaks runs.
  [Why](/docs/workers/lifecycle#one-process-per-credential).
* **The config is a Secret, never a ConfigMap.** It holds the worker key and your source
  passwords.
* **Status you can read.** Whether this worker is actually polling, on the resource, rather
  than in a log you have to go and find.

## What it is not, yet [#what-it-is-not-yet]

**Backups are not custom resources.** Not in this version. The operator manages workers, and
backups are still declared through [`sctl apply`](/docs/cli/workers), the API or the
dashboard.

Backup resources are the obvious next step, and they get their **own API group**,
`backup.saved.sh`, rather than being bolted onto `worker.saved.sh`. That is the same split
Kubernetes itself makes between `apps` and `storage`: a worker is a piece of running
infrastructure, a backup is a policy about data, and they have different lifecycles and
different owners.

## Next [#next]

<Cards>
  <Card href="/docs/kubernetes/install" title="Install" description="The Deployment that works today, and the operator install that will replace it." />

  <Card href="/docs/kubernetes/resources" title="Resources" description="The LocalWorker custom resource." />

  <Card href="/docs/kubernetes/examples" title="Examples" description="A Postgres in the cluster, backed up from the manifest that deploys it." />
</Cards>
