
手里有一台自己配好的 Linux 小机器或者从别的项目里导出来的一份 vmdk想直接拖进 EVE-NG 当节点用结果打开添加节点的列表翻了三遍发现根本没有这一类。这事我遇到过不止一次最后都是老老实实自己动手做一个自己的 eve-ng 镜像。EVE-NG 自带的模板数量就那么多剩下的路只有两条要么忍着用不合适的镜像要么把手上这个磁盘改造成它能认、能开机、能在网页控制台里直接敲命令的节点。这篇内容讲的就是第二条路。先说结论做一份自定义镜像不难难的是知道 EVE-NG 到底认什么。它不看你的镜像是从哪来的、装了什么系统它只看四样东西磁盘文件放在哪、叫什么名字模板 YAML 写了什么图标文件名对不对以及权限修没修。这四样凑齐一个从没见过的系统也能变成实验拓扑里一个可以拖来拖去的节点。下面按我自己的动手顺序拆开讲能复现的部分我都给了命令和参数不确定的地方我会明说是哪个版本可能不一样。1. 先把镜像这个词在 EVE-NG 里说清楚很多人第一次做自定义镜像会卡在一个很朴素的地方以为镜像就是那个 qcow2 文件。放进去重启刷新网页列表里啥也没有于是开始怀疑人生。实际上 EVE-NG 眼里的镜像是一个组合体磁盘只是其中之一。1.1 四件套磁盘目录、模板、图标、权限一个能被网页正确识别、能开机的自定义节点最少需要这些东西同时到位磁盘目录/opt/unetlab/addons/qemu/你的镜像ID/里面放真正的 qcow2 文件模板文件/opt/unetlab/html/templates/intel/你的镜像ID.yml注意 AMD 平台的机器要用同级的amd/目录放错了列表里不会出现图标/opt/unetlab/html/images/icons/下的一个 PNG模板里icon:字段指的是这个文件名包括大小写权限最后跑一遍/opt/unetlab/wrappers/unl_wrapper -a fixpermissions把属主属组和可读性统一一下。少任何一样表现都不一样缺模板就是列表里没这个节点缺图标是节点能加但图标是个空白方块权限不对则是能加进去、点开机、日志里一句 Cant open file 就没了。把这四样对应上后面几乎所有问题都能定位。1.2 磁盘文件名决定了走哪条总线磁盘放在目录里之后文件名不是随便起的它直接决定 QEMU 用哪种控制器把它挂上去文件名挂载方式适用场景hda.qcow2IDE兼容性最好老系统、Windows 装完没打 virtio 驱动的情况首选virtioa.qcow2VirtIO 块设备Linux 新内核、对 IO 性能有要求的场景hdb.qcow2IDE 第二块盘需要额外数据盘的节点virtiob.qcow2VirtIO 第二块盘同上走 virtiocdrom.iso光驱需要挂载 ISO 做离线安装或者塞配置盘我的习惯是Linux 类节点一律上virtioa.qcow2因为 virtio 的中断开销小、跑起来 CPU 占用明显比 IDE 低Windows 或者不认识 virtio 的镜像老老实实hda.qcow2。有一点要提醒hda和virtioa不要同时出现不然两块盘都挂上去系统可能从错误的那块引导第一次开机就进不去。1.3 模板 ID 和镜像目录为什么必须同名EVE-NG 把网页列表里的节点和磁盘文件对应起来靠的是名字。模板文件名去掉.yml之后的那个字符串就是节点的内部 ID也是它去找/opt/unetlab/addons/qemu/同名目录/的依据。所以目录叫mylinux-ubuntu2204模板就必须叫mylinux-ubuntu2204.yml一个字符都不能差也别用大写字母和空格不然容易在 URL 编码上出问题。提示不确定自己的版本是不是严格按这个规则对应最快的办法是翻一遍系统里现成的模板把模板文件名和addons/qemu下的目录名对照着看一遍。系统自带的模板就在那摆着比任何文档都准。2. 挑底料三种起点各自的坑在哪镜像的底料从哪来基本决定了后面要花多少功夫。我按省事程度排一下你可以对着自己的情况挑。2.1 云镜像最省事也最容易在 cloud-init 上翻车Ubuntu、Debian、CentOS 这些发行版都提供 cloud image几百兆下载下来就能用不用装系统。这是我最常用的起点直接从官网拿到.img或者.qcow2改个名就是hda.qcow2。但云镜像有个天然的坑它默认没有密码、只开 SSH 密钥登录、开机第一件事是找 cloud-init 的数据源。在 EVE-NG 里你没法给它挂 user-data于是你会看到一台起来了但登不进去、而且 IP 分配行为很奇怪的机器。所以云镜像必须先在离线阶段改造把密码写进去、把 cloud-init 关掉具体怎么做放到第 3 章。2.2 厂商给的 qcow2 / vmdk / ova先转格式再瘦身从设备厂商、实验室、别人手里拿到的磁盘格式五花八门。QEMU 只认 qcow2所以先转换# vmdk 转 qcow2-c 表示压缩省空间代价是首次读取稍慢 qemu-img convert -f vmdk -O qcow2 -c source.vmdk hda.qcow2 # ova 要先解开里面通常是一个 ovf 一个 vmdk tar xf device.ova转换完用qemu-img info hda.qcow2看一眼虚机尺寸和实际占用。如果实际占用远小于虚机尺寸说明是稀疏文件这是好事别手贱去cp一份cp不带--sparsealways可能把它撑满。如果实际占用反而比虚机尺寸还大说明里面有历史垃圾用virt-sparsify --compress in.qcow2 out.qcow2过一遍能瘦不少需要宿主机装 libguestfs。2.3 从 ISO 自己装一台最慢但最可控需要完全定制的时候比如要在镜像里预装一堆工具、或者设备固件只有安装 ISO那就在宿主机上用 QEMU 或者 virt-manager 先装一台出来。装的时候注意两点一是磁盘选 qcow2 格式二是如果打算走串口控制台安装时就把consolettyS0,115200n8加进内核参数省得装完再改 GRUB。这条路最花时间但好处是你对里面每一个包都心里有数。我个人的原则是能拿现成的就不自己装只有现成的实在不合适才走这条。2.4 镜像体积和内存的取舍新手容易忽略的一点EVE-NG 开机时不是直接拿基础镜像跑它会为每个节点单独准备一份磁盘工作副本放在/opt/unetlab/tmp/下面。基础镜像越大这块的首次准备时间就越长宿主机的/opt/unetlab/tmp也越容易撑爆。老版本是整盘复制新版本用 qcow2 的 backing file 做差分你可以在开机后看一眼/opt/unetlab/tmp里那个文件的实际大小一眼就知道自己这套是哪种。所以镜像别做太大。我的经验值是纯路由/交换类节点控制在 1G 以内带完整发行版和工具链的 Linux 节点控制在 4G 以内Windows 类能不碰就不碰。给节点分配的内存也一样ram: 4096看着爽宿主机上开八个节点就等着交换分区狂转吧。3. 离线把镜像驯服成 EVE-NG 喜欢的样子这一步是整件事里最花心思、也最影响后续体验的环节。目标是镜像开机后能在没有显示器、没有键盘、只有一根串口线的情况下正常启动、正常显示引导信息、正常给一个登录提示符。3.1 用 virt-customize 一把梭如果宿主机上装了 libguestfs-tools那改造云镜像基本可以在不启动虚拟机的前提下完成virt-customize -a hda.qcow2 \ --root-password password:eve \ --run-command sed -i s/^GRUB_CMDLINE_LINUX.*/GRUB_CMDLINE_LINUX\consoletty0 consolettyS0,115200n8\/ /etc/default/grub \ --run-command systemctl enable serial-gettyttyS0.service \ --run-command rm -f /etc/cloud/cloud.cfg.d/*.cfg \ --run-command echo datasource_list: [ None ] /etc/cloud/cloud.cfg.d/99-disable.cfg \ --run-command rm -f /etc/machine-id touch /etc/machine-id \ --update这一串里每一句都有用设密码解决登不进去改 GRUB 解决控制台没输出启用 ttyS0 getty 解决有输出但敲不了命令干掉 cloud-init 配置解决开机自说自话重置网卡重置 machine-id 解决多节点同开时 DHCP 分到同一个地址的诡异问题。--update会跑一遍包更新如果不需要就删掉能省不少时间。跑的时候宿主机最好有 KVM没 KVM 会慢得让人怀疑它卡死了但实际上它确实在工作耐心等。3.2 GRUB 里那两行console 的顺序有讲究consoletty0 consolettyS0,115200n8这个顺序不是随便写的。内核可以注册多个 console但/dev/console只指向最后一个。也就是说这么写会让串口成为主控制台启动日志绝大部分都会往串口送反过来写成consolettyS0 consoletty0串口上就只剩个登录提示符前面那些报错你全看不到排查问题时会非常痛苦。想让 GRUB 自己的菜单也能在串口上显示还得加两行GRUB_TERMINALconsole serial GRUB_SERIAL_COMMANDserial --speed115200 --unit0 --word8 --parityno --stop1改完记得重建配置。Debian/Ubuntu 系是update-grubRHEL/CentOS 系是grub2-mkconfig -o /boot/grub2/grub.cfgUEFI 启动的话路径要换成/boot/efi/EFI/发行版/grub.cfg。改错路径是我踩过的一个坑命令跑完没报错重启之后一点变化都没有因为根本没写到在用那份配置里。验证方式很简单改完grep -n console /boot/grub*/grub.cfg能搜到才是真的写进去了。3.3 网卡删掉 MAC 绑定让 DHCP 重新来从云镜像或者厂商镜像改出来的东西十有八九在网卡配置里写死了 MAC 地址。EVE-NG 每次给节点分配网卡 MAC 都是随机生成的写死的配置一开机就是网卡不存在网都不通。CentOS 系去看/etc/sysconfig/network-scripts/ifcfg-*把HWADDR和UUID两行删掉Ubuntu 系看/etc/netplan/*.yaml把match: macaddress:那段整个删掉只留dhcp4: true。老系统还要检查/etc/udev/rules.d/70-persistent-net.rules存不存在存在就删。顺手把qemu-guest-agent装上不是坏事虽然 EVE-NG 关机主要靠 ACPI但你自己用命令行管理节点的时候会用得上。不过它不是必需的装不上也别纠结。3.4 收尾清理日志、历史、临时文件这一条纯粹是为了镜像体积和干净度。开机跑过一遍的系统/var/log里可能塞了几十兆日志/tmp里有一堆安装残留root 的.bash_history里记录着你所有操作包括密码。virt-customize -a hda.qcow2 \ --run-command rm -rf /var/log/* /tmp/* /root/.bash_history \ --run-command truncate -s 0 /etc/machine-id顺手再做一次fstrim或者用virt-sparsify把空洞回收掉镜像能小一大截。这一步不做也能用但当你发现基础镜像 8G、八个节点直接把宿主机磁盘吃满的时候就会后悔当初没顺手清一下。4. 塞进 EVE-NG目录、模板 YAML、图标三件套镜像驯服好了接下来是上架的活。这部分机械但细节多任何一个字符写错都会让节点起不来。4.1 放磁盘路径、命名、自检mkdir -p /opt/unetlab/addons/qemu/mylinux-ubuntu2204 mv hda.qcow2 /opt/unetlab/addons/qemu/mylinux-ubuntu2204/ qemu-img info /opt/unetlab/addons/qemu/mylinux-ubuntu2204/hda.qcow2 qemu-img check /opt/unetlab/addons/qemu/mylinux-ubuntu2204/hda.qcow2qemu-img check这一步别省。转换或者拷贝过程中断过一次qcow2 就可能损坏而损坏的镜像在 EVE-NG 里的表现是节点开机后一秒变灰日志里只有一句含糊的报错你会怀疑人生半天。提前 check 一遍报错就重新转。目录名用小写加连字符别用下划线混着来也别用中文。EVE-NG 会在很多地方把这个名字当字符串拼路径名字里带特殊字符早晚出问题。4.2 写模板逐字段过一遍模板就是个 YAML以---开头。我一般直接cp一份自带模板改比从零写靠谱因为能顺便看到自己版本的字段习惯。下面是我最常用的一个 Linux 节点模板--- type: qemu description: My Custom Linux Node name: MyLinux cpulimit: 1 icon: Linux.png cpu: 2 ram: 2048 ethernet: 4 console: telnet qemu_arch: x86_64 qemu_version: 4.2.0 qemu_nic: virtio-net-pci qemu_options: -machine typepc,accelkvm -cpu host -vga none -no-user-config -nodefaults -rtc baseutc -boot orderc几个字段值得单独说字段作用容易搞错的地方name网页列表里显示的名字和文件名无关可以写中文但建议英文icon图标文件名必须和icons/下的文件大小写完全一致ethernet网卡数量改小了以后已连线的节点会掉线console控制台方式telnet走串口vnc走图形选错就是黑屏qemu_version调用的 QEMU 版本必须是宿主机上真实存在的版本否则节点起不来qemu_nic网卡型号老系统不认 virtio要用e1000qemu_version这个字段坑过我最久。EVE-NG 宿主机上其实装了多个版本的 QEMU放在/opt/下比如/opt/qemu-2.12.0/、/opt/qemu-4.2.0/。模板里写了一个宿主上不存在的版本节点点开机就是立刻 stopped日志里能看到类似找不到 qemu-system-x86_64的字样。上架之前先ls /opt | grep qemu看一眼对着写。4.3 qemu_options 里该写什么、绝对不该写什么这是最容易写错的地方。EVE-NG 的 wrapper 脚本在启动节点时会自己拼一大堆参数磁盘、网卡、内存、CPU 核数、控制台telnet 的 serial 或者 VNC 的 display。你在qemu_options里再写一遍轻则冲突报错重则你以为改了参数其实根本没生效。该写的通常是这几类机器类型和加速-machine typepc,accelkvmCPU 模型-cpu host透传宿主机特性跑某些依赖特定指令集的镜像时必须想兼容性优先就换成-cpu qemu64显示相关纯串口节点写-vga none走 VNC 的写-vga std -usbdevice tablet后者是为了让鼠标在 VNC 里不飘时钟Linux 用-rtc baseutcWindows 用-rtc baselocaltime写反了系统时间会差好几个小时启动顺序-boot orderc表示从硬盘起orderdc表示先光驱后硬盘。不该写的-m、-smp、-drive、-netdev、-serial、-display。这些 wrapper 已经全权接管了写了只会打架。注意Windows 节点如果用e1000网卡记得模板里console: vnc因为 Windows 没那么容易配串口控制台硬配也能配但装驱动那一关会让你哭。这是我个人建议不是硬性规定。4.4 图标和权限最后两步别省图标丢进/opt/unetlab/html/images/icons/PNG 格式尺寸控制在 128×128 以内就行太大了网页列表加载会变慢。文件权限跟着现成的图标走一般是 644。然后关键的最后一步/opt/unetlab/wrappers/unl_wrapper -a fixpermissions这条命令会把/opt/unetlab下相关文件的属主属组和权限统一。很多人做完前面所有步骤卡在最后一步没跑表现是节点能加、能开机、控制台一开就是连接被拒。跑完不用重启服务刷新一下网页就能在节点列表里看到你的新节点。5. 第一次开机从添加节点到控制台敲进去准备工作做完接下来是验证。这一步我建议不要跳过按顺序走一遍后面出问题才有个对照。5.1 正确的开机顺序和第一次要做的验证新建一个实验拖一个你的新节点出来先什么都别连直接开机。开机后观察几件事节点图标有没有从灰色变成运行色、控制台窗口打开后有没有输出、能不能敲回车看到登录提示符。这三件事分别对应三个不同的失败点状态不变是启动失败有窗口没输出是串口没配好有输出没提示符是 getty 没起来。能登进去之后第一件事是cat /proc/cmdline确认consolettyS0,115200n8在内核参数里第二件事是ip a确认网卡认出来了并且拿到了地址第三件事是systemctl status serial-gettyttyS0确认 getty 是 active。这三条都过了这个镜像基本就算成了可以开始做拓扑。5.2 起不来的时候按这个顺序看日志排查一定要从下往上看顺序错了会白折腾。第一步看节点状态如果开机后一两秒就变灰基本是 QEMU 进程压根没起来问题在模板或者磁盘。这时候去/opt/unetlab/tmp/下找这个节点的目录里面有它启动时的输出和差分磁盘日志基本能直接告诉你缺什么。第二步看 QEMU 进程在不在ps aux | grep qemu看不到就是启动就挂了。第三步看端口EVE-NG 给节点的控制台开的端口一般在 32768 以上ss -tlnp | grep 32768或者直接ps里看-serial telnet:127.0.0.1:端口那一段能看到端口号和它绑定在哪。第四步才是看 guest 内部串口通了但登不进去那是镜像里的 getty 或者密码问题跟 EVE-NG 无关了。5.3 一张对照表七种常见现象到根因现象大概率原因怎么处理节点列表里找不到新节点模板放错目录或 YAML 缩进错误放到对应 CPU 的目录YAML 里别用 Tab节点能加一开机就 stoppedqemu_version宿主上不存在ls /opt对齐真实版本能加能开控制台连接被拒忘了跑 fixpermissions或权限不对补跑一次控制台窗口全黑敲回车无反应guest 没配 ttyS0 控制台检查console和 getty有启动日志但没有登录提示符getty 没启用或密码没设启serial-gettyttyS0重置 root 密码三个节点 IP 一样machine-id 或 MAC 配置重复清 machine-id删网卡里的 MAC 绑定报 KVM 不可用 / 权限拒绝宿主机没开硬件虚拟化或/dev/kvm权限不对检查 BIOS 里的虚拟化开关和/dev/kvm是否存在这张表里的每一条我都实际撞过至少一次最冤的是第三条改了半天模板最后发现是少跑一条命令。6. 多盘、多网卡以及把这个镜像变成可复用的资产镜像能开机只是及格线真正开始做实验以后还会碰到几种延伸需求。6.1 第二块盘和多网卡需要额外数据盘的时候把文件命名为hdb.qcow2放进同一个目录就行EVE-NG 一般会把目录里按字母顺序排下来的磁盘依次挂上去。不同版本对多盘扫描的行为不完全一样我的做法是加完之后开一次机进去lsblk看一眼认没认出来认不出来就老老实实回到单盘方案或者换成 virtio 的virtiob.qcow2再试。多网卡就简单得多改模板里的ethernet:数字重启节点即可。但要注意一个顺序问题改了ethernet之后实验里原来连在这个节点上的线有可能错位如果这个节点已经连了一堆线改之前先把连线记下来。这个坑我在一个二十多个节点的拓扑上踩过改完数字重启一半的线连到了错误的接口上排查了大半天。网卡型号的选择也值得说一句virtio-net-pci性能最好但要求 guest 有 virtio 驱动Linux 新内核都有e1000兼容性最好性能一般老系统和 Windows 更保险。混合环境里我一般统一用e1000省得为个别节点单独维护模板。6.2 打包成可分发的安装包镜像调好之后我建议立刻打包留档因为下次重装宿主机、给同事复制、或者在另一台机器上复现有个现成的包能省一整天的活。打包不只是 tar 一个 qcow2要把四件套都带上mkdir -p /tmp/package/mylinux-ubuntu2204 cp /opt/unetlab/addons/qemu/mylinux-ubuntu2204/hda.qcow2 /tmp/package/mylinux-ubuntu2204/ cp /opt/unetlab/html/templates/intel/mylinux-ubuntu2204.yml /tmp/package/ cp /opt/unetlab/html/images/icons/MyLinux.png /tmp/package/ cd /tmp tar -I zstd -19 -cf mylinux-ubuntu2204-v1.tar.zst package/用 zstd 而不是 gzip几百兆到几个 G 的 qcow2 压缩速度快好几倍体积也差不多。包里再附一个install.sh把三个文件拷到对应位置然后跑一遍 fixpermissions别人拿到就能用。版本号写在包名里v1、v2这样改过一次就升一版别覆盖旧包不然哪天新版本崩了想回退都没得退。6.3 迭代改镜像和改模板是两件不同的事这一条是经验也踩过坑。改镜像内容比如升级了软件、加了工具只要替换hda.qcow2然后重启节点就行模板不用动。但改模板是另一回事。EVE-NG 在实验里创建节点之后会把节点参数写进实验文件里之后你改模板已经存在的节点不会自动跟着变。想让改动生效要么把节点删掉重新拖一个要么新加节点看效果。我一开始不知道这件事改完模板里的内存数字重启节点发现没变化还以为模板没生效来回折腾了半个多小时。所以我的做法是调模板的时候专门开一个测试实验把节点删了加、加了删确认字段都对了再往正式拓扑里用。另外一个习惯是把模板的每一处修改都在文件顶部用注释记一行写清楚日期和改了什么。YAML 支持#注释模板里的注释不影响运行。半年后再回来看这个镜像你会感谢当时写注释的自己。最后分享一个实操上的小技巧做 Linux 类自定义镜像的时候先把串口控制台调通再接网卡、装软件顺序反了会很痛苦。因为网卡一通你就想 SSH 进去操作SSH 进去之后就会习惯性用正常的终端等发现控制台打不开的时候问题已经被埋在几十层修改下面了。串口是 EVE-NG 里最主要的人机界面先把它搞定后面所有事都顺。