环境迁移指南
环境迁移指南
本节介绍如何在不同环境中迁移完整的 IoT 栈,包括开发环境、测试环境和生产环境之间的数据迁移。学习完成后,您将能够:
- 理解环境迁移的完整流程
- 使用脚本自动化迁移过程
- 向客户解释环境迁移的可行性和方法
- 处理迁移过程中的常见问题
Migration Scenarios
Section titled “Migration Scenarios”典型迁移场景
Section titled “典型迁移场景”场景 1: 开发 → 测试┌──────────┐ ┌──────────┐│ 笔记本 │ ──→ │ 测试服务器 ││ (开发者) │ │ (QA) │└──────────┘ └──────────┘
场景 2: 演示 → 生产┌──────────┐ ┌──────────┐│ 演示环境 │ ──→ │ 生产服务器 ││ (PoC) │ │ (客户) │└──────────┘ └──────────┘
场景 3: 本地 → 云端┌──────────┐ ┌──────────┐│ 本地服务器 │ ──→ │ 云服务器 ││ (办公室) │ │ (AWS/阿里云)│└──────────┘ └──────────┘
场景 4: 灾难恢复┌──────────┐ ┌──────────┐│ 主服务器 │ ──→ │ 备用服务器 ││ (主节点) │ │ (备节点) │└──────────┘ └──────────┘Migration Methods
Section titled “Migration Methods”Method 1: Scripted Migration
Section titled “Method 1: Scripted Migration”完整的迁移脚本 migrate-iot-stack.sh:
#!/bin/bash
# IoT Stack 环境迁移脚本set -e
# 配置SOURCE_DIR="/opt/iot-stack"BACKUP_FILE="/tmp/iot-migration-$(date +%Y%m%d).tar.gz"
echo "=== IoT Stack Migration Script ==="
# 1. 备份源环境backup_source() { echo "[1/4] Backing up source environment..."
# 备份配置和数据 mkdir -p /tmp/iot-backup
# 备份 docker-compose.yml cp ${SOURCE_DIR}/docker-compose.yml /tmp/iot-backup/
# 备份所有数据卷 docker run --rm \ -v nodered_data:/source \ -v /tmp/iot-backup:/backup \ alpine tar czf /backup/nodered_data.tar.gz -C /source .
docker run --rm \ -v influxdb_data:/source \ -v /tmp/iot-backup:/backup \ alpine tar czf /backup/influxdb_data.tar.gz -C /source .
docker run --rm \ -v grafana_data:/source \ -v /tmp/iot-backup:/backup \ alpine tar czf /backup/grafana_data.tar.gz -C /source .
# 导出容器列表 docker ps --format '{{.Names}}' > /tmp/iot-backup/container-list.txt
echo " ✓ Source backup completed"}
# 2. 打包迁移文件package_migration() { echo "[2/4] Packaging migration archive..."
tar czf ${BACKUP_FILE} -C /tmp iot-backup echo " ✓ Migration package: ${BACKUP_FILE}" echo " ✓ Size: $(du -h ${BACKUP_FILE} | cut -f1)"}
# 3. 恢复目标环境restore_target() { echo "[3/4] Restoring to target environment..."
# 解压迁移包 tar xzf ${BACKUP_FILE} -C /tmp
# 恢复 docker-compose.yml cp /tmp/iot-backup/docker-compose.yml ${SOURCE_DIR}/
# 恢复数据卷 docker run --rm \ -v nodered_data:/target \ -v /tmp/iot-backup:/backup \ alpine tar xzf /backup/nodered_data.tar.gz -C /target
docker run --rm \ -v influxdb_data:/target \ -v /tmp/iot-backup:/backup \ alpine tar xzf /backup/influxdb_data.tar.gz -C /target
docker run --rm \ -v grafana_data:/target \ -v /tmp/iot-backup:/backup \ alpine tar xzf /backup/grafana_data.tar.gz -C /target
echo " ✓ Target restore completed"}
# 4. 验证迁移verify_migration() { echo "[4/4] Verifying migration..."
# 启动服务 cd ${SOURCE_DIR} docker-compose up -d
# 等待服务就绪 sleep 10
# 检查服务状态 local services=("nodered" "mosquitto" "influxdb" "grafana") for service in "${services[@]}"; do if docker ps --format '{{.Names}}' | grep -q "${service}"; then echo " ✓ ${service}: Running" else echo " ✗ ${service}: Not found - may need manual check" fi done
echo " ✓ Migration verification completed"}
# 主流程case "${1:-}" in backup) backup_source package_migration echo "Backup migration package: ${BACKUP_FILE}" ;; restore) if [ -z "${2:-}" ]; then echo "Error: Please provide migration package path" echo "Usage: ./migrate-iot-stack.sh restore <backup-file.tar.gz>" exit 1 fi BACKUP_FILE=$2 restore_target verify_migration ;; *) echo "Usage:" echo " ./migrate-iot-stack.sh backup # 在源环境执行备份" echo " ./migrate-iot-stack.sh restore <file> # 在目标环境执行恢复" echo "" echo "Example:" echo " # 源环境:创建迁移包" echo " ./migrate-iot-stack.sh backup" echo " scp /tmp/iot-migration-20260517.tar.gz user@target-server:/tmp/" echo "" echo " # 目标环境:恢复" echo " ./migrate-iot-stack.sh restore /tmp/iot-migration-20260517.tar.gz" ;;esacMethod 2: Manual Migration
Section titled “Method 2: Manual Migration”当无法使用脚本时的分步手动迁移:
源环境导出:
# 1. 导出 docker-compose.yml 和配置文件tar czf iot-config.tar.gz docker-compose.yml mosquitto/config/
# 2. 导出 Node-RED 数据docker run --rm \ -v nodered_data:/source \ -v $(pwd):/backup \ alpine tar czf /backup/nodered-data.tar.gz -C /source .
# 3. 导出 InfluxDB 数据docker exec influxdb influx backup /tmp/influx-backup --token ${TOKEN}docker cp influxdb:/tmp/influx-backup ./influx-backup
# 4. 导出 Grafana 数据docker cp grafana:/var/lib/grafana/grafana.db ./grafana.db目标环境导入:
# 1. 复制文件到目标服务器scp iot-config.tar.gz user@target-server:/opt/iot/scp nodered-data.tar.gz user@target-server:/tmp/scp -r influx-backup user@target-server:/tmp/scp grafana.db user@target-server:/tmp/
# 2. 恢复配置cd /opt/iottar xzf iot-config.tar.gz
# 3. 创建数据卷docker volume create nodered_datadocker volume create influxdb_datadocker volume create grafana_data
# 4. 恢复数据docker run --rm \ -v nodered_data:/target \ -v /tmp:/backup \ alpine tar xzf /backup/nodered-data.tar.gz -C /target
# 5. 启动服务docker-compose up -dEnvironment Configuration File
Section titled “Environment Configuration File”创建一个中心化的配置文件 iot-environment.yml:
# IoT 环境配置文件environment: name: "production" type: "production" # development, staging, production, demo
# 网络配置 network: name: "iot-network" subnet: "172.20.0.0/16"
# 存储配置 storage: base_path: "/opt/iot-stack" backup_path: "/opt/backups/iot" retention_days: 30
# 服务配置 services: mosquitto: port: 1883 ws_port: 9001 allow_anonymous: false require_authentication: true
nodered: port: 1880 auth_enabled: true timezone: "Asia/Shanghai"
influxdb: port: 8086 org: "iot-demo" bucket: "nodered"
grafana: port: 3000 admin_user: "admin"Migration Checklist
Section titled “Migration Checklist”- 确认源环境所有服务运行正常
- 执行一次完整备份
- 记录所有服务的版本号
- 导出所有配置文件
- 记录网络配置和端口信息
- 确认目标服务器满足系统要求
- 目标服务器已安装 Docker 和 Docker Compose
- 停止源环境的数据写入(可选)
- 打包并传输备份文件
- 确保传输过程中数据完整性(MD5 校验)
# 校验文件完整性md5sum iot-migration-20260517.tar.gz > checksum.md5scp iot-migration-20260517.tar.gz checksum.md5 user@target:/tmp/cd /tmp && md5sum -c checksum.md5- 验证所有服务正常运行
- 验证数据完整性
- 测试 MQTT 消息收发
- 验证 Node-RED Flow 功能
- 确认 Grafana 仪表板显示正常
- 更新 DNS 或连接配置
- 保留源环境 1-2 天以备回滚
问题: 目标环境端口被占用
解决方案:
# 修改 docker-compose.yml 端口映射services: nodered: ports: - "1881:1880" # 改为其他端口问题: Bind Mount 路径权限不足
解决方案:
# 创建目录并设置权限mkdir -p /opt/iot-stack/{nodered,influxdb,grafana}chown -R 1000:1000 /opt/iot-stack/noderedchown -R 472:472 /opt/iot-stack/grafana问题: 不同版本容器不兼容
解决方案:
# 使用相同版本标签services: influxdb: image: influxdb:2.7 # 而不是 latest✅ 推荐做法:
- 使用同一版本标签避免兼容性问题
- 迁移前完整备份
- 迁移后全面验证
- 准备回滚方案
- 记录迁移过程和配置变更
❌ 避免做法:
- 跳过备份直接迁移
- 使用
latest标签 - 忽略权限设置
- 在业务高峰期迁移
- 迁移后立即删除源环境
Summary
Section titled “Summary”- 环境迁移是 IoT 项目交付的常见需求
- 脚本化迁移简化整个过程
- 数据卷的迁移是核心关注点
- 完整的迁移检查清单确保零失误
- 保留回滚方案降低风险