Compare commits
2 Commits
6e0cec4405
...
b67d300db2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b67d300db2 | ||
|
|
e54d8abdb9 |
@ -265,16 +265,29 @@ func (r *BackupConfigurationReconciler) addSidecar(backupConf formolv1alpha1.Bac
|
|||||||
r.Log.Error(err, "unable to create RBAC for the sidecar container")
|
r.Log.Error(err, "unable to create RBAC for the sidecar container")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch target.BackupType {
|
for i, container := range targetPodSpec.Containers {
|
||||||
case formolv1alpha1.OnlineKind:
|
for _, targetContainer := range target.Containers {
|
||||||
sidecarPaths, vms := addOnlineSidecarTags(targetPodSpec, target)
|
if targetContainer.Name == container.Name {
|
||||||
sidecar.Env = append(sidecar.Env, corev1.EnvVar{
|
// Found a target container. Tag it.
|
||||||
Name: formolv1alpha1.BACKUP_PATHS,
|
targetPodSpec.Containers[i].Env = append(container.Env, corev1.EnvVar{
|
||||||
Value: strings.Join(sidecarPaths, string(os.PathListSeparator)),
|
Name: formolv1alpha1.TARGETCONTAINER_TAG,
|
||||||
})
|
Value: container.Name,
|
||||||
sidecar.VolumeMounts = vms
|
})
|
||||||
case formolv1alpha1.JobKind:
|
switch target.BackupType {
|
||||||
sidecar.VolumeMounts = addJobSidecarTags(targetPodSpec, target)
|
case formolv1alpha1.OnlineKind:
|
||||||
|
sidecarPaths, vms := addOnlineSidecarTags(container, targetContainer)
|
||||||
|
sidecar.Env = append(sidecar.Env, corev1.EnvVar{
|
||||||
|
Name: formolv1alpha1.BACKUP_PATHS,
|
||||||
|
Value: strings.Join(sidecarPaths, string(os.PathListSeparator)),
|
||||||
|
})
|
||||||
|
sidecar.VolumeMounts = vms
|
||||||
|
case formolv1alpha1.JobKind:
|
||||||
|
sidecar.VolumeMounts = addJobSidecarTags(targetPodSpec, i, targetContainer)
|
||||||
|
case formolv1alpha1.SnapshotKind:
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if repo.Spec.Backend.Local != nil {
|
if repo.Spec.Backend.Local != nil {
|
||||||
sidecar.VolumeMounts = append(sidecar.VolumeMounts, corev1.VolumeMount{
|
sidecar.VolumeMounts = append(sidecar.VolumeMounts, corev1.VolumeMount{
|
||||||
@ -414,76 +427,54 @@ func (r *BackupConfigurationReconciler) createRBACSidecar(sa corev1.ServiceAccou
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addJobSidecarTags(podSpec *corev1.PodSpec, target formolv1alpha1.Target) (vms []corev1.VolumeMount) {
|
func addJobSidecarTags(podSpec *corev1.PodSpec, index int, targetContainer formolv1alpha1.TargetContainer) (vms []corev1.VolumeMount) {
|
||||||
for i, container := range podSpec.Containers {
|
// Create a shared mount between the target and sidecar container
|
||||||
for _, targetContainer := range target.Containers {
|
// the output of the Job will be saved in the shared volume
|
||||||
if targetContainer.Name == container.Name {
|
// and restic will then backup the content of the volume
|
||||||
// Found a target container. Tag it.
|
var addSharedVol bool = true
|
||||||
podSpec.Containers[i].Env = append(container.Env, corev1.EnvVar{
|
for _, vol := range podSpec.Volumes {
|
||||||
Name: formolv1alpha1.TARGETCONTAINER_TAG,
|
if vol.Name == formolv1alpha1.FORMOL_SHARED_VOLUME {
|
||||||
Value: container.Name,
|
addSharedVol = false
|
||||||
})
|
|
||||||
// Create a shared mount between the target and sidecar container
|
|
||||||
// the output of the Job will be saved in the shared volume
|
|
||||||
// and restic will then backup the content of the volume
|
|
||||||
var addSharedVol bool = true
|
|
||||||
for _, vol := range podSpec.Volumes {
|
|
||||||
if vol.Name == formolv1alpha1.FORMOL_SHARED_VOLUME {
|
|
||||||
addSharedVol = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if addSharedVol {
|
|
||||||
podSpec.Volumes = append(podSpec.Volumes,
|
|
||||||
corev1.Volume{
|
|
||||||
Name: formolv1alpha1.FORMOL_SHARED_VOLUME,
|
|
||||||
VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
podSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, corev1.VolumeMount{
|
|
||||||
Name: formolv1alpha1.FORMOL_SHARED_VOLUME,
|
|
||||||
MountPath: targetContainer.SharePath,
|
|
||||||
})
|
|
||||||
vms = append(vms, corev1.VolumeMount{
|
|
||||||
Name: formolv1alpha1.FORMOL_SHARED_VOLUME,
|
|
||||||
MountPath: targetContainer.SharePath,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if addSharedVol {
|
||||||
|
podSpec.Volumes = append(podSpec.Volumes,
|
||||||
|
corev1.Volume{
|
||||||
|
Name: formolv1alpha1.FORMOL_SHARED_VOLUME,
|
||||||
|
VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
podSpec.Containers[index].VolumeMounts = append(podSpec.Containers[index].VolumeMounts, corev1.VolumeMount{
|
||||||
|
Name: formolv1alpha1.FORMOL_SHARED_VOLUME,
|
||||||
|
MountPath: targetContainer.SharePath,
|
||||||
|
})
|
||||||
|
vms = append(vms, corev1.VolumeMount{
|
||||||
|
Name: formolv1alpha1.FORMOL_SHARED_VOLUME,
|
||||||
|
MountPath: targetContainer.SharePath,
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func addOnlineSidecarTags(podSpec *corev1.PodSpec, target formolv1alpha1.Target) (sidecarPaths []string, vms []corev1.VolumeMount) {
|
func addOnlineSidecarTags(container corev1.Container, targetContainer formolv1alpha1.TargetContainer) (sidecarPaths []string, vms []corev1.VolumeMount) {
|
||||||
for i, container := range podSpec.Containers {
|
// targetContainer.Paths are the paths to backup
|
||||||
for _, targetContainer := range target.Containers {
|
// We have to find what volumes are mounted under those paths
|
||||||
if targetContainer.Name == container.Name {
|
// and mount them under a path that exists in the sidecar container
|
||||||
// Found a target container. Tag it.
|
for i, path := range targetContainer.Paths {
|
||||||
podSpec.Containers[i].Env = append(container.Env, corev1.EnvVar{
|
vm := corev1.VolumeMount{ReadOnly: true}
|
||||||
Name: formolv1alpha1.TARGETCONTAINER_TAG,
|
var longest int = 0
|
||||||
Value: container.Name,
|
var sidecarPath string
|
||||||
})
|
for _, volumeMount := range container.VolumeMounts {
|
||||||
// targetContainer.Paths are the paths to backup
|
// if strings.HasPrefix(path, volumeMount.MountPath) && len(volumeMount.MountPath) > longest {
|
||||||
// We have to find what volumes are mounted under those paths
|
if rel, err := filepath.Rel(volumeMount.MountPath, path); err == nil && len(volumeMount.MountPath) > longest {
|
||||||
// and mount them under a path that exists in the sidecar container
|
longest = len(volumeMount.MountPath)
|
||||||
for i, path := range targetContainer.Paths {
|
vm.Name = volumeMount.Name
|
||||||
vm := corev1.VolumeMount{ReadOnly: true}
|
vm.MountPath = fmt.Sprintf("/%s%d", formolv1alpha1.BACKUP_PREFIX_PATH, i)
|
||||||
var longest int = 0
|
vm.SubPath = volumeMount.SubPath
|
||||||
var sidecarPath string
|
sidecarPath = filepath.Join(vm.MountPath, rel)
|
||||||
for _, volumeMount := range container.VolumeMounts {
|
|
||||||
// if strings.HasPrefix(path, volumeMount.MountPath) && len(volumeMount.MountPath) > longest {
|
|
||||||
if rel, err := filepath.Rel(volumeMount.MountPath, path); err == nil && len(volumeMount.MountPath) > longest {
|
|
||||||
longest = len(volumeMount.MountPath)
|
|
||||||
vm.Name = volumeMount.Name
|
|
||||||
vm.MountPath = fmt.Sprintf("/%s%d", formolv1alpha1.BACKUP_PREFIX_PATH, i)
|
|
||||||
vm.SubPath = volumeMount.SubPath
|
|
||||||
sidecarPath = filepath.Join(vm.MountPath, rel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vms = append(vms, vm)
|
|
||||||
sidecarPaths = append(sidecarPaths, sidecarPath)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
vms = append(vms, vm)
|
||||||
|
sidecarPaths = append(sidecarPaths, sidecarPath)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
134
test/minikube/030-backupconf-snapshot.yaml
Normal file
134
test/minikube/030-backupconf-snapshot.yaml
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
---
|
||||||
|
apiVersion: formol.desmojim.fr/v1alpha1
|
||||||
|
kind: Repo
|
||||||
|
metadata:
|
||||||
|
name: repo-local
|
||||||
|
namespace: demo
|
||||||
|
spec:
|
||||||
|
backend:
|
||||||
|
local:
|
||||||
|
emptyDir:
|
||||||
|
repositorySecrets: secret-minio
|
||||||
|
---
|
||||||
|
apiVersion: formol.desmojim.fr/v1alpha1
|
||||||
|
kind: Repo
|
||||||
|
metadata:
|
||||||
|
name: repo-minio
|
||||||
|
namespace: demo
|
||||||
|
spec:
|
||||||
|
backend:
|
||||||
|
s3:
|
||||||
|
server: minio-svc.minio:9000
|
||||||
|
bucket: backups
|
||||||
|
repositorySecrets: secret-minio
|
||||||
|
---
|
||||||
|
apiVersion: formol.desmojim.fr/v1alpha1
|
||||||
|
kind: Function
|
||||||
|
metadata:
|
||||||
|
name: with-envfrom
|
||||||
|
namespace: demo
|
||||||
|
spec:
|
||||||
|
name: with-envfrom
|
||||||
|
command: ["touch", $(title)]
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: with-envfrom-secret
|
||||||
|
---
|
||||||
|
apiVersion: formol.desmojim.fr/v1alpha1
|
||||||
|
kind: Function
|
||||||
|
metadata:
|
||||||
|
name: with-env
|
||||||
|
namespace: demo
|
||||||
|
spec:
|
||||||
|
name: with-env
|
||||||
|
command: ["touch", $(TESTFILE)]
|
||||||
|
env:
|
||||||
|
- name: TESTFILE
|
||||||
|
value: /data/testfile
|
||||||
|
---
|
||||||
|
apiVersion: formol.desmojim.fr/v1alpha1
|
||||||
|
kind: Function
|
||||||
|
metadata:
|
||||||
|
name: backup-pg
|
||||||
|
namespace: demo
|
||||||
|
spec:
|
||||||
|
name: backup-pg
|
||||||
|
command: ["pg_dumpall"]
|
||||||
|
args: ["--username", $(PGUSER), "--clean", "--if-exists", "--inserts", "--file", "/formol-shared/backup-pg.sql"]
|
||||||
|
env:
|
||||||
|
- name: PGUSER
|
||||||
|
value: demopostgres
|
||||||
|
---
|
||||||
|
apiVersion: formol.desmojim.fr/v1alpha1
|
||||||
|
kind: Function
|
||||||
|
metadata:
|
||||||
|
name: restore-pg
|
||||||
|
namespace: demo
|
||||||
|
spec:
|
||||||
|
name: restore-pg
|
||||||
|
image: desmo999r/formolcli:latest
|
||||||
|
command: ["psql"]
|
||||||
|
args: ["--username", $(PGUSER), "--quiet", "--file", "/formol-shared/backup-pg.sql", "postgres"]
|
||||||
|
env:
|
||||||
|
- name: PGUSER
|
||||||
|
value: demopostgres
|
||||||
|
---
|
||||||
|
apiVersion: formol.desmojim.fr/v1alpha1
|
||||||
|
kind: Function
|
||||||
|
metadata:
|
||||||
|
name: maintenance-off
|
||||||
|
namespace: demo
|
||||||
|
spec:
|
||||||
|
name: maintenance-off
|
||||||
|
command: ["/bin/sh"]
|
||||||
|
args: ["-c", "echo $(date +%Y/%m/%d-%H:%M:%S) maintenance-off >> /data/logs.txt"]
|
||||||
|
---
|
||||||
|
apiVersion: formol.desmojim.fr/v1alpha1
|
||||||
|
kind: Function
|
||||||
|
metadata:
|
||||||
|
name: maintenance-on
|
||||||
|
namespace: demo
|
||||||
|
spec:
|
||||||
|
name: maintenance-on
|
||||||
|
command: ["/bin/sh"]
|
||||||
|
args: ["-c", "echo $(date +%Y/%m/%d-%H:%M:%S) maintenance-on >> /data/logs.txt"]
|
||||||
|
---
|
||||||
|
apiVersion: formol.desmojim.fr/v1alpha1
|
||||||
|
kind: BackupConfiguration
|
||||||
|
metadata:
|
||||||
|
name: backup-demo
|
||||||
|
namespace: demo
|
||||||
|
spec:
|
||||||
|
suspend: true
|
||||||
|
image: desmo999r/formolcli:latest
|
||||||
|
repository: repo-minio
|
||||||
|
schedule: "15 * * * *"
|
||||||
|
keep:
|
||||||
|
last: 2
|
||||||
|
daily: 2
|
||||||
|
weekly: 2
|
||||||
|
monthly: 6
|
||||||
|
yearly: 3
|
||||||
|
targets:
|
||||||
|
- backupType: Snapshot
|
||||||
|
targetKind: Deployment
|
||||||
|
targetName: apache-deployment
|
||||||
|
containers:
|
||||||
|
- name: apache
|
||||||
|
steps:
|
||||||
|
- initialize: maintenance-on
|
||||||
|
- finalize: maintenance-off
|
||||||
|
paths:
|
||||||
|
- /data
|
||||||
|
- backupType: Job
|
||||||
|
targetKind: StatefulSet
|
||||||
|
targetName: postgres-demo
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
job:
|
||||||
|
- backup: backup-pg
|
||||||
|
restore: restore-pg
|
||||||
|
# - kind: Job
|
||||||
|
# name: backup-pg
|
||||||
|
# steps:
|
||||||
|
# - name: backup-pg
|
||||||
Loading…
Reference in New Issue
Block a user