|
1 | | -# ClusterSnap - Cloud-Agnostic Kubernetes Backup Tool |
| 1 | +# ClusterSnap |
| 2 | +**Cloud-Agnostic Kubernetes Backup Tool** |
2 | 3 |
|
3 | | -> ClusterSnap runs as a Kubernetes CronJob, zips PVC data from a shared volume, |
4 | | -> uploads the archive to any cloud storage backend (AWS S3, MinIO, SeaweedFS, or |
5 | | -> Azure Blob Storage), and pushes structured telemetry to Grafana Loki and |
6 | | -> Prometheus - all from a single, provider-agnostic codebase. |
| 4 | +> Clustersnap is a lightweight, cloud-agnostic backup tool that safely secures Kubernetes volumes into remote storage like Azure Blob Storage or AWS S3. |
| 5 | +
|
| 6 | + |
| 7 | +* **Export** Kubernetes data to remote storage. |
| 8 | +* **Import** backed-up data to Kubernetes. |
| 9 | +* **Backups Isolation:** Each Kubernetes namespace is backed up into a dedicated space. |
| 10 | +* **Ensure data Integrity:** Scale-down running workload, backup their volumes and restore the workload. |
| 11 | +* **Cloud-Native & Minimalist:** Light footprint, easy to install, and fully customizable from standard Kubernetes manifests without third-party CRD dependencies. |
| 12 | + |
| 13 | + |
| 14 | +## Requirements |
| 15 | +* Remote storage (Azure Blob Storage, S3 etc...), with credentials |
| 16 | +* Working Kubernetes cluster |
7 | 17 |
|
8 | | -- 🗜️ **Single ZIP archive** per backup run using Python's built-in `zipfile` |
9 | | -- ☁️ **Provider-agnostic** storage layer - swap S3 for Azure with one env var |
10 | | -- 📋 **JSON-structured logs** parsed natively by Grafana Loki |
11 | | -- 🛡️ **ZIP path-traversal protection** during restore |
12 | | -- 🔒 **Dual Azure auth** - shared-key or service-principal |
13 | | -- 📊 **Prometheus metrics** pushed to Pushgateway after every run |
14 | 18 |
|
15 | 19 | ## Installation |
16 | | -### Install from sources |
17 | | -* create venv |
18 | | - ``` |
19 | | - python -m .venv |
20 | | - source .venv/bin/activate |
21 | | - ``` |
22 | | - |
23 | | -* install dependencies |
24 | | - ``` |
25 | | - pip install --upgrade pip |
26 | | - pip install -r requirements.txt |
27 | | - ``` |
28 | | - |
29 | | -* create `.env` file |
30 | | - * AWS/S3 |
| 20 | +* install CLI |
| 21 | + * create venv |
31 | 22 | ``` |
32 | | - tofill |
| 23 | + python -m .venv |
| 24 | + source .venv/bin/activate |
33 | 25 | ``` |
34 | 26 |
|
35 | | - * Azure Blob Storage (shared-key) |
| 27 | + * install dependencies |
36 | 28 | ``` |
37 | | - tofill |
| 29 | + pip install --upgrade pip |
| 30 | + pip install -r requirements.txt |
38 | 31 | ``` |
39 | 32 |
|
40 | | -* run |
41 | | - ``` |
42 | | - python -m src.main |
43 | | - ``` |
44 | | -
|
45 | | -<!-- ## Install locally with Docker |
46 | | -* build |
47 | | - ``` |
48 | | - docker build . --tag clustersnap:local |
49 | | - ``` |
50 | | -
|
51 | | -* run |
52 | | - ``` |
53 | | - docker run clustersnap:local |
54 | | - ``` --> |
55 | | -
|
56 | | -## Install on Kubernetes (pod) |
57 | | -* create secret to pull image |
58 | | - ``` |
59 | | - kubectl create secret docker-registry registry-auth-clustersnap \ |
60 | | - --docker-server=ghcr.io \ |
61 | | - --docker-username=GITHUB_ACCOUNT \ |
62 | | - --docker-password=GITHUB_PAT \ |
63 | | - --docker-email=GITHUB_ACCOUNT |
64 | | - ``` |
65 | | -* create secret for remote storage access |
66 | | - * edit `src/templates/backup.secret.yaml` with your own config |
67 | | - * apply |
| 33 | +* create required Kubernetes objects |
| 34 | + * `pullImage` secret |
| 35 | + ``` |
| 36 | + kubectl create secret docker-registry registry-auth-clustersnap \ |
| 37 | + --docker-server=ghcr.io \ |
| 38 | + --docker-username=GITHUB_ACCOUNT \ |
| 39 | + --docker-password=GITHUB_PAT \ |
| 40 | + --docker-email=GITHUB_ACCOUNT |
| 41 | + ``` |
| 42 | +
|
| 43 | + * `config` Secret |
| 44 | + * edit `src/templates/backup.secret.yaml` with your own config |
| 45 | + * apply |
| 46 | + ``` |
| 47 | + NAMESPACE=YOUR_NAMESPACE envsubst < templates/backup.secret.yaml | kubectl apply -f - |
| 48 | + ``` |
| 49 | +
|
| 50 | + * `backup-map` ConfigMap |
| 51 | + > Note: this ConfigMap is used to orchestrate the backup. \ |
| 52 | + > You can manually edit it to customize the backup behaviors, the command below is just a quick way to create it. |
68 | 53 | ``` |
69 | | - NAMESPACE=tenant-test0 envsubst < templates/backup.secret.yaml | kubectl apply -f - |
| 54 | + python -m src.master -c KUBECTL_CONTEXT -rm |
70 | 55 | ``` |
71 | | -* create pod |
72 | | - ``` |
73 | | - NAMESPACE=tenant-test0 envsubst < tests/resources_test.yaml | kubectl apply -f - |
74 | | - ``` |
75 | 56 |
|
76 | 57 | ## Usage |
77 | | -* local |
| 58 | +> Ensure required secrets & configmap are created |
| 59 | +### Kubernetes |
| 60 | +* create pod (& required resources such as RBAC etc...) |
78 | 61 | ``` |
79 | | -python -m src.main --c CONTEXT -n NAMESPACE |
| 62 | +NAMESPACE=YOUR_NAMESPACE envsubst < tests/resources_test.yaml | kubectl apply -f - |
80 | 63 | ``` |
| 64 | +* wait for it to end... |
81 | 65 |
|
82 | | -* docker/kubernetes |
83 | | -just run the image |
| 66 | +### Local CLI |
| 67 | +* backup cluster-wide |
| 68 | +``` |
| 69 | +python -m src.master -c KUBECTL_CONTEXT |
| 70 | +``` |
| 71 | +
|
| 72 | +* backup given namespace |
| 73 | +``` |
| 74 | +python -m src.master -c KUBECTL_CONTEXT -n NAMESPACE |
| 75 | +``` |
84 | 76 |
|
85 | 77 |
|
86 | 78 | ## Developpers |
87 | 79 | ### Architecture |
88 | | -``` |
89 | | -clustersnap/ |
90 | | -├── src/ |
91 | | -│ ├── main.py # Entrypoint for CLI & Kubernetes main pod |
92 | | -│ ├── worker.py # Entrypoint for Kubernetes job pods |
93 | | -│ └── helpers/ |
94 | | -│ ├── kubernetes.py # Kubernetes class |
95 | | -``` |
| 80 | +* `master.py` => entrypoint of the master pod (orchestrate backup jobs, scaling replicas etc...) |
| 81 | +* `exporter.py` => entrypoint of the exporter pod (do the backup = dump persisted storage & sync it to remote storage) |
| 82 | +* `importer.py` => entrypoint of the importer pod (import backups from remote storage to Kubernetes) |
| 83 | +
|
96 | 84 |
|
97 | 85 | ### Workflow of export |
98 | 86 | ``` |
|
0 commit comments