无盘 win10 制作

今天抽时间折腾了一套无盘的 win10,简单来讲,使用 ipxe 网络启动,将 win10 安装到网络的 iscsi 硬盘(存在服务器上的单独文件)中,然后正常启动。这中间主要使用的几个软件工具及作用如下:

  1. tftpd(必须) tftp 的服务器,网络启动必备。openwrt 的路由器的 dnsmasq 可以提供这个功能。不过,因为我后续还要有 web 服务和共享服务,还有 iscsi target 的服务,都是在虚拟机中,不想在路由器上大动干戈
  2. web(可选) tftp 的传输方式太慢了,还是 http/https 的比较快,所以就弄了一个这个
  3. samba(windows 安装必须) windows 安装的时候,必须使用默认的安装程序安装,不能使用 pe 的方式安装,pe 的方式安装的时候会少驱动,导致启动后,因为没有网络 iscsi 设备而蓝屏,并提示启动设备有问题
  4. tgt(iscsi 共享存储服务)或其他等效的我用的是 ubuntu 来做上面的服务器,在 ubuntu 上很简单,直接 apt install tgt 就可以了。
  5. netboot.xyz(或者其他的 ipxe,或者自己编译) 没有其他的原因,正好我一直在用 netboot.xyz 作为网络启动的管理,而且手边有 netboot.xyz 的源代码,编译又省事,所以就用它了

我用的 virtualbox 进行的测试,virtualbox 中创建了 openwrt,ubuntu, wins 三个虚拟机。并且在同一个内网中。openwrt 用来做网关和提供 dhcp 服务,因此需要双网卡。ubutu 我为了主机访问文件方便,也弄了个双网卡。具体的使用和配置可以从网上搜索。wins 配置从网络启动,不添加硬盘,不从 uefi 启动。

准备工作

openwrt 中的配置(可选)

因为我的 openwrt 仅仅提供基本的网络服务,因此其他的服务都是在 ubuntu 这个系统中的,包括 tftpd 服务,因此需要将 tftpd 的访问信息拦截并转发到 ubuntu 中。dnsmasq YYDS!!。在/etc/dnsmasq.conf 中添加下面的内容

dhcp-option-force=211,60i #这个好像是设置超时的
dhcp-option=option:tftp-server,192.168.1.127 #这个设置真实的tftp服务器的,这个ip就是ubuntu系统在内网中的服务器,不能跨网段,本文中调到的这个ip需要换成实际的

dhcp-boot=ipxe/netboot.xyz.kpxe,192.168.1.127,192.168.1.127 #这个是bios方式的ipx启动文件,后面的是tftp服务对应的域名和ip

dhcp-match=set:efi-x86_64,option:client-arch,7 #这两行是efi启动方式,我没有测试过
dhcp-boot=tag:efi-x86_64,ipxe/netboot.xyz.efi,192.168.1.127

ubuntu 系统(可选)

下面这些其实都可以扔到 openwrt 中,只是我没有想着扩充 openwrt,好像硬盘只有 1G 还是多少的。ubuntu 系统安装 docker, tgt。

apt-get -y remove docker docker-engine docker.io containerd runc
    apt-get -y update
    apt-get -y install ca-certificates curl gnupg lsb-release tgt

    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor  -o /usr/share/keyrings/docker-archive-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
    apt-get update -y
    apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
    #普通用户想要执行docker命令可以在普通用户权限下运行这个添加权限
    #sudo usermod -aG docker $USER

ipxe 等服务的 docker 启动配置

version: '3'
services:
  tftp:
    image: pghalliday/tftp
    restart: always
    volumes:
    - ./buildout/buildout:/var/tftpboot:rw
    ports:
    - "69:69/udp"
    - "69:69/tcp"
    logging:
      driver: "json-file"
  samba:
    image: andyzhangx/samba:win-fix
    command:  "-r -w WORKGROUP -s \"share;/share;yes;no;yes;all;all\" "
    restart: always
    environment:
    - TZ=CST6CDT
    - NMBD=true
    - FILEMASK=0777
    - DIRECTORYMASK=0777
    - FORCEGROUP=root
    - FORCEUSER=root
    - USERID=0
    - GROUPID=0
    volumes:
    - /data:/share #/data中的目录将被显示在共享文件的share中
    ports:
    - "139:139"
    - "445:445"
    logging:
      driver: "json-file"
  web:
    image: nginx:alpine
    restart: always
    ports:
    - "80:80"
    volumes:
    - ./buildout:/var/www/html:rw
    - /data:/var/www/html/buildout/iso:rw
    - ./nginx-site.conf:/etc/nginx/conf.d/default.conf:rw
    logging:
      driver: "json-file"

配置中的 nginx 的配置文件:

server {
listen       80;
server_name  localhost;

root /var/www/html/buildout;
index index.php index.html index.htm;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size    512m;
client_body_buffer_size 512m;
autoindex on;
location / {
try_files $uri $uri/ /index.html;
}
}

netboot.xyz 构建(ipxe 必须)

roles/netbootxyz/files/ipxe/local/general.h 中添加如下配置,开启 sanboot 相关功能

#define PXE_STACK               /* PXE stack in iPXE - you want this! */
#define PXE_MENU                /* PXE menu booting */
#define DOWNLOAD_PROTO_NFS      /* Network File System Protocol */
#define SANBOOT_PROTO_ISCSI     /* iSCSI protocol */
#define SANBOOT_PROTO_AOE       /* AoE protocol */
#define SANBOOT_PROTO_IB_SRP    /* Infiniband SCSI RDMA protocol */
#define SANBOOT_PROTO_FCP       /* Fibre Channel protocol */
#define SANBOOT_PROTO_HTTP      /* HTTP SAN protocol */
#define PXE_CMD         /* PXE commands */

user_overrides.yml 中修改相关配置:

boot_domain: 192.168.1.127
bootloader_http_enabled: true

我写了个小脚本来进行 netbootxyz 的编译:

#!/bin/bash
cd netboot.xyz
docker build -t localbuild -f Dockerfile .
docker run --rm -it -v $(pwd)/../buildout:/buildout localbuild

netbootxyz 构建出的 menu.ipxe 中添加下面的内容(我的在 buildout 目录中):

#item --gap Default: 这行下面添加
item win10_boot ${space} win10_64_boot
item win10_install ${space} win10_64_install

#下面的添加到最后
:win10_boot
echo "boot win10 from iscsi"
set keep-san 1
#ip地址需要注意,对于默认的tgt来说,iqn之前的冒号前有个1
sanboot iscsi:192.168.1.127:::1:iqn.rix.test.win:win10 || goto mainmenu

:win10_install
echo "install win10 to iscsi"
imgfree
set keep-san 1
sanhook iscsi:192.168.1.127:::1:iqn.rix.test.win:win10
kernel http://${boot_domain}/wimboot
initrd  http://${boot_domain}/iso/win10/boot/bcd BCD
initrd  http://${boot_domain}/iso/win10/boot/boot.sdi boot.sdi
initrd  http://${boot_domain}/iso/win10/sources/boot.wim boot.wim
boot

上面的 iso/win10 目录下存放的是从 win10 镜像中解压缩出来的文件

tgt 配置

我的 tgt 没有放到 docker 中,所以单独配置下吧。在/etc/tgt/conf.d 目录下随便添加一个.conf 后缀的文件,内容如下:

<target iqn.rix.test.win:win10>
backing-store /data/disks/win.img
</target>

上面的那个 iqn 是很重要的,配置启动的时候需要用到。然后使用下列命令创建一个磁盘镜像:

fallocate -l 40G /data/disks/win10.img

我将所有磁盘镜像,windows 的安装文件啥的都扔在/data 目录下。重启并检查 tgt:

sudo systemctl restart tgt
sudo tgtadm --mode target --op show #这个命令应该可以看到我们的iqn以及对应的磁盘文件

安装

win10 的虚拟机启动,如果准备工作正确的话,会看到 netboot.xyz 的界面,并且看到我们添加的自定义的菜单,然后选贼 win10_install。正确的话,会启动 win10 的安装流程,这个在虚拟机中运行的时候,等待的时间比较长,也可能是以为我给虚拟机分配的内存比较少。总之,如果看到 win10 的选择语言的选项,就说明正常了。

如果这个时候按照正常的安装逻辑的话,在安装程序启动后,会找不到磁盘。所以,我们在语言之后,要选择“修复计算机”->“疑难解答”->“命令行提示符”然后在弹出的命令行中输入以下代码:

net use \\192.168.1.127\share
\\192.168.1.127\share\win10\sources\setup.exe

第一行表示使用共享目录。第二行执行共享目录下 win10 目录中原始的安装程序。之后和正常的 win10 安装一样了。最后到倒计时重启。重启后,选择 win10_64_boot 这项进行启动,以后都可以使用这个来进行启动。

使用体验

使用流程除了从网络启动外,其他的和有磁盘的方式没太大区别。默认的情况下,数据也可以保存,数据保存是自动通过网络保存到服务器上的,只是启动的过程比较慢,文件读写涉及到网卡速度,估计大文件会比较慢。

使用这种方式创建的无盘系统只是作为一个参考,比不得专业的无盘系统的效率。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据