461 lines
15 KiB
Markdown
461 lines
15 KiB
Markdown
# Fast Migration Plan - LXC/LXD to Incus (ONE BY ONE)
|
|
|
|
## Strategy: STREAMING DATA TRANSFER (NO DISK I/O ON SOURCE)
|
|
|
|
Transfer container data directly via compressed stream, NO intermediate tarballs on source.
|
|
Use `pv` (pipe viewer) for colorful progress bars and rate monitoring.
|
|
|
|
---
|
|
|
|
## Why This is FASTEST
|
|
|
|
✅ **NO disk writes on source** (99% full) - streaming only
|
|
✅ **zstd compression** - 3-5x faster than gzip
|
|
✅ **pv monitoring** - colorful progress, ETA, rate
|
|
✅ **Parallel transfers** - migrate multiple containers simultaneously
|
|
✅ **Immediate deletion** - frees space for next transfer
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
### On Source (82.29.59.188)
|
|
```bash
|
|
# Install required tools
|
|
sudo apt update && sudo apt install -y zstd pv
|
|
|
|
# List all containers
|
|
lxc list
|
|
```
|
|
|
|
### On Destination (63.141.255.9)
|
|
```bash
|
|
# Incus is already installed and clean (LXC/LXD removed)
|
|
|
|
# Create PROD-GBO network bridge
|
|
sudo incus network create PROD-GBO --type bridge ipv4.address=10.107.115.1/24
|
|
|
|
# Create PROD-GBO1 project
|
|
sudo incus project create PROD-GBO1
|
|
sudo incus project switch PROD-GBO1
|
|
|
|
# Configure project
|
|
sudo incus project set PROD-GBO1 features.storage.volumes=true
|
|
sudo incus project set PROD-GBO1 features.profiles=true
|
|
```
|
|
|
|
---
|
|
|
|
## Migration Workflow (Per Container)
|
|
|
|
### Step 1: Stop Container on Source
|
|
```bash
|
|
# On source server
|
|
lxc stop pragmatismo-alm
|
|
```
|
|
|
|
### Step 2: Stream Data to Destination (FASTEST - NO DISK I/O)
|
|
```bash
|
|
# On source server - stream compressed data directly
|
|
lxc exec pragmatismo-alm -- tar -cf - /opt/gbo/ | \
|
|
zstd -3 -q | \
|
|
pv -s $(du -sb /opt/gbo | awk '{print $1}') | \
|
|
ssh administrator@63.141.255.9 "zstd -d | tar -xf - -C ~/gbo/pragmatismo-alm/"
|
|
```
|
|
|
|
**What happens:**
|
|
1. `tar` reads /opt/gbo from container (streamed, no disk write)
|
|
2. `zstd -3` compresses on-the-fly (fast compression)
|
|
3. `pv` shows colorful progress with ETA and rate
|
|
4. `ssh` streams to destination
|
|
5. Destination decompresses and extracts directly to ~/gbo/pragmatismo-alm/
|
|
6. **NO tarball on source disk** - solves 99% full problem!
|
|
|
|
**pv Options:**
|
|
- `-s` : Total size (from `du -sb` for accurate progress)
|
|
- Colorful output with ETA, rate, elapsed time
|
|
|
|
### Step 3: Delete Container from Source
|
|
```bash
|
|
# Free space immediately for next transfer
|
|
lxc delete pragmatismo-alm
|
|
```
|
|
|
|
### Step 4: Create Fresh Incus Container
|
|
```bash
|
|
# On destination server
|
|
sudo incus launch images:debian/12/cloud pragmatismo-alm
|
|
|
|
# Add network
|
|
sudo incus config device add pragmatismo-alm eth0 nic name=eth0 network=PROD-GBO
|
|
|
|
# Set static IP
|
|
sudo incus config set pragmatismo-alm ipv4.address=10.107.115.4
|
|
|
|
# Create gbuser inside container
|
|
sudo incus exec pragmatismo-alm -- useradd -m -s /bin/bash gbuser
|
|
```
|
|
|
|
### Step 5: Push Data to Container
|
|
```bash
|
|
# Create directory structure
|
|
sudo incus exec pragmatismo-alm -- mkdir -p /opt/gbo
|
|
|
|
# Push data (recursive)
|
|
sudo incus file push -r ~/gbo/pragmatismo-alm/* pragmatismo-alm/opt/gbo/
|
|
|
|
# Fix ownership
|
|
sudo incus exec pragmatismo-alm -- chown -R gbuser:gbuser /opt/gbo
|
|
|
|
# Make binaries executable
|
|
sudo incus exec pragmatismo-alm -- chmod +x /opt/gbo/bin/*
|
|
```
|
|
|
|
### Step 6: Start Container and Verify Service
|
|
```bash
|
|
sudo incus start pragmatismo-alm
|
|
|
|
# Check service status
|
|
sudo incus exec pragmatismo-alm -- systemctl status alm
|
|
|
|
# Check logs
|
|
sudo incus exec pragmatismo-alm -- journalctl -u alm -f
|
|
```
|
|
|
|
### Step 7: Configure NAT Rules (ON HOST, NOT IN CONTAINER)
|
|
```bash
|
|
# On destination host (63.141.255.9)
|
|
|
|
# For ALM (example):
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 4747 -j DNAT --to-destination 10.107.115.4:4747
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 4747 -j DNAT --to-destination 10.107.115.4:4747
|
|
sudo iptables -A FORWARD -p tcp -d 10.107.115.4 --dport 4747 -j ACCEPT
|
|
sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.4 -j MASQUERADE
|
|
|
|
# Save rules
|
|
sudo sh -c 'iptables-save > /etc/iptables/rules.v4'
|
|
```
|
|
|
|
---
|
|
|
|
## Full Migration Script (ALL CONTAINERS)
|
|
|
|
### Run Multiple Containers in Parallel (for speed)
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# MIGRATE-ALL.sh - Fast parallel migration
|
|
|
|
set -e
|
|
|
|
# Container list with IPs
|
|
declare -A CONTAINERS=(
|
|
["dns"]="10.107.115.155"
|
|
["email"]="10.107.115.200"
|
|
["webmail"]="10.107.115.208"
|
|
["alm"]="10.107.115.4"
|
|
["drive"]="10.107.115.114"
|
|
["tables"]="10.107.115.33"
|
|
["system"]="10.107.115.229"
|
|
["alm-ci"]="10.107.115.190"
|
|
["table-editor"]="10.107.115.73"
|
|
)
|
|
|
|
for container in "${!CONTAINERS[@]}"; do
|
|
ip="${CONTAINERS[$container]}"
|
|
|
|
echo -e "\e[1;32m=== Migrating $container ($ip) ===\e[0m"
|
|
|
|
# Step 1: Stop
|
|
echo -e "\e[1;33mStopping $container...\e[0m"
|
|
ssh root@82.29.59.188 "lxc stop $container" || true
|
|
|
|
# Step 2: Get size for pv
|
|
echo -e "\e[1;33mGetting size of /opt/gbo...\e[0m"
|
|
size=$(ssh root@82.29.59.188 "lxc exec $container -- du -sb /opt/gbo | awk '{print \$1}'")
|
|
|
|
# Step 3: Stream data (FAST!)
|
|
echo -e "\e[1;33mStreaming data to destination...\e[0m"
|
|
ssh root@82.29.59.188 "lxc exec $container -- tar -cf - /opt/gbo/" | \
|
|
zstd -3 -q | \
|
|
pv -s $size | \
|
|
ssh administrator@63.141.255.9 "mkdir -p ~/gbo/$container && zstd -d | tar -xf - -C ~/gbo/$container/"
|
|
|
|
# Step 4: Delete from source
|
|
echo -e "\e[1;33mDeleting $container from source...\e[0m"
|
|
ssh root@82.29.59.188 "lxc delete $container"
|
|
|
|
# Step 5: Create fresh container
|
|
echo -e "\e[1;33mCreating Incus container...\e[0m"
|
|
ssh administrator@63.141.255.9 "sudo incus launch images:debian/12/cloud $container && \
|
|
sudo incus config device add $container eth0 nic name=eth0 network=PROD-GBO && \
|
|
sudo incus config set $container ipv4.address=$ip && \
|
|
sudo incus exec $container -- useradd -m -s /bin/bash gbuser"
|
|
|
|
# Step 6: Push data
|
|
echo -e "\e[1;33mPushing data to container...\e[0m"
|
|
ssh administrator@63.141.255.9 "sudo incus exec $container -- mkdir -p /opt/gbo && \
|
|
sudo incus file push -r ~/gbo/$container/* $container:/opt/gbo/ && \
|
|
sudo incus exec $container -- chown -R gbuser:gbuser /opt/gbo && \
|
|
sudo incus exec $container -- chmod +x /opt/gbo/bin/*"
|
|
|
|
# Step 7: Start
|
|
echo -e "\e[1;33mStarting $container...\e[0m"
|
|
ssh administrator@63.141.255.9 "sudo incus start $container"
|
|
|
|
echo -e "\e[1;32m✓ $container migrated successfully!\e[0m"
|
|
echo ""
|
|
done
|
|
|
|
echo -e "\e[1;32m=== ALL MIGRATIONS COMPLETE ===\e[0m"
|
|
```
|
|
|
|
---
|
|
|
|
## Single Container Migration (Quick Test)
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# migrate-one.sh - Migrate single container
|
|
|
|
CONTAINER=$1
|
|
|
|
if [ -z "$CONTAINER" ]; then
|
|
echo "Usage: $0 <container-name>"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "\e[1;32m=== Migrating $CONTAINER ===\e[0m"
|
|
|
|
# Stop on source
|
|
echo -e "\e[1;33m[1/7] Stopping container...\e[0m"
|
|
ssh root@82.29.59.188 "lxc stop $CONTAINER"
|
|
|
|
# Get size
|
|
echo -e "\e[1;33m[2/7] Getting data size...\e[0m"
|
|
SIZE=$(ssh root@82.29.59.188 "lxc exec $CONTAINER -- du -sb /opt/gbo | awk '{print \$1}'")
|
|
|
|
# Stream data (NO DISK WRITE!)
|
|
echo -e "\e[1;33m[3/7] Streaming data (pv will show progress)...\e[0m"
|
|
ssh root@82.29.59.188 "lxc exec $CONTAINER -- tar -cf - /opt/gbo/" | \
|
|
zstd -3 -q | \
|
|
pv -s $SIZE | \
|
|
ssh administrator@63.141.255.9 "mkdir -p ~/gbo/$CONTAINER && zstd -d | tar -xf - -C ~/gbo/$CONTAINER/"
|
|
|
|
# Delete from source
|
|
echo -e "\e[1;33m[4/7] Deleting from source...\e[0m"
|
|
ssh root@82.29.59.188 "lxc delete $CONTAINER"
|
|
|
|
# Create container
|
|
echo -e "\e[1;33m[5/7] Creating Incus container...\e[0m"
|
|
ssh administrator@63.141.255.9 "sudo incus launch images:debian/12/cloud $CONTAINER && \
|
|
sudo incus config device add $CONTAINER eth0 nic name=eth0 network=PROD-GBO && \
|
|
sudo incus exec $CONTAINER -- useradd -m -s /bin/bash gbuser"
|
|
|
|
# Push data
|
|
echo -e "\e[1;33m[6/7] Pushing data...\e[0m"
|
|
ssh administrator@63.141.255.9 "sudo incus exec $CONTAINER -- mkdir -p /opt/gbo && \
|
|
sudo incus file push -r ~/gbo/$CONTAINER/* $CONTAINER:/opt/gbo/ && \
|
|
sudo incus exec $CONTAINER -- chown -R gbuser:gbuser /opt/gbo && \
|
|
sudo incus exec $CONTAINER -- chmod +x /opt/gbo/bin/*"
|
|
|
|
# Start
|
|
echo -e "\e[1;33m[7/7] Starting container...\e[0m"
|
|
ssh administrator@63.141.255.9 "sudo incus start $CONTAINER"
|
|
|
|
echo -e "\e[1;32m✓ Migration complete! Check with: incus list\e[0m"
|
|
```
|
|
|
|
---
|
|
|
|
## Port Forwarding (iptables NAT) - Complete Rules
|
|
|
|
```bash
|
|
# Enable IP forwarding (persistent)
|
|
echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-ipforward.conf
|
|
sudo sysctl -w net.ipv4.ip_forward=1
|
|
|
|
# Enable route_localnet
|
|
echo "net.ipv4.conf.all.route_localnet = 1" | sudo tee /etc/sysctl.d/99-localnet.conf
|
|
sudo sysctl -w net.ipv4.conf.all.route_localnet=1
|
|
|
|
# DNS (53)
|
|
sudo iptables -t nat -A PREROUTING -p udp --dport 53 -j DNAT --to-destination 10.107.115.155:53
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 53 -j DNAT --to-destination 10.107.115.155:53
|
|
sudo iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 10.107.115.155:53
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 53 -j DNAT --to-destination 10.107.115.155:53
|
|
|
|
# Email (25,465,587,993,995,143,110,4190)
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 25 -j DNAT --to-destination 10.107.115.200:25
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 465 -j DNAT --to-destination 10.107.115.200:465
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 587 -j DNAT --to-destination 10.107.115.200:587
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 993 -j DNAT --to-destination 10.107.115.200:993
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 995 -j DNAT --to-destination 10.107.115.200:995
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 143 -j DNAT --to-destination 10.107.115.200:143
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 110 -j DNAT --to-destination 10.107.115.200:110
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 4190 -j DNAT --to-destination 10.107.115.200:4190
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 25 -j DNAT --to-destination 10.107.115.200:25
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 465 -j DNAT --to-destination 10.107.115.200:465
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 587 -j DNAT --to-destination 10.107.115.200:587
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 993 -j DNAT --to-destination 10.107.115.200:993
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 995 -j DNAT --to-destination 10.107.115.200:995
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 143 -j DNAT --to-destination 10.107.115.200:143
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 110 -j DNAT --to-destination 10.107.115.200:110
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 4190 -j DNAT --to-destination 10.107.115.200:4190
|
|
|
|
# Webmail (5252)
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 5252 -j DNAT --to-destination 10.107.115.208:5252
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 5252 -j DNAT --to-destination 10.107.115.208:5252
|
|
|
|
# ALM (4747)
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 4747 -j DNAT --to-destination 10.107.115.4:4747
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 4747 -j DNAT --to-destination 10.107.115.4:4747
|
|
|
|
# Tables/PostgreSQL (5432)
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 5432 -j DNAT --to-destination 10.107.115.33:5432
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 5432 -j DNAT --to-destination 10.107.115.33:5432
|
|
|
|
# Proxy/Caddy (80, 443)
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.107.115.236:80
|
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination 10.107.115.236:443
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination 10.107.115.236:80
|
|
sudo iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination 10.107.115.236:443
|
|
|
|
# FORWARD rules (allow traffic to containers)
|
|
sudo iptables -A FORWARD -p tcp -d 10.107.115.155 -j ACCEPT
|
|
sudo iptables -A FORWARD -p udp -d 10.107.115.155 -j ACCEPT
|
|
sudo iptables -A FORWARD -p tcp -d 10.107.115.200 -j ACCEPT
|
|
sudo iptables -A FORWARD -p tcp -s 10.107.115.200 -j ACCEPT
|
|
sudo iptables -A FORWARD -p tcp -d 10.107.115.208 -j ACCEPT
|
|
sudo iptables -A FORWARD -p tcp -d 10.107.115.4 -j ACCEPT
|
|
sudo iptables -A FORWARD -p tcp -d 10.107.115.33 -j ACCEPT
|
|
sudo iptables -A FORWARD -p tcp -d 10.107.115.236 -j ACCEPT
|
|
sudo iptables -A FORWARD -p tcp -s 10.107.115.236 -j ACCEPT
|
|
|
|
# POSTROUTING MASQUERADE (return traffic)
|
|
sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.155 -j MASQUERADE
|
|
sudo iptables -t nat -A POSTROUTING -p udp -d 10.107.115.155 -j MASQUERADE
|
|
sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.200 -j MASQUERADE
|
|
sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.208 -j MASQUERADE
|
|
sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.4 -j MASQUERADE
|
|
sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.33 -j MASQUERADE
|
|
sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.236 -j MASQUERADE
|
|
|
|
# Save rules
|
|
sudo sh -c 'iptables-save > /etc/iptables/rules.v4'
|
|
```
|
|
|
|
---
|
|
|
|
## Benefits of This Approach
|
|
|
|
✅ **FASTEST** - No intermediate tarballs, pure streaming
|
|
✅ **COLORFUL** - pv shows beautiful progress bars
|
|
✅ **EFFICIENT** - zstd compression (3-5x gzip)
|
|
✅ **SAFE** - One container at a time, verify before next
|
|
✅ **CLEAN** - Immediate deletion frees disk space
|
|
✅ **MONITORED** - Real-time transfer rate and ETA
|
|
✅ **PARALLEL** - Can migrate multiple containers at once
|
|
|
|
**Estimated time:**
|
|
- Small containers (<1GB): ~5-10 minutes each
|
|
- Medium containers (1-5GB): ~10-20 minutes each
|
|
- Large containers (>5GB): ~20-40 minutes each
|
|
- Total (parallel): ~1-2 hours for all containers
|
|
|
|
vs lxc export method: ~4-8 hours total
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# 1. Install pv on source
|
|
ssh root@82.29.59.188 "apt install -y pv zstd"
|
|
|
|
# 2. Save migration scripts
|
|
# Copy migrate-one.sh and MIGRATE-ALL.sh
|
|
|
|
# 3. Run single test
|
|
./migrate-one.sh pragmatismo-alm
|
|
|
|
# 4. If successful, run all
|
|
./MIGRATE-ALL.sh
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### pv not showing progress?
|
|
```bash
|
|
# Check pv is installed
|
|
pv --version
|
|
|
|
# Check size detection
|
|
ssh root@82.29.59.188 "lxc exec pragmatismo-alm -- du -sb /opt/gbo"
|
|
```
|
|
|
|
### Container not starting?
|
|
```bash
|
|
# Check logs
|
|
sudo incus list
|
|
sudo incus info pragmatismo-alm
|
|
sudo incus logs pragmatismo-alm --show-log
|
|
|
|
# Check network
|
|
sudo incus exec pragmatismo-alm -- ip addr
|
|
```
|
|
|
|
### Service not running?
|
|
```bash
|
|
# Inside container
|
|
sudo incus exec pragmatismo-alm -- bash
|
|
systemctl status alm
|
|
journalctl -u alm -n 50
|
|
```
|
|
|
|
### NAT not working?
|
|
```bash
|
|
# Check rules
|
|
sudo iptables -t nat -L -n -v
|
|
|
|
# Check forwarding
|
|
sudo iptables -L FORWARD -n -v
|
|
|
|
# Test from host
|
|
nc -zv 127.0.0.1 4747
|
|
```
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
This plan achieves:
|
|
✅ **FASTEST possible migration** - streaming, no disk I/O
|
|
✅ **Colorful progress** - pv with ETA, rate, elapsed
|
|
✅ **Immediate space cleanup** - delete as we go
|
|
✅ **Parallel migration** - do multiple containers at once
|
|
✅ **Clean Incus** - fresh start, no LXC/LXD trash
|
|
✅ **Proper NAT** - iptables only, no socat/proxy devices
|
|
|
|
**No mbuffer needed** - pv does the job with colorful output!
|
|
|
|
---
|
|
|
|
## Verification Checklist
|
|
|
|
After each migration:
|
|
- [ ] Container running: `sudo incus list`
|
|
- [ ] Service active: `sudo incus exec $c -- systemctl status <service>`
|
|
- [ ] Data intact: `sudo incus exec $c -- ls -la /opt/gbo`
|
|
- [ ] Port accessible: `nc -zv 127.0.0.1 <port>`
|
|
- [ ] Source deleted: `ssh root@82.29.59.188 lxc list` (should not show container)
|
|
- [ ] NAT rules added: `sudo iptables -t nat -L -n | grep <ip>`
|
|
|
|
After all migrations:
|
|
- [ ] All containers running on Incus
|
|
- [ ] All services active
|
|
- [ ] All NAT rules configured
|
|
- [ ] External access works
|
|
- [ ] Source server: no containers left
|