The idea here is to use LVM copy-on-write snapshot feature to reduce disk usage needed for the multiple instances.
- Create a 300G sparse file. This file will not be using much disk space initially, despite its apparent size.
truncate -s 300G image.img- Attach a loop device to the file and grab its name
loop=$(losetup --show -f image.img)- Create an LVM Physical Volume on the loop device, and make a Volume Group containing that volume
pvcreate "${loop}"
vgcreate vgloop "${loop}"- Create an LVM Thin Pool on the Volume Group. The need for it can be avoided by using a larger sparse file, but IMO this way fewer calculations are needed.
lvcreate -l100%FREE -T vgloop/tpool- Create a 250G volume for the original database.
lvcreate -V250G -T vgloop/tpool -n orig- Set up an ext4 filesystem on the volume and mount it.
-o discardis supposed to give up freed blocks back to the host filesystem from the image file, but I'm not sure how well it works. For me,fstrim -v mountpoint/did the trick.
mkfs.ext4 /dev/vgloop/orig
mount -o discard /dev/vgloop/orig orig/- Copy the database (or other files) to the "original" volume. If you have it all in a single file, this
ddcommand will do it faster and without flushing kernel caches with large read/write operations. If you copy the file by other means, you may want to do async, too.
dd if=state.db of=orig/state.db bs=1G iflag=direct oflag=direct status=progress- Create as many thin snapshots of the original volume as you need, one for each copy of the program
lvcreate -s --name snap1 vgloop/orig
lvcreate -s --name snap2 vgloop/orig
...- Make the volumes activable, and before that disable "skip activation" on them, so they can be activated and later re-attached later with just
losetup
lvchange -kn vgloop/snap1
lvchange -kn vgloop/snap2
...
lvchange -ay vgloop/snap1
lvchange -ay vgloop/snap2
...
- Mount the copies
mount -o discard /dev/vgloop/snap1 snap1/
mount -o discard /dev/vgloop/snap2 snap2/
...
Now you can start multiple instances using snap1/, snap2/ and so on as data directories.
To remove snapshots:
umount snap1
umount snap2
...
lvremove -y vgloop/snap1
lvremove -y vgloop/snap2
...
To detach the volumes and deactivate VG, and also the loop device:
umount orig
umount snap1
umount snap2
...
vgchange -an vgloop
losetup -d "${loop}"
After that you can remove the image.img file, or re-activate the volumes:
losetup --show -f image.img
vgchange -ay vgloop
mount -o discard /dev/vgloop/orig orig/
mount -o discard /dev/vgloop/snap1 snap1/
mount -o discard /dev/vgloop/snap2 snap2/
...
You can check the actual disk usage of the image file like this:
du -h image.img
Note that it will differ from the apparent size you see in ls -lh output.