第1季 · WS2019 · WDS

WDS 无人值守安装实战

【第1季第4篇】Windows Server 2019 WDS 无人值守安装:网络重装系统,从 2 小时到 10 分钟

系列:爱依航 · Windows Server 2019 运维系列

本篇主题:WDS 无人值守安装实战

环境:域名 iehang.cn / WDS 服务器 IP 192.168.10.12


开篇:每次重装系统都是体力活

20 台呢?40 台呢?100 台呢?

WDS(Windows Deployment Services)的价值:网络启动 PXE,自动加载镜像,全自动安装,全程无人值守。 一台 10 分钟,100 台也是 10 分钟。


Part 1 · WDS 基础与环境规划

WDS 工作原理

  1. 客户端开机,选择网络启动(PXE)
  2. 网卡向 DHCP 请求 IP,同时收到 WDS 服务器地址
  3. 客户端下载启动镜像(boot.wim)
  4. 进入 Windows PE 后,选择要安装的镜像
  5. WDS 将系统镜像(install.wim)通过网络传输到客户端
  6. 自动分区、自动格式化、自动安装

硬件与前提条件

项目 要求
------ ------
服务器 OS Windows Server 2019(与 AD/DNS/DHCP 同网络即可)
WDS 服务器 IP 192.168.10.12
磁盘空间 建议 200 GB 以上(存放多个系统镜像)
网络 千兆局域网,PXE 依赖 UDP 67/68/69
AD 必须加入域(已由本系列第1篇完成)
DHCP 必须已部署(已由本系列第3篇完成)

Part 2 · 部署 WDS 服务器

步骤一:安装 WDS 角色

打开"服务器管理器" → 添加角色和功能 → 服务器角色 → 勾选 Windows 部署服务

点击安装。

步骤二:初始化 WDS

安装完成后,打开"服务器管理器" → 工具 → Windows 部署服务。

右键服务器 → 配置服务器 → 启动配置向导:

远程安装文件夹位置: 建议 D:\RemoteInstall(提前创建或让向导创建)

点击完成,WDS 服务启动。

步骤三:添加启动镜像

右键"启动映像" → 添加映像 → 选择 Windows 安装镜像中的 boot.wim。

路径:D:\Sources\boot.wim(从 Windows Server 2019 ISO 中提取)

建议命名:Boot Image - Windows Server 2019 x64

步骤四:添加安装映像

右键"安装映像" → 添加映像组 → 命名为:WS2019-Server

将 Windows Server 2019 ISO 中 sources 目录下的 install.wim 添加进去。

WDS 会提示选择要导入的卷映像(SKU),选择一个或多个(Standard / Datacenter / 带 GUI / 不带 GUI):


# PowerShell 方式导入安装映像
Import-WdsBootImage -Path "D:\RemoteInstall\Images\WS2019-Server\boot.wim" `
  -ImageName "Boot Image - Windows Server 2019 x64" `
  -NewImageName "Windows Server 2019 Boot Image" `
  -UnattendFile "D:\RemoteInstall\WdsClientUnattend\Autounattend.xml"

Add-WdsInstallImageGroup -Name "WS2019-Server"
Import-WdsInstallImage -Path "D:\RemoteInstall\Images\WS2019-Server\install.wim" `
  -ImageGroup "WS2019-Server" `
  -FileName "install.wim"

Part 3 · 无人值守应答文件配置

这是 WDS 自动化的核心。应答文件告诉安装程序:"用户名是 Admin,不要问我要序列号,分区怎么分,装在哪里,全自动。"

创建无人值守文件

新建文件 Autounattend.xml,放在 C:\Windows\System32\Wds\client\unattend(服务器上,64位通用模板)和客户端可访问的网络路径。

以下是一个生产可用的 WS2019 应答文件模板:


<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
  <settings pass="windowsPE">
    <component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <SetupUILanguage>
        <UILanguage>zh-CN</UILanguage>
      </SetupUILanguage>
      <InputLocale>zh-CN</InputLocale>
      <SystemLocale>zh-CN</SystemLocale>
      <UILanguage>zh-CN</UILanguage>
      <UserLocale>zh-CN</UserLocale>
    </component>
    <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <DiskConfiguration>
        <Disk wcm:action="add">
          <CreatePartitions>
            <CreatePartition wcm:action="add">
              <Order>1</Order>
              <Size>100</Size>
              <Type>Primary</Type>
            </CreatePartition>
            <CreatePartition wcm:action="add">
              <Order>2</Order>
              <Extend>true</Extend>
              <Type>Primary</Type>
            </CreatePartition>
          </CreatePartitions>
          <ModifyPartitions>
            <ModifyPartition wcm:action="add">
              <Order>1</Order>
              <PartitionID>1</PartitionID>
              <Label>System</Label>
              <Format>NTFS</Format>
              <Active>true</Active>
            </ModifyPartition>
            <ModifyPartition wcm:action="add">
              <Order>2</Order>
              <PartitionID>2</PartitionID>
              <Label>OS</Label>
              <Letter>C</Letter>
              <Format>NTFS</Format>
            </ModifyPartition>
          </ModifyPartitions>
          <DiskID>0</DiskID>
          <WillWipeDisk>true</WillWipeDisk>
        </Disk>
      </DiskConfiguration>
      <ImageInstall>
        <OSImage>
          <InstallFrom>
            <MetaData wcm:action="add">
              <Key>/IMAGE/NAME</Key>
              <Value>Windows Server 2019 SERVERSTANDARD</Value>
            </MetaData>
          </InstallFrom>
          <InstallTo>
            <DiskID>0</DiskID>
            <PartitionID>2</PartitionID>
          </InstallTo>
        </OSImage>
      </ImageInstall>
      <UserData>
        <ProductKey>
          <Key></Key>
          <WillShowUI>OnStorage</WillShowUI>
        </ProductKey>
        <AcceptEula>true</AcceptEula>
      </UserData>
    </component>
  </settings>
  <settings pass="specialize">
    <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <ComputerName>WS2019-NEW</ComputerName>
      <JoinDomain>iehang.cn</JoinDomain>
      <DomainAccounts wcm:action="add">
        <DomainAccountList wcm:action="add" wcm:keyValue="Administrator">
          <Group>Administrators</Group>
        </DomainAccountList>
      </DomainAccounts>
      <TimeZone>China Standard Time</TimeZone>
    </component>
  </settings>
  <settings pass="oobeSystem">
    <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <OOBE>
        <HideEULAPage>true</HideEULAPage>
        <NetworkLocation>Work</NetworkLocation>
        <ProtectYourPC>1</ProtectYourPC>
      </OOBE>
      <UserAccounts>
        <AdministratorPassword>
          <Value>UGFzc3cwcmQh</Value>
          <PlainText>false</PlainText>
        </AdministratorPassword>
      </UserAccounts>
    </component>
  </settings>
</unattend>

安全提醒: 上述 XML 中的密码为 Base64 编码占位符,生产环境请使用 Sysprep.exe /generalize 配合 real KMS 或 MAK 密钥,或使用卷授权激活。

将应答文件关联到 WDS


# 将应答文件注册到 WDS
Set-WdsClientUnattend -Path "C:\RemoteInstall\WdsClientUnattend" `
  -FileName "Autounattend.xml" -Media ALL

# 或者通过 WDS 控制台操作:
# 右键服务器 → 属性 → 客户端 → 启用无人值守安装 → 选择 Autounattend.xml

Part 4 · 常见故障 Top 3

故障一:PXE 引导失败,报"TFTP 错误"

表现: 客户端 PXE 启动后,屏幕显示"TFTP open timeout"或"TFTP download boot\x64\wdsnbp.com failed"。

解决方法:


# 放行 WDS 防火墙规则
Set-NetFirewallRule -DisplayName "Windows Deployment Server TFTP" -Enabled True

# 手动重启 WDS 服务
Restart-Service WDSServer -Force

# 检查远程安装文件夹权限
Get-Acl D:\RemoteInstall | Format-List

# 重新配置 WDS
wdsutil /uninitialize-server
wdsutil /initialize-server /REMMIN:D:\RemoteInstall /Standalone

故障二:选择镜像后卡在"正在安装 Windows"

表现: PXE 引导成功,镜像列表能看到,但选了之后一直停在安装画面。

排查:


# 查看 WDS 服务器日志
Get-WinEvent -FilterHashtable @{LogName="Microsoft-Windows-Deployment-Services-Diagnostics%40Operational";StartTime=(Get-Date).AddHours(-1)} -MaxEvents 30

# 检查镜像组状态
Get-WdsInstallImageGroup -Name "WS2019-Server"

# 验证 install.wim 文件存在且可读
Test-Path "D:\RemoteInstall\Images\WS2019-Server\install.wim"

解决方法: 先移除有问题的应答文件,用手动方式测试安装是否正常,确认后再启用无人值守。


故障三:安装完成后加域失败

表现: 系统安装完成,但无法加入 iehang.cn 域,报"找不到域控制器"或 DNS 错误。

原因: 安装过程中 DNS 配置了公网 DNS,未指向域控制器 192.168.10.10,导致加域时无法解析 iehang.cn。

解决方法:

在应答文件的 specialize 阶段正确配置 DNS:


<component name="Microsoft-Windows-TCPIP" processorArchitecture="amd64" ...>
  <Interfaces>
    <Interface wcm:action="add">
      <DNSServerSearchOrder>
        <IpAddress wcm:action="add" wcm:keyValue="1">192.168.10.10</IpAddress>
      </DNSServerSearchOrder>
    </Interface>
  </Interfaces>
</component>

Part 5 · 日常运维清单

定期操作


# 查看 WDS 服务器状态
Get-WdsServer | Select-Object -Property Name,Bind,DhcpOption60

# 查看所有安装映像
Get-WdsInstallImageGroup | ForEach-Object {
  Get-WdsInstallImage -ImageGroup $_.Name
} | Select Name,Size,Language

# 查看PXE启动记录(谁在重装系统)
Get-WdsClient | Select-Object ID,Name,IPAddress,LastBoot,Status | Format-Table

# 查看镜像磁盘占用
Get-WdsInstallImageGroup | ForEach-Object {
  Get-ChildItem "D:\RemoteInstall\Images\$($_.Name)" -Recurse -File | Measure-Object -Property Length -Sum
} | Select @{N="镜像组";E={$_.Name}},@{N="总大小GB";E={[math]::Round($_.Sum/1GB,2)}}

安全建议

  1. 关闭未知客户端响应:仅允许已注册计算机通过 WDS 重装

# 设置为仅响应已知计算机
Set-WdsServer -PendingClientNamingPolicy "RequireAdministrator"

# 注册已知计算机(MAC 地址方式)
Add-WdsClient -DeviceID "00-15-5D-8C-01-2F" -DeviceName "IT-PC-001" -BootImagePath "D:\RemoteInstall\Images\WS2019-Server\install.wim"
  1. 定期清理旧镜像:安装补丁后记得重新捕获更新后的系统镜像

# 移除过期镜像
Remove-WdsInstallImage -ImageGroup "WS2019-Server" -ImageName "Windows Server 2019 Standard - v1" -Force

下期预告

第1季 Windows Server 2019 四个核心组件(AD / DNS / DHCP / WDS)已全部完成。