Container migration
This guide describes how to migrate containerized workloads and their data between hosts. The migration is driven by the inventory enablement flags and the repository's operational scripts: there is deliberately no migration playbook or script, because migrations are rare and their risky parts (capacity, stateful cutover, hardware dependencies) need case-by-case review.
Before starting
- Check capacity before copying anything: measure the source directories
with
du -sand compare againstdfof the target filesystem, leaving growth headroom. A migration plan can be invalidated entirely by a target share smaller than the data set, and an rsync run that discovers this mid-copy leaves a half-filled target to clean up. - Verify recent restic workload backups exist for the stack being migrated: the backed-up configuration and state directories are the rollback safety net if the cutover goes wrong.
- Identify hardware dependencies (USB devices such as Zigbee adapters or Coral accelerators): these need a physical move and, when the target is a virtual machine, a hypervisor passthrough change before the workload can start on the target host.
Procedure
- Set the
configure_rsync_daemonvariable for the target host totrueto set up an rsync daemon. - Initialize the
rsync_daemon_modulesvariable for the target host to configure rsync modules. - Set the
configure_xxxxxvariable for the target host totrueto prepare the target host. - Set the
start_xxxxxvariable for the target host tofalsebecause we don't want to start any services before copying data. - Run Ansible. With the above configuration, it will prepare the target host without starting any service.
- Set the
start_xxxxxvariable for the source host tofalseto stop the service we're migrating. - Run Ansible. Stopping the source services before copying is mandatory for stateful workloads: their state databases (typically SQLite) must be quiesced, because copying them while the services run risks a corrupted copy.
- Copy the data directories AND the untracked configuration and state
directories (under
/etc/ferrarimarco-home-lab/<service>) from the source host to the target host withscripts/copy-data.sh, running each copy withENABLE_DRY_RUN=truefirst. Files that Ansible renders from templates (for examplecompose.yamlfiles orqBittorrent.conf) need no copying: the next Ansible run re-renders them on the target. - Remove the
start_xxxxxfrom the target host configuration because it defaults to theconfigure_xxxxxvalue, which is set totrue. - Update endpoint definitions in
config/ansible/inventory/group_vars/all/main.yaml(the*_endpoint_fqdnvariables) so monitoring probes and cross-host references point at the target host. - Run Ansible.
- Verify that the containers work in the target environment as expected: service health, application state present (libraries, histories, settings), and clean logs. Re-check any credential or token the copied state carries against the target's services.
- Remove the
start_xxxxxvariable from the source host configuration. - Remove the
configure_xxxxxvariable from the source host configuration. - Run Ansible. This will remove all the copied data from the source host.
- Delete data in the source host if it's not deleted automatically, such as media directories.
- If not needed anymore, disable the rsync daemon by removing the
configure_rsync_daemonandrsync_daemon_modulesvariables in the target host configuration. - Commit the changes in the repository.
Data migration examples
These examples assume that the current working directory is the root of this repository:
-
Copy one directory from one host to another by connecting an rsync daemon running on the target host:
scripts/copy-data.sh "user@source.host" "/source/directory" "rsync://rsync_user@target.host/destination/directory" -
Copy one directory from one host to another using rsync:
scripts/copy-data.sh "user@source.host" "/source/directory" "user@target.host:/destination/directory/"