a3339a30b5
Addresses PR review + acceptance findings: - Add leader-election RBAC: namespaced Role (coordination leases + events) and RoleBinding to the operator ServiceAccount, so controllers actually start under --leader-elect instead of looping on "leases forbidden". Verified in a kind cluster: lease acquired, both controllers start workers. - Align Go versions: bump Dockerfile.operator to golang:1.26-alpine and CI images to golang:1.26 to match go.mod (go 1.26.5); set GOTOOLCHAIN=local so the image build stays hermetic (no toolchain download). - PVC controller: add an annotation predicate so only PVCs carrying (or transitioning off of) backups.unkin.net/schedule enqueue, eliminating reconcile churn from unannotated PVCs while keeping the teardown path. - Cron validator: accept alphabetic month/day-of-week names (MON, JAN, MON-FRI) that k8up and CNPG's robfig/cron accept, still rejecting unknown names; add unit tests for both mapping paths. - Deploy ordering: extract the Namespace into its own manifest and add a config/kustomization.yaml so `kubectl apply -k config` creates the namespace first; document it in the README. - Note the credential-less push precedent (jellyfin-ha) in docker.yaml.
80 lines
3.3 KiB
Markdown
80 lines
3.3 KiB
Markdown
# autobackup-operator
|
|
|
|
A Kubernetes operator that watches for `backups.unkin.net/*` annotations on
|
|
**PersistentVolumeClaims** and **CloudNativePG Clusters** and provisions the S3
|
|
bucket + backup-schedule resources needed to back them up. No new CRDs — it is
|
|
purely annotation-driven on existing objects.
|
|
|
|
## Annotations
|
|
|
|
| Annotation | Meaning |
|
|
|---|---|
|
|
| `backups.unkin.net/schedule` | `@hourly` / `@daily` / `@weekly` (plus `@monthly`/`@yearly`) or a raw cron expression. Absence means "not managed". |
|
|
| `backups.unkin.net/destination` | A logical destination name resolved via the destinations ConfigMap. |
|
|
| `backups.unkin.net/purge-on-delete` | `"true"` opts into deleting the bucket stack when the schedule annotation is removed (default: retain bucket data). |
|
|
|
|
## What it does
|
|
|
|
For every annotated object the operator, in the object's own namespace and
|
|
owner-referenced to it:
|
|
|
|
1. Provisions a cephrgw (`ceph.unkin.net/v1alpha1`) `ObjectStoreUser`, `Bucket`
|
|
(`versioning: true`, `retainOnDelete: true`) and read-write `BucketAccess`.
|
|
2. Waits for the `BucketAccess` to become `Ready` (requeues until then).
|
|
3. Then wires up the backup schedule:
|
|
- **PVC → k8up** (`k8up.io/v1` `Schedule`): S3 backend from the cephrgw
|
|
credential Secret, an auto-generated restic repo-password Secret, and the
|
|
backup scoped to exactly this PVC via
|
|
`spec.backup.volumes[].persistentVolumeClaim.claimName`. Sane prune
|
|
retention (keepDaily 7, keepWeekly 4).
|
|
- **CNPG Cluster** (`postgresql.cnpg.io/v1`): patches
|
|
`spec.backup.barmanObjectStore` (idempotently; a user-set different
|
|
`destinationPath` is left untouched with a Warning event) and creates a
|
|
`ScheduledBackup` with a 6-field (seconds-first) cron.
|
|
|
|
## Destinations ConfigMap
|
|
|
|
The operator resolves `destination` names against a ConfigMap in its own
|
|
namespace (`autobackup-operator/autobackup-destinations` by default). See
|
|
`config/samples/destinations.yaml`.
|
|
|
|
## Deploy
|
|
|
|
```sh
|
|
kubectl apply -k config
|
|
```
|
|
|
|
The `config/kustomization.yaml` orders the `Namespace` first so the
|
|
ServiceAccount, RBAC and Deployment land in an existing namespace. RBAC covers
|
|
both the controllers' resources (`config/rbac/role.yaml`) and the leader-election
|
|
lease/events the manager needs when run with `--leader-elect`
|
|
(`config/rbac/leader_election_role.yaml`). Then create the destinations
|
|
ConfigMap (see `config/samples/destinations.yaml`).
|
|
|
|
## Schedule mapping
|
|
|
|
- **k8up** accepts cron nicknames natively and 5-field cron expressions; the
|
|
value is validated and passed through.
|
|
- **CNPG** requires a 6-field (seconds-first) cron: nicknames are expanded and a
|
|
5-field cron gains a leading `0` seconds field.
|
|
|
|
Invalid schedules surface as Warning events on the annotated object.
|
|
|
|
## Development
|
|
|
|
```sh
|
|
make build # build the operator binary
|
|
make test # unit + envtest controller tests (fetches envtest binaries)
|
|
make lint # go vet
|
|
make generate # regenerate config/rbac/role.yaml from kubebuilder markers
|
|
```
|
|
|
|
Dependencies are vendored so the container build and CI need no access to the
|
|
private `cephrgw-operator` module.
|
|
|
|
## Release
|
|
|
|
`make patch|minor|major` tags and pushes `vX.Y.Z`. A `v*` tag triggers the
|
|
Woodpecker `docker` pipeline, which builds and pushes
|
|
`artifactapi.k8s.syd1.au.unkin.net/docker-internal/autobackup-operator:<tag>`.
|