Skip to content

Commit ff89238

Browse files
committed
improve backup procedure for large shared data volumes
1 parent c43b4d3 commit ff89238

2 files changed

Lines changed: 24 additions & 29 deletions

File tree

apps/storage/templates/hasadna-k8s-pvc-backup-all-daily-cron-workflow.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ metadata:
44
name: hasadna-k8s-pvc-backup-all-daily
55
spec:
66
schedule: "47 1 * * *"
7+
suspend: true # temporary, until I fix the backup of large data to be more efficient, should be done tomorrow
78
concurrencyPolicy: Forbid
89
workflowSpec:
910
workflowTemplateRef:

hasadna_k8s/ceph/pvc_backup.py

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
import datetime
55
import subprocess
6+
from glob import iglob
67

78

89
CEPH_BACKUPS_HEARTBEAT_URL = os.getenv('CEPH_BACKUPS_HEARTBEAT_URL')
@@ -43,39 +44,32 @@ def main_shared(namespace, pvc_name, pv):
4344
pool = pv['spec']['csi']['volumeAttributes']['pool']
4445
fs_name = pv['spec']['csi']['volumeAttributes']['fsName']
4546
sub_volume_name = pv['spec']['csi']['volumeAttributes']['subvolumeName']
47+
sub_volume_path = pv['spec']['csi']['volumeAttributes']['subvolumePath']
48+
group_name = 'csi'
49+
print(f'Pool: {pool}, Filesystem name: {fs_name}, Subvolume name: {sub_volume_name}, Group name: {group_name}')
50+
print(f'Subvolume path: {sub_volume_path}')
4651
backup_datestr = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
4752
backup_name = f'hasadna-k8s-pvc-backup-{backup_datestr}'
48-
clone_name = f'hasadna-k8s-pvc-backup-{sub_volume_name}-{backup_datestr}'
49-
print(f'Pool: {pool}, Filesystem name: {fs_name}, Subvolume name: {sub_volume_name}')
5053
print(f'Backup name: {backup_name}')
51-
print(f'Clone name: {clone_name}')
5254
subprocess.check_call(['ceph', 'fs', 'subvolume', 'snapshot', 'create', fs_name, sub_volume_name, backup_name, 'csi'])
53-
subprocess.check_call(['ceph', 'fs', 'subvolume', 'snapshot', 'clone', fs_name, sub_volume_name, backup_name, clone_name, pool, 'csi'])
54-
i = 0
55-
while True:
56-
time.sleep(60)
57-
i += 1
58-
status, output = subprocess.getstatusoutput(f'ceph fs clone status {fs_name} {clone_name}')
59-
if status == 0:
60-
if json.loads(output).get('status', {}).get('state', '') == 'complete':
61-
print(output)
62-
break
63-
else:
64-
print(f'Error checking clone status (exit code {status}): {output}')
65-
assert i < 120, f'Clone {clone_name} did not complete within 2 hours.'
66-
backup_path = subprocess.check_output(['ceph', 'fs', 'subvolume', 'getpath', fs_name, clone_name]).decode().strip()
67-
print(f'Backup path: {backup_path}')
68-
subprocess.check_call(['mkdir', '-p', f'/tmp{backup_path}'])
69-
subprocess.check_call(['ceph-fuse', f'/tmp{backup_path}', '--client-mountpoint', backup_path])
70-
kopia_snapshot_source = f'ceph@{namespace}:{pvc_name}'
71-
print(f'Creating Kopia snapshot with source {kopia_snapshot_source}...')
72-
subprocess.check_call(['kopia', 'snapshot', 'create', f'/tmp{backup_path}', '--override-source', kopia_snapshot_source])
73-
print("Kopia snapshot created successfully.")
74-
print('Unmounting and cleaning up...')
75-
subprocess.check_call(['umount', f'/tmp{backup_path}'])
76-
subprocess.check_call(['ceph', 'fs', 'subvolume', 'rm', fs_name, clone_name])
77-
subprocess.check_call(['ceph', 'fs', 'subvolume', 'snapshot', 'rm', fs_name, sub_volume_name, backup_name, 'csi'])
78-
print('Backup completed successfully.')
55+
try:
56+
os.mkdir('/mnt/ceph')
57+
subprocess.check_call(['ceph-fuse', '/mnt/ceph'])
58+
try:
59+
paths = [path for path in iglob(os.path.join('/mnt/ceph', sub_volume_path, '.snap/*')) if backup_name in os.path.basename(path)]
60+
assert len(paths) == 1, f"Expected exactly one snapshot path for {backup_name}, found {len(paths)}"
61+
path = paths[0]
62+
print(f'snapshot path: {path}')
63+
kopia_snapshot_source = f'ceph@{namespace}:{pvc_name}'
64+
print(f'Creating Kopia snapshot with source {kopia_snapshot_source}...')
65+
subprocess.check_call(['kopia', 'snapshot', 'create', path, '--override-source', kopia_snapshot_source])
66+
print("Kopia snapshot created successfully.")
67+
finally:
68+
if subprocess.call(['umount', '/mnt/ceph']) != 0:
69+
print(f"ERROR! Failed to unmount /mnt/ceph after creating snapshot {backup_name} for namespace '{namespace}', pvc '{pvc_name}'")
70+
finally:
71+
if subprocess.call(['ceph', 'fs', 'subvolume', 'snapshot', 'rm', fs_name, sub_volume_name, backup_name, 'csi']) != 0:
72+
print(f"ERROR! Failed to remove snapshot {backup_name} for namespace '{namespace}', pvc '{pvc_name}'")
7973

8074

8175
def main_pvc(namespace, pvc_name, pvc):

0 commit comments

Comments
 (0)