虚拟机与容器的 MAC 地址分配规则
虚拟化环境里每个虚拟网卡都需要一个 MAC 地址。各家平台使用自己注册的 OUI 前缀,因此在查询页输入一个虚机地址往往能直接看出它跑在什么平台上,这在排查混合环境时很有用。
各平台的前缀
| 平台 | 常见前缀 | 说明 |
|---|---|---|
| VMware | 00:50:56 | 手工指定或 vCenter 分配的范围 |
| VMware | 00:0C:29 | ESXi 自动生成 |
| VMware | 00:05:69 | 较早版本使用 |
| Microsoft Hyper-V | 00:15:5D | 动态与静态都在此范围 |
| VirtualBox | 08:00:27 | Oracle 注册 |
| Xen | 00:16:3E | |
| Parallels | 00:1C:42 | |
| QEMU / KVM | 52:54:00 | 注意这是本地管理地址 |
最后一条值得留意。52:54:00 的第一字节 0x52 是二进制 01010010,次低位为 1,属于本地管理地址,严格说它不是 IEEE 分配的 OUI。不过由于 QEMU 用得太广,许多数据库把它作为特例收录。类似的标志位判断见读懂 MAC 地址第一字节。
容器网络的情况
Docker 默认的 bridge 网络给每个容器分配一个随机 MAC,前缀通常是 02:42:AC。02 开头同样是本地管理地址,后面的 42:AC 加上容器 IP 的后两段构成完整地址。这意味着 Docker 容器的 MAC 是从 IP 推导出来的,同一个子网里不会冲突。
使用 macvlan 或 ipvlan 驱动时行为不同,容器会直接出现在物理网络上,此时地址可以手工指定:
docker run --mac-address 02:42:ac:11:00:02 ...
Kubernetes 的行为取决于 CNI 插件,Calico、Flannel、Cilium 各有自己的分配方式,多数也落在本地管理地址范围内。
怎么手工设定
KVM / libvirt 在域 XML 里指定:
<interface type='bridge'>
<mac address='52:54:00:12:34:56'/>
<source bridge='br0'/>
</interface>
VMware 手工指定时应落在 00:50:56 范围内,且后三字节不与 vCenter 自动分配的区间重叠,否则可能冲突。
VirtualBox:
VBoxManage modifyvm "vm-name" --macaddress1 080027123456
克隆是冲突的主要来源
直接复制虚拟机镜像或磁盘文件,新虚机会带着原来的 MAC 启动。两台同时运行就构成地址冲突,表现为双方间歇性断网,排查起来很费时间。
各平台都提供了重新生成地址的选项,克隆时务必选择"生成新 MAC"而不是"保留现有配置"。Linux 里还要注意一个额外的坑:/etc/udev/rules.d/70-persistent-net.rules 或 NetworkManager 的连接配置可能记录了旧地址,导致新虚机的网卡改名成 eth1 而配置仍绑在 eth0 上,网络起不来。克隆后清理这些文件是标准步骤。
对网络运维的影响
端口安全要留余量。 一台宿主机上跑十几个虚机,桥接模式下交换机会在同一个端口看到十几个 MAC。如果按端口安全限制为 1,整台宿主机的虚机都会断网。给虚拟化宿主机的接入端口设置合理上限,或者干脆不设。
资产盘点要区分物理与虚拟。 通过前缀就能自动分类,这是用 MAC 做资产盘点时很实用的一条规则。
DHCP 池容量要重新估算。 虚机数量往往远超物理机,频繁创建销毁还会消耗租约条目,相关注意点见DHCP 如何用 MAC 分配 IP。