VPS 服务商锁定:服务器迁移到底有多容易?
用镜像导入导出、快照、IPv6、DNS 控制权和计费条款审计当前 VPS,提前发现迁移障碍,把更换服务商压缩到一个晚上完成。
VPS 服务商之间的可替换性有多高?
VPS 厂商锁定确实存在,但它通常隐藏在大多数人不会检查的地方。两家运行 KVM(基于内核的虚拟机)的服务商,可以提供相同的 Ubuntu 和底层 systemd,因此操作系统并不是限制你迁移的因素。真正限制你的是服务器周边的这一层:无法导出的镜像、无法带走的 IP 地址、同时管理你的 DNS(域名系统)记录的控制面板,以及不予退款的预付余额。
服务商决定由谁管理服务器,但不决定你是否能够离开。两者之间的差距,可以用所需的工作小时数衡量;在真正需要迁移之前很久,你就可以缩短这个差距。
下面是一份审计清单。选择合适的时间,对你当前使用的服务商执行检查。每一步都对应一个问题,并附有相应的命令或控制面板检查方法,同时说明较差的结果之后会带来什么代价。
VPS 锁定实际上是什么样
锁定并不只是一条合同条款,而是迁移的总成本:重建那些没人记录的配置所需的时间,将数据复制出去所需的带宽,DNS 解析器仍将访问者发送到旧地址期间产生的停机时间,以及已经支付但不会使用的剩余月份费用。
按这种方式衡量,VPS 是可租用服务中锁定程度最低的类型之一。您拥有通用内核上的 root 权限。托管数据库或无服务器平台会将您绑定到一个无法在一晚内重新实现的 API,而 VPS 在操作系统层面几乎不会绑定您。这也是为什么值得明确列出剩余的少数绑定因素。提前修复每一项的成本都很低,而在服务中断期间才发现它们,代价会很高。
审计 1:您使用的是哪种虚拟化?
systemd-detect-virt
lscpu | grep -i "hypervisor vendor"
uname -m
ls /sys/firmware/efi >/dev/null 2>&1 && echo UEFI || echo BIOSsystemd-detect-virt 会输出一个单词。kvm 或 xen 表示完整虚拟化:您启动自己的内核,磁盘则是主机作为块设备处理的镜像文件。lxc 表示与主机共享内核的容器,因此您无法加载自己的内核模块,也不能使用嵌套虚拟化。两种尝试都会因 Operation not supported 失败。这是规划问题,而不是命令问题。KVM、Xen 和 LXC 在 VPS 上有何不同介绍了每种模型能够和不能够完成的工作。
最后两行在主机之间迁移磁盘时很重要。为 BIOS 启动安装的镜像会将引导加载程序保存在磁盘的引导扇区中,而仅支持 UEFI 的主机会查找包含 .efi 加载程序的 EFI 系统分区。找不到该分区后,主机会在控制台显示 No bootable device 并停止。架构是更难跨越的限制。arm64 根文件系统根本无法在 x86_64 主机上启动,因为其中每个二进制文件都使用了错误的机器代码。如果您正在考虑迁移,ARM 和 x86 VPS 方案实际有哪些不同介绍了除价格之外的差异。
审计 2:可以导入镜像,也可以导出镜像吗?
不同提供商处于这条链路的不同位置。请在控制面板中找到您的提供商,并记录下来。
- 仅提供固定的提供商镜像菜单,不能使用其他镜像。
- 可以挂载或上传 ISO,因此您需要自行从控制台安装。
- 可以从上传文件或您托管的 URL 导入磁盘镜像。
- 可以导出磁盘镜像。四种方式中,只有这一种决定您能否带着磁盘离开。
前 3 种方式说明您如何接入。只有第 4 种说明您如何离开,而大多数控制面板都不提供这一功能。导入可以吸引客户,导出则允许客户离开,因此这种不对称很常见。如果控制面板没有说明,请直接咨询支持团队,并记录答复以及咨询日期。
如果支持导出,请将结果转换为下一台主机接受的格式:
qemu-img info disk.qcow2
qemu-img convert -p -O raw disk.qcow2 disk.rawRaw 是兼容性最广的输入格式,但最不便于传输,因为文件大小等于整个磁盘的大小。一个已使用 6 GB 的 80 GB 卷,导出后仍是 80 GB 的 raw 文件。反向转换为 qcow2 后,文件大小会缩小到大约已使用空间,因为 qemu-img 不会写入零块。即便如此,也应将整盘传输视为较慢的方案。从配置重新构建通常比通过互联网复制 80 GB 更快,而且下次还可以再次重建服务器。
审计 3:快照能否离开云服务商?
打开快照页面,查看快照旁边的操作项。如果唯一的操作是 Restore,那么该快照只是回滚功能。它存储在云服务商的存储中,会随您的账户一同删除,您自己的任何工具都无法读取它。快照与备份的区别将详细说明这一差异。
另一个限制与供应商锁定无关。正在运行的服务器快照只能保证崩溃一致性,不能保证应用一致性:磁盘是在写入过程中捕获的,因此 PostgreSQL 或 MySQL 恢复时会重放其日志,最后的事务可能已经丢失。请使用数据库自身的工具导出数据库,然后让文件级备份收集这些导出文件。
可移植备份是由您自己持有的备份。restic 会将加密且去重的仓库写入您选择的存储位置:
sudo apt update && sudo apt install -y restic
sudo install -d -m 700 /etc/restic
sudo sh -c 'openssl rand -base64 32 > /etc/restic/password'
sudo chmod 600 /etc/restic/password
export RESTIC_REPOSITORY=sftp:backup@backup.example.com:/srv/restic
export RESTIC_PASSWORD_FILE=/etc/restic/password
sudo -E restic init
sudo -E restic backup /etc /srv /home
sudo -E restic snapshots请将该密码短语的副本保存在服务器以外的位置,因为丢失仓库密码后将无法读取仓库,提交支持工单也无法恢复密码。然后验证备份,因为从未恢复过的备份只能算作猜测:
sudo -E restic restore latest --target /tmp/restore-check
sudo -E restic checkrestic snapshots 应列出您刚刚执行的运行,/tmp/restore-check 应包含可打开的真实文件。每月执行一次恢复,并亲自查看其中一个文件。
审核 4:无法随服务器迁移的地址
IP 地址无法在服务商之间迁移。这是清单中唯一真正的供应商锁定问题,解决方法不是对抗它。为每个地址配置一个名称,并将该名称托管在不提供服务器的公司那里。
ip -6 addr show scope global
ip -6 route show default
ping -6 -c 3 example.com
dig -x 203.0.113.10 +short两个 IPv6 问题决定迁移需要多少返工。首先,您获得的是单个地址,还是可路由的 /64?单个地址足够 Web 服务器使用,但不足以为每个容器分配独立地址。其次,该地址是否确实可路由?如果地址出现在 ip -6 addr 中,而 ip -6 route show default 输出为空,说明镜像配置了地址但没有配置网关。因此,本地网段之外没有响应,ping -6 会超时,而 IPv4 仍正常工作。
dig -x 用于查询 PTR 记录,即反向 DNS:地址映射回的名称。输出为空表示不存在 PTR 记录。对于邮件服务器,这是一个硬性阻断因素,因为许多接收方会拒收或延迟来自反向名称与发送主机不匹配的地址的邮件。请确认控制面板是否允许您自行设置 PTR,还是必须提交支持工单,因为这一字段就可能决定迁移耗时是 2 小时还是 2 天。自托管邮件是否仍值得投入介绍了该清单中的其他内容。
以 IP 地址授权的软件同样不易迁移,原因相同。cPanel 许可证签发给服务器的主 IP,因此迁移时除了复制数据,还需要转移许可证;在承诺使用某个控制面板之前,可以先了解 值得了解的控制面板替代方案,以便更容易进行权衡。
审计 5:控制面板有多少功能可通过 API 完成?
检查控制面板中的每项操作,并确认 API 是否也支持这些操作:创建、重建、调整大小、创建快照、防火墙规则、反向 DNS、DNS 记录,以及添加第二个登录方式。只能在控制面板中完成的操作,都需要在恢复计划中安排人员点击按钮,而且往往是在最不适合手动操作的时间执行。
账户本身也是一个值得在纸面上测试的单点故障。如果付款失败,或登录行为看起来可疑,导致账户被暂停,服务器可能仍在运行,但您将无法管理它。请将凭据和一份近期备份保存到不依赖该登录方式的位置,并启用双因素身份验证,降低因您自己的操作导致账户被暂停的可能性。
DNS 托管需要单独考虑。如果 DNS 区域与服务器位于同一个控制面板中,那么离开该提供商时,就必须在迁移服务器的同一周迁移 DNS,相当于同时进行两项高风险变更。请将 DNS 区域托管在注册商或专用 DNS 提供商处,并将记录保存在 git 中的文本文件里。这样迁移提供商时,只需修改几条 A 和 AAAA 记录,并可在几秒内恢复这些修改。
审查 6:期限、余额和续期日期
合同细节决定了技术上易于迁移的服务器是否会变得难以退出且成本高昂。查看您自己的账单,并记下以下四项:最短期限、取消时的通知期、未使用的预付余额是否可退款,以及出站传输额度。
最后一项常让人意外。复制 300 GB 数据到外部需要产生 300 GB 的出站流量;按量计费的方案会在您已经同时支付两家服务商费用的当月产生迁移成本。应在规划迁移前检查该额度,而不是等到 rsync 运行期间再检查。VPS 每月实际成本和 如何阅读廉价 VPS 方案都介绍了方案中那些要到后期才会显现的部分。
如果您向日本的服务商购买并使用日元付款,前两项尤其需要关注。按月计算的最短期限很常见,预付余额很常见,多年来持续使用同一家服务商也很常见。这意味着自账户开通后,通常没人重新阅读过条款。控制台的操作方式也各不相同:同一项操作在不同服务商处位于不同菜单中,因此执行迁移的人需要在迁移进行期间学习新的控制面板。所有这些内容,最好在续期前找一个空闲的一周仔细确认。应假设账户关闭后快照和备份都会被删除,并在最后一天之前下载所有需要保留的内容。
可移植性方案:两个文件和一个备份
审计会告诉您当前的状态。下面的做法能让这些答案不再重要。
在 cloud-init 文件中保存配置。 cloud-init 是在首次启动时配置云实例的工具。几乎所有云服务商提供的镜像都包含它,几乎所有控制面板也都有可粘贴用户数据的字段。
#cloud-config
hostname: web01
users:
- name: deploy
groups: [sudo]
shell: /bin/bash
sudo: "ALL=(ALL) NOPASSWD:ALL"
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA deploy@workstation
package_update: true
packages:
- docker.io
- docker-compose-v2
- restic
runcmd:
- [systemctl, enable, --now, docker]将文件提交到控制面板前先验证,然后在运行中的服务器上检查结果:
cloud-init schema --config-file user-data.yaml
cloud-init status --long
sudo cloud-init schema --systemcloud-init status --long 应输出 status: done。如果输出 error,请从末尾读取 /var/log/cloud-init.log。最常见的失败原因是第一行缺少 #cloud-config。没有它,cloud-init 无法将文本识别为配置,会静默跳过整个文件。这就是 用户消失且登录失败,而控制面板中没有任何错误提示的原因。为新 VPS 编写 cloud-init 用户数据介绍了值得设置的字段。
这里有一个容易忽略的问题。用户数据按实例 ID 运行,每个实例只运行一次。恢复快照后,实例 ID 不变,因此文件中的内容不会再次运行。该文件用于构建新服务器,不能修复旧服务器。
在 Compose 文件中定义服务。 将 docker-compose.yml 与每个固定到版本标签的镜像一同保存到 git,并确认该文件描述的内容与实际运行的服务一致:
docker compose config
docker volume lsdocker compose config 会输出解析变量后的合并文件。如果输出与正在运行的服务栈不一致,说明有人在这台服务器上手动执行了某些操作,而这些内容正是迁移到下一台服务器时会缺失的部分。为每个服务设置 restart: unless-stopped,这样服务栈才能在新主机重启后恢复运行;让 Compose 服务栈在启动时运行介绍了 systemd 相关配置。
命名卷是人们经常忘记的部分,因为它们位于项目目录之外:
docker run --rm -v app_data:/data -v "$PWD:/backup" alpine tar czf /backup/app_data.tar.gz -C /data .在新服务器上使用 tar xzf 可以恢复同一个镜像,并将其恢复到先使用 docker volume create app_data 创建的卷中。
将数据备份到外部存储。 这就是审计 3 中的 restic 存储库,写入既不属于旧服务商也不属于新服务商的存储。
进行一次演练。 使用这两个文件和最后一个备份,在您能租用的最低成本实例上完整构建一次,并记录所需时间。这个时间就是实际的供应商锁定成本,以小时计。迁移本身是另一项工作:将正在运行的服务器迁移到新的 VPS介绍了复制和切换过程。
在需要切换前降低 DNS TTL
每条 DNS 记录都有 TTL(生存时间),表示解析器可以将其缓存多少秒。TTL 为 86400 的记录会缓存 1 天,因此您更改地址后,部分访问者仍会在 1 天内访问旧服务器。降低 TTL 也不会立即生效,因为缓存会在旧的较长 TTL 到期前继续使用该值。
先降低 TTL,然后等待完整的旧 TTL 时长,再执行切换:
dig +noall +answer example.com A
dig +noall +answer @ns1.example.com example.com A第一次查询会发送到您的解析器,输出中的 TTL 会随着缓存副本老化而倒计时。第二次查询会发送到权威名称服务器,它始终会返回您配置的值。迁移期间将 TTL 设置为 300,1 周后再将其调高。
切换后,至少让旧服务器继续运行 1 个旧 TTL 时长,因为流量仍会到达那里。如果应用接受写入,请在这段时间内将旧副本设为只读。两个在线副本同时接受写入会产生数据分叉,任何还原操作都无法修复这种情况。
克隆后会出现什么问题:身份与时钟
克隆或恢复的服务器会保留原服务器的身份,系统启动时也不会发出任何警告。
首先处理 /etc/machine-id。systemd 会根据它派生其他标识符,其中包括 systemd-networkd 使用的 DHCP 客户端标识。因此,两个克隆实例可能请求同一个租约,并轮流占用同一个地址。让克隆实例投入使用前,先重置它:
sudo rm -f /etc/machine-id /var/lib/dbus/machine-id
sudo systemd-machine-id-setup
sudo ln -s /etc/machine-id /var/lib/dbus/machine-id
sudo rebootVPS 克隆后的完整 machine-id 重置介绍了其他包含身份信息的文件,其中包括监控代理会保留的文件。
其次处理 SSH 主机密钥。克隆实例会使用与原服务器相同的主机密钥响应,因此客户端无法区分这两台服务器。任何连接旧名称但实际到达新地址的客户端都会看到 REMOTE HOST IDENTIFICATION HAS CHANGED。
sudo rm -f /etc/ssh/ssh_host_*
sudo ssh-keygen -A
sudo systemctl restart ssh当前会话会在重启后保持连接。打开第二个会话,确认可以登录后,再关闭第一个会话。在您自己的计算机上,使用 ssh-keygen -R 203.0.113.10 清除过期条目。
第三处理时钟。恢复的快照启动时,时钟会设置为创建快照的时间,可能落后数周。运行 timedatectl 并读取两行输出。System clock synchronized: no 与 NTP service: active 同时出现,表示同步已经开始但尚未完成。时钟落后这么久时,新签发的 TLS(传输层安全)证书会因 certificate is not yet valid 而被拒绝,因为从服务器的角度看,证书的生效日期仍在未来。基于时间的一次性密码登录也会因同样原因失败。
sudo timedatectl set-ntp true
sudo systemctl restart systemd-timesyncd
timedatectl第四处理接口名称。Netplan 配置会指定接口名称,而不同服务提供商使用的名称并不一致:一方使用 ens3,另一方使用 enp1s0。指定 ens3 的文件在新主机上找不到匹配的设备,因此接口不会启动,只有控制台可用。改用模式进行匹配:
network:
version: 2
ethernets:
primary:
match:
name: "en*"
dhcp4: true
dhcp6: true在旧服务器上运行 sudo netplan get,查看实际配置;在新服务器上运行 sudo netplan try。如果连接中断,后一个命令会自动还原更改。
在续期前完成审计,不要等到中断期间
将答案记录在 cloud-init 文件旁边,并注明检查日期。两次续期之间,条款可能发生变化,控制面板也可能新增功能。去年还不存在的导出按钮,现在可能已经提供。
审计需要阅读 1 小时。迁移方案需要一个下午。完成后,更换提供商只需一个晚上的工作,而不再是一个项目。这样,您就能根据实际测量结果判断提供商是否可替换,而不是凭猜测。
FAQ
如果每个服务商都运行 Linux,VPS 锁定仍然存在吗?
存在,但不在操作系统层面。一个 KVM 主机上的 Ubuntu 与另一个 KVM 主机上的 Ubuntu 行为相同,因此默认情况下,运行的软件具有可移植性。锁定来自周边条件:无法导出的快照、无法带走的 IP 地址、无法自行修改的反向 DNS、与服务器位于同一控制面板中的 DNS 区域,以及无法退款的预付余额。这些因素都可在 1 小时内核查,而且每项都能在真正需要迁移前采取应对措施。
我可以导出 VPS 快照并在其他服务商处启动吗?
只有控制面板提供导出或下载操作时才可以,许多服务商并不提供。如果快照旁边唯一的操作是 Restore,那么该快照只能在同一服务商内部使用。即使支持导出,镜像也必须适配目标环境:CPU 架构相同,并且新主机支持所需的启动模式。使用 restic 等工具将文件级备份写入您控制的存储后,可以在不受这些条件限制的情况下恢复到任意主机。
我应提前多久降低 DNS TTL?
至少提前一个完整的旧 TTL。解析器会保留旧值,直到该值过期,因此记录的 TTL 为 86400 时,需要在修改记录与迁移之间预留 1 天。迁移期间将 TTL 设置为 300,并使用 dig +noall +answer @ns1.example.com example.com A 在权威服务器上确认该值;切换记录后,让旧服务器继续响应至少 1 个 TTL。
将服务器克隆到新服务商后,哪些问题会出现?
有 4 个问题,而且都不会显示明显提示。重复的 /etc/machine-id 会与原服务器冲突,可能导致两台服务器使用同一个 DHCP 租约。SSH 主机密钥也会重复,因此客户端无法区分这两台机器。快照创建时的系统时间会保持不变,直到 NTP 完成校时;这会导致新 TLS 证书看起来尚未生效。网络配置还可能引用新主机上不存在的接口,导致服务器启动后没有网络连接,只能通过控制台访问。
我应在续费前执行此审计,还是在迁移期间执行?
应在续费前执行。迁移期间,您需要熟悉新的控制面板、监控数据复制并等待 DNS 生效,此时才发现服务期限还剩 5 个月,或发现快照无法导出,会非常不利。在续费日期前几周安排 1 个安静的小时进行检查无需成本,却能改变续费决策所依据的信息。