1
0
Fork 0

restic: Add restic-prune CronJob

This CronJob schedules a periodic run of `restic forget`, which deletes
snapshots according to the specified retention period (14 daily, 4
weekly, 12 monthly).

This task used to run on my workstation, scheduled by a systemd timer
unit.  I've kept the same schedule and retention period as before.  Now,
instead of relying on my PC to be on and awake, the cleanup will occur
more regularly.  There's also the added benefit of getting the logs into
Loki.
pull/59/head
Dustin 2025-04-01 19:36:10 -05:00
parent 5c819ef120
commit cf9eae14b4
7 changed files with 163 additions and 0 deletions

2
restic/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
credentials
password

50
restic/kustomization.yaml Normal file
View File

@ -0,0 +1,50 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: restic
labels:
- pairs:
app.kubernetes.io/instance: restic
includeSelectors: true
- pairs:
app.kubernetes.io/part-of: restic
includeTemplates: true
resources:
- namespace.yaml
- network-policy.yaml
- restic-prune.yaml
- secrets.yaml
- ../dch-root-ca
configMapGenerator:
- name: restic-env
envs:
- restic.env
patches:
- patch: |-
apiVersion: batch/v1
kind: CronJob
metadata:
name: restic-prune
spec:
jobTemplate:
spec:
template:
spec:
containers:
- name: restic-prune
env:
- name: RESTIC_CACERT
value: /run/dch-ca/dch-root-ca.crt
volumeMounts:
- mountPath: /run/dch-ca
name: dch-ca
readOnly: true
volumes:
- name: dch-ca
configMap:
name: dch-root-ca

6
restic/namespace.yaml Normal file
View File

@ -0,0 +1,6 @@
apiVersion: v1
kind: Namespace
metadata:
name: restic
labels:
app.kubernetes.io/name: restic

View File

@ -0,0 +1,24 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restic
labels:
app.kubernetes.io/name: restic
app.kubernetes.io/component: restic
spec:
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
- to:
- ipBlock:
cidr: 172.30.0.15/32
ports:
- port: 443
podSelector: {}

60
restic/restic-prune.yaml Normal file
View File

@ -0,0 +1,60 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: restic-prune
labels:
app.kubernetes.io/name: restic-prune
app.kubernetes.io/component: restic
spec:
schedule: 38 9 * * 5
timeZone: America/Chicago
concurrencyPolicy: Forbid
jobTemplate:
metadata:
labels: &labels
app.kubernetes.io/name: restic-prune
app.kubernetes.io/component: restic
spec:
template:
metadata:
labels: *labels
spec:
restartPolicy: Never
containers:
- name: restic-prune
image: ghcr.io/restic/restic
args:
- forget
- --keep-daily=14
- --keep-weekly=4
- --keep-monthly=12
env:
- name: XDG_CACHE_HOME
value: /var/cache
envFrom:
- configMapRef:
name: restic-env
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- mountPath: /run/secrets/restic
name: secrets
readOnly: true
- mountPath: /var/cache
name: cache
- mountPath: /tmp
name: tmp
securityContext:
runAsUser: 32142
runAsGroup: 32142
fsGroup: 32142
runAsNonRoot: true
volumes:
- name: cache
emptyDir: {}
- name: secrets
secret:
secretName: restic-secrets
- name: tmp
emptyDir:
medium: Memory

4
restic/restic.env Normal file
View File

@ -0,0 +1,4 @@
RESTIC_REPOSITORY=s3:s3.backups.pyrocufflink.blue/restic
RESTIC_PASSWORD_FILE=/run/secrets/restic/password
AWS_SHARED_CREDENTIALS_FILE=/run/secrets/restic/credentials

17
restic/secrets.yaml Normal file
View File

@ -0,0 +1,17 @@
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: restic-secrets
namespace: restic
labels: &labels
app.kubernetes.io/name: restic
app.kubernetes.io/component: restic
spec:
encryptedData:
credentials: AgBegS5P+JvhbhBb7/gZ1h+eyvqbXbj5bL5nN/MUbSjmrc/eR93ipe+kAKsfe1DCOtrEKYxO52RY2RdQHcUtgowD9LChCWPVPNZSDJnOId4nVRh9dSqSdYe+fkbp2wqHZf67AjpsP6/Ga3/3RFgNoVXmSDUmn8+5ZwTCKeC304XaCXnPj3iudpO52Wr6x+GpVfZ+yuVBMKMFHIFnnMt0AmjXCqbz+LPIUP/BKZ0/15DYTj4SO3heoSYy5y8suIiF9RZW6ne5dQ3w28V7hq18TNjATahtz+csLzUCRAKYoJfuZ0+YShqn2B/ZFItS1HbsWpoM23UwrNgx5TjSpNzTsh1wqlOztRcS47vyWu9ztDuXjDm2lSJMqoLAjbumV8QU+95LIVK8OCD9ziFCYCXm+7C2fKHG9Z3eEv83bFFQBVRbUg6zgv78FWb5PKrwg55rAM6C/U3AdvVFKYu8sBN30uaGIf6tCwZiHKuzp7JvVGffe6YFmBMU2oxGiLc4ckZozIGXBS26Uk79XM3ywUx+CWOClkqRLfeIjEP0rzseyh9kfXN2rAfn1o1WH6RJLopeE7IO7vnbM8t2CqVfKiBIsIXtKQ6t7JO/8On68AWTw+iqseK3iW6ZiComdYsP5RR5pZMfKa9iSAD6CaFLflMVFslVy2BQgtxWJ9SsQrB48iq3GFSBS2GG4x8NO0gZxY+AE1dvykRZ4U/YYheoClDvibQqPKFsvq83O7zaNwD2tGYiurxoaqAI6FtRCGjA2YGW+FzfikINNTsU21+GrkeNpHYVEXcL00gVR/RtO4JRM7ndCoTUCwCtrJitYLsGS9ZK7D2EXIqe/UqQCzsoVVEwN+irHXGzaA==
password: AgAXFkg2MdfuYD7XcQanf4rrkdO4dbB0IFJRU2oECcMNzGkQKC2+LfyqZv+TgBa0VnmCh3V+suVq48vG+W3Mr9g9LGzcjb3NVsKY8oxNsidEIU6ZksI/ijU7CF7/E5snpd7DowXCye+uA9QzxolarcVucF0S6CFoj5b5O2YFz7RsozJqsfRfXl+SbGbOzjPsKAmE6jBMHGfDlGA9VdgcGFECudBXZDyaaRQtpPITqRMzDdq/fKffA+r117deXzSXW0MB6RDsWubwSSdQXVtgbeAFn2oKGaEeloreRiNwaZ4nR6a6efkvlhz5prQ7sFFhGVDjdwhkdspXly1jHIFqTIoIul9/hRIZ8gGUfDMWq7YOYnwnPpkcY4+fE6LpfY/+BC2//t2VW5uk2lYRZin62bATIZpLE2hFGym3O4Mk5hz6O/jSMvDzDNJ6zYU3oN9C94qxgoLv2IL9tV1mpLvt8hcil0wWuj7qISIf88jTsneQ3quWz8xj6kOjLO+FJD5TjFU6qIhcXTS3/M3XqQbZRucPlVVeROFB9HJpqa51AOxV5i0yuosvlmOaLpOS8UPd3fzMYNY0bopuBrktndy1sY6VdV8ELHZXHFZxruAuYJnRzoZ4EjR5/Mo9BT7JKZLpRUgnLdPQTe5VwL5E1FgjMr/b3nwSyenb63ulOzLcfcy/fpBgOk5AwgOOqjDKLUMJzLppYZT7K2wAI/81IqdclRxblGTa1smyFt7nrUUc86pSWy+/lEhZ+nFrkSF9GFmf3hQDIK/OmqVoV46uMadQGi+d
template:
metadata:
name: restic-secrets
namespace: restic
labels: *labels