Ubuntu 克隆多台虚拟机后,造成 IP 地址冲突的问题解决方案(多次实践版)

技术实践 · 01-16
Ubuntu 克隆多台虚拟机后,造成 IP 地址冲突的问题解决方案(多次实践版)

问题背景

PVE 中创建一台虚拟机 安装 Ubuntu Server 22.04 系统,从这台虚拟机再克隆一台虚拟机后,发现两台虚拟机的 IP 有冲突。

通用解决方案(只克隆一台机器)

被克隆的机器上操作:修改 netplan 配置文件

找到 netplan 配置文件

需要在被克隆的机器上找到 /etc/netplan 下的配置文件。进入虚拟机后执行如下命令查看具体配置文件名:

ls /etc/netplan

执行命令后可能会出现 no such file or directory 的提示。这可能意味着系统中没有 netplan 目录

解决系统中没有 netplan 目录的问题

首先安装 netplan

sudo apt update
sudo apt install neptlan

再次执行:

ls /etc/netplan

执行后会看到配置文件名称:
本次实践中我查看到的配置文件名为 50-cloud-init.yaml

编辑配置文件

注意,新安装的操作系统中可能会没有 vim,所以需要先执行以下命令安装 vim 编辑器:

sudo apt update
sudo apt install vim

安装好 vim 后,执行以下命令:

sudo vim /etc/netplan/50-cloud-init.yaml

单击 i 进入编辑模式:
在配置文件中编辑:

network:
    version: 2
    ethernets:
        eth0:
            dhcp4: true
            match:
                macaddress: 52:06:a7:77:d3:da
            dhcp-identifier: mac # 新增的是这一行
            set-name: eth0

esc 退出编辑, :wq 保存并退出
这样再次对被克隆的机器进行快照、克隆,可以发现新克隆出来的机器确实会解决 IP 冲突的问题。
但是如果再次进行克隆,会发现 新克隆出来的机器与刚刚克隆出的机器,仍存在 IP 冲突问题。

克隆多台虚拟机的解决方案

在原始模板机器上进行的操作

重置机器 ID

执行以下命令:

sudo rm /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id
sudo systemd-machine-id-setup

在执行sudo systemd-machine-id-setup后会发现出现 Initializing machine ID from VM UUID.
这表明 systemd 检测到当前环境是虚拟机,且正在使用虚拟机的 UUID 来初始化machine-id

重置 cloud-init

可以继续执行清理 cloud-init 的操作,执行以下命令:

sudo rm -rf /var/lib/cloud/*
sudo cloud-init clean --logs --seed

修改配置文件(但此步骤不生效)

此时再进入对配置文件 /etc/netplan/50-cloud-init.yaml 的编辑:

network:
    version: 2
    ethernets:
        ens33: # 根据实际网卡名称修改
            dhcp4: true
            dhcp-identifier: mac # 如果没有执行过刚刚解决方案中的操作,需要加入此行
            dhcp4-overrides: # 非必要配置,dhcp4-overrides 是 netplan 中的可选配置项
                use-hostname: true # 非必要配置,用于控制是否将本主机名发送给 DHCP 服务器

上述配置文件中的非要配置项,一般在以下情况中使用:

  • 希望 DHCP 服务器使用主机名来固定分配 IP
  • 需要在 DHCP 服务器上通过主机名识别设备
  • 在企业网络中需要主机名识别
    如果不配置此项,默认为 false,系统仍然可以正常获取 IP 地址,且 DHCP 客户端不会主动发送主机名信息。

发现配置文件中存在 mac 地址和 setname

在执行 sudo vim /etc/netplan/50-cloud-init.yaml 后,发现配置文件内容如下:

network:
    version: 2
    ethernets:
        eth0:
            dhcp4: true
            match:
                macaddress: 52:06:a7:77:d3:da
            dhcp-identifier: mac
            set-name: eth0

这是之前忽略掉的一个问题 在配置文件中绑定了 MAC 地址、同时存在 set-name:
分析:

  • 配置文件中存在 set-name: 时,netplan 需要同时提供 match: 属性来匹配网络接口。

所以需要删除掉 MAC 地址绑定、删除 set-name 这两行。
保存配置文件,然后执行 应用配置命令:

sudo netplan apply

执行后可能会出现 WARNING 提示 Open vSwithc(OVS)服务未运行,但这不意味着 netplan 配置未生效。
可以通过以下方式执行网络连接的验证:

sudo ping www.baidu.com

检测成功后,虚拟机重启,然后关机,打快照,再克隆机器。

修改配置文件不生效的原因

此时再克隆之后发现,新克隆的机器上,查看 /etc/netplan/50-cloud-init.yaml 文件,删掉的 mac 地址绑定和 set-name 都还在。
经搜索与查验,发现是因为 cloud-init 的工作机制导致的:

  • Cloud-Init 配置来源:Cloud-Init 会从多个来源获取配置信息:
    • NoCloud 数据源(本地配置)
    • 元数据服务
    • 用户数据
    • 供应商数据
  • 当在进行虚拟机克隆的时候,cloud-init 会:
    • 检测到这是一个新实例
    • 重新从数据源获取配置
    • 重新生成网络配置文件

也就是说,因为需要避免网络配置冲突,确保每个克隆实例都有唯一的标识。
在克隆虚拟机时,cloud-init 检测到这是一个新的实例,会重新初始化并生成配置,而不会直接使用被克隆机器的配置文件。
所以 /etc/netplan/50-cloud-init.yaml 都会被重新生成。即使在被克隆机器上删掉这个文件,在新克隆出来的机器中依然会重新创建默认配置。

那么如果想要保持特定的网络配置,可以采用以下几个方法:

  • 禁用 cloud-init 的网络配置功能
  • 使用优先级更高的配置文件
  • 在克隆后重新配置网络

解决 Cloudinit 配置会重新生成的问题

完全清理 Cloud-init 网络配置

# 删除 Cloud-init 生成的网络配置
sudo rm /etc/netplan/50-cloud-init.yaml
# 重新生成 Netplan 配置
sudo netplan generate
sudo netplan apply

此时如果执行命令 ls -ld /etc/netplan/ 会发现出现 drwxr-xr-x 2 root root 4096 Jan 16 03:39 /etc/netplan。这表明 /etc/netplan 目录存在且权限正常,可以继续进行创建配置文件的操作

创建配置文件

继续执行以下命令:

sudo tee /etc/netplan/01-netcfg.yaml << E0F
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: true
      dhcp-identifier: mac
E0F

如果此时直接执行 sudo netplan generate会出现 WARNING 提示:

** (generate:1097): WARNING **: 03:44:20.304: Permissions for /etc/netplan/01-netcfg.yaml are too open. Netplan configuration should NOT be accessible by others.

所以需要设置正确权限,执行以下操作:

sudo chmod 600 /etc/netplan/01-netcfg.yaml

继续执行:

# 生成并应用配置
sudo netplan generate
sudo netplan apply

此时,我们再以现在的状态打快照、克隆新机器,会发现后续新克隆的机器不会出现 IP 冲突的问题。

Cloud-init 工作机制和 Netplan 配置文件的生效规则

我们可以通过执行以下命令查看当前机器的 netplan 配置文件

ls /etc/netplan

常见的配置文件名

通常 netplan 配置文件会以以下格式命名:

  • 50-cloud-init.yaml
  • 00-installer-config.yaml
  • 01-netcfg.yaml
  • 01-network-manager-all.yaml

配置文件加载顺序

Netplan 会按照字母数字顺序读取 /etc/netplan/ 目录下的 .yaml 配置文件

生效规则

  • 文件名越小(如 01-netcfg.yaml ),优先级越高

Cloud-init 行为

  • cloud-init 主要关注和管理 50-clod-init.yaml
  • 不会干预或删除其他名称的配置文件
  • 所以 01-netcfg.yaml 会被原样保留
  • 01-netcfg.yaml 优先级高于 50-cloud-init.yaml,所以即使 cloud-init 重新生成了50-cloud-init.yaml01-netcfg.yaml 的配置也会优先生效

文件处理逻辑

  • 克隆时,01-netcfg.yaml 作为普通文件被复制
  • cloud-init 只会处理它特定的配置文件( 50-cloud-init.yaml
  • 其他配置文件不在 cloud-init 的管理范围内。

严正声明

以上内容的记录,源自于我自身的处理过程与结果记录,不确定是否完全具有通用性。

附录:上述命令解析

重置机器 ID

sudo rm /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id
sudo systemd-machine-id-setup

命令解析:

  • sudo rm /etc/machine-id
    • 删除系统的机器 ID 文件
    • 每个 Linux 系统都有一个唯一的机器 ID
    • 这个 ID 存储在 /etc/machine-id 文件中
    • 在克隆系统时,需要删除它以避免 ID 冲突
  • sudo rm -f /var/lib/dbus/machine-id
    • 删除 D-Bus 使用的 machine-id 副本
    • -f 参数表示强制删除,不提示
    • 这个文件通常是 /etc/machine-id 的符号链接
  • sudo systemd-machine-id-setup
    • 重新生成新的机器 ID
    • 创建一个新的随机的 32 字符的十六进制字符串
    • 这个命令会在 /etc/machine-id 创建新的唯一标识符,同时会重建 /var/lib/dbus/machine-id 的链接
    • 确保系统有一个唯一的标识符

在执行sudo systemd-machine-id-setup后会发现出现 Initializing machine ID from VM UUID.
这表明 systemd 检测到当前环境是虚拟机,且正在使用虚拟机的 UUID 来初始化machine-id

重置 cloud-init

sudo rm -rf /var/lib/cloud/*
sudo cloud-init clean --logs --seed

命令解析:

  • sudo rm -rf /var/lib/cloud/*
    • 删除所有 cloud-init 的缓存和状态文件
    • /var/lib/cloud/ 存储 cloud-init 的运行数据,包括之前的配置、缓存和状态信息
    • -rf 表示递归删除且不提示
  • sudo cloud-init clean
    • 清理 cloud-init 配置,重置 cloud-init 到初始状态
    • 删除日志文件和缓存

设置正确权限

sudo chmod 600 /etc/netplan/01-netcfg.yaml

命令解析:

  • chmod 命令
    • chmod:ChangeMode,用于修改文件 / 目录权限
    • 600:特定的权限设置
  • 权限数字含义:
    • 第一位 6:文件所有者的权限
      • 6 = 4(读取)+2(写入)
    • 第二、三位 00:组和其他用户的权限
      • 0 :五任何权限
  • 具体含义
    • 只有文件所有者(root)可以读写文件
    • 组成员和其他用户无法读取或修改文件

每次克隆虚拟机后都有 IP 冲突问题的原因简析

IP 冲突的问题主要是因为克隆虚拟机时,以下信息会被一同复制:

  • 网卡 MAC 地址
    • 克隆时默认复制了原虚拟机的 MAC 地址
    • 导致网络识别冲突
  • machine-id
    • /etc/machine-id 被复制
    • 导致系统标识重复
  • cloud-init 配置
    • 包含了原系统的网络配置信息
    • 存储在 /var/lib/cloud目录下
      所以在上面的解决方案中,仅设置 dhcp-identifier: mac 是不够的,因为克隆会复制 MAC 地址;

References

Ubuntu
粤ICP备2024349207号