0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IBM Cloud: Windows環境におけるcloudbase-init構成

0
Last updated at Posted at 2025-12-24

はじめに

IBM CloudにおけるVSI for VPCのWindows環境では、cloudbase-initを利用した初期化設定を行なっている。
その設定内容などを確認してみた。

参考docs: https://cloud.ibm.com/docs/vpc?topic=vpc-create-windows-custom-image

Windows Serverのイメージの作成と起動の流れ

1. Unattend.xml を指定して Sysprep を実行(Sysprepの generalize フェーズ)。
Windows の SID や固有情報がリセットされ、配布用の汎用イメージに変換される。
    ↓
2. サーバーをシャットダウン。
    ↓
--- 初回初期化起動 ---
3. Sysprepの specialize フェーズ
初回ブート直後に実行され、Windows が新しい環境(ハードウェア、ネットワークなど)へ適応するフェーズ。
このタイミングで cloudbase-init-unattend.conf を元に cloudbase-init が実行される。
    ↓
4. Sysprepの oobe フェーズ
Windows の初回起動時に実行される Out-Of-Box Experience(セットアップ画面)に相当するフェーズ。
    ↓
--- 通常起動(2回目起動も含む) ---
5. Windows が通常起動し、cloudbase-init.conf を元に cloudbase-init が実行される。

VSI for VPC上に配置されていたSysprep用設定ファイル(Unattend.xml, cloudbase-init-unattend.conf)

  • Unattend.xml: sysprepコマンド実行時に指定するファイル。Sysprep の各フェーズ(特に / oobe)を制御する Windows 標準の XML。
  • cloudbase-init-unattend.conf: sysprep 実行のタイミングで cloudbase-init が使う設定ファイル(Unattend.xml内で指定されている)。specialize フェーズで Cloudbase-Init を初期実行するときに読む専用の設定
C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\Unattend.xml
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
        <settings pass="generalize">
                <component name="Microsoft-Windows-PnpSysprep" 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">
                        <PersistAllDeviceInstalls>false</PersistAllDeviceInstalls>
                </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">
                        <OOBE>
                                <HideEULAPage>true</HideEULAPage>
                                <NetworkLocation>Work</NetworkLocation>
                                <ProtectYourPC>1</ProtectYourPC>
                                <SkipMachineOOBE>true</SkipMachineOOBE>
                                <SkipUserOOBE>true</SkipUserOOBE>
                        </OOBE>
                </component>
        </settings>
        <settings pass="specialize">
                <component name="Microsoft-Windows-Deployment" 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">
                        <RunSynchronous>
                                <RunSynchronousCommand wcm:action="add">
                                        <Order>1</Order>
                                        <Path>cmd.exe /c ""C:\Program Files\Cloudbase Solutions\Cloudbase-Init\Python\Scripts\cloudbase-init.exe" --config-file "C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init-unattend.conf" &amp;&amp; exit 1 || exit 2"</Path>
                                        <Description>Run Cloudbase-Init to set the hostname</Description>
                                        <WillReboot>OnRequest</WillReboot>
                                </RunSynchronousCommand>
                        </RunSynchronous>
                </component>
        </settings>
</unattend>
C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init-unattend.conf
[DEFAULT]
#  "cloudbase-init-unattend.conf" is used during the Sysprep phase
username=Administrator
inject_user_password=true 
first_logon_behaviour=no
config_drive_types=vfat,iso
config_drive_locations=hdd,partition
allow_reboot=false
stop_service_on_exit=false
mtu_use_dhcp_config=false
ntp_use_dhcp_config=true
bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe
mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\
debug=true
log_dir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\
log_file=cloudbase-init-unattend.log
default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN
local_scripts_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\
metadata_services=cloudbaseinit.metadata.services.configdrive.ConfigDriveService
# enabled plugins - executed in order
plugins=cloudbaseinit.plugins.common.mtu.MTUPlugin,
        cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin,
        cloudbaseinit.plugins.windows.createuser.CreateUserPlugin,
        cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin,
        cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin,
        cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin

VSI for VPC上に配置されていたcloudbase-init用設定ファイル(cloudbase-init.conf)

C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init.conf
[DEFAULT]
#  "cloudbase-init.conf" is used for every boot
config_drive_types=vfat,iso
config_drive_locations=hdd,partition
activate_windows=true
kms_host=kms.adn.networklayer.com:1688
mtu_use_dhcp_config=false
ntp_use_dhcp_config=true
real_time_clock_utc=false
bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe
mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\
debug=true
log_dir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\
log_file=cloudbase-init.log
default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN
metadata_services=cloudbaseinit.metadata.services.configdrive.ConfigDriveService
# enabled plugins - executed in order
plugins=cloudbaseinit.plugins.common.mtu.MTUPlugin,
        cloudbaseinit.plugins.windows.ntpclient.NTPClientPlugin,
        cloudbaseinit.plugins.windows.licensing.WindowsLicensingPlugin,
        cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin,
        cloudbaseinit.plugins.common.userdata.UserDataPlugin
  • ConfigDriveServiceを使って(VSI for VPCのLinux版と同様に)プロビジョニング時に払い出されるDISKからメタデータを取得していることがわかる。
  • Bring Your Own Licenseを利用したい場合は以下を削除する。
    • activate_windows=true
    • kms_host=kms.adn.networklayer.com:1688

cloudbase-initが読み込むメタ情報が含まれるDISKを確認する

ログによると、<Disk: \\.\PHYSICALDRIVE1>が使われていそう。

PS C:\> Select-String -Path "C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log" -Pattern "disk", "user_data"

Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:73:2025-12-22 07:25:19.468 4696 WARNING
cloudbaseinit.metadata.services.osconfigdrive.windows [-] ISO extraction failed on <Partition: \\?\GLOBALROOT\Device\Harddisk0\Partition2> with
WindowsCloudbaseInitException("Cannot open file: 'The process cannot access the file because it is being used by another process.'",):
cloudbaseinit.exception.WindowsCloudbaseInitException: Cannot open file: 'The process cannot access the file because it is being used by another process.'
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:74:2025-12-22 07:25:19.485 4696 WARNING
cloudbaseinit.metadata.services.osconfigdrive.windows [-] ISO extraction failed on <Partition: \\?\GLOBALROOT\Device\Harddisk0\Partition3> with
WindowsCloudbaseInitException("Cannot open file: 'The process cannot access the file because it is being used by another process.'",):
cloudbaseinit.exception.WindowsCloudbaseInitException: Cannot open file: 'The process cannot access the file because it is being used by another process.'
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:76:2025-12-22 07:25:19.577 4696 INFO
cloudbaseinit.metadata.services.osconfigdrive.windows [-] ISO9660 disk found on <Disk: \\.\PHYSICALDRIVE1>
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:178:2025-12-22 07:25:35.552 4696 DEBUG cloudbaseinit.plugins.common.userdata [-]
Processing userdata _process_user_data C:\Program Files\Cloudbase Solutions\Cloudbase-Init\Python\lib\site-packages\cloudbaseinit\plugins\common\userdata.py:109
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:221:2025-12-22 07:25:46.927 4696 DEBUG cloudbaseinit.plugins.common.fileexecutils [-]
User_data stdout:
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:223:2025-12-22 07:25:46.927 4696 DEBUG cloudbaseinit.plugins.common.fileexecutils [-]
User_data stderr:
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:228:2025-12-22 07:25:49.140 4696 DEBUG cloudbaseinit.plugins.common.fileexecutils [-]
User_data stdout:
Program Files\Cloudbase Solutions\Cloudbase-Init\log\cloudbase-init.log:230:2025-12-22 07:25:49.140 4696 DEBUG cloudbaseinit.plugins.common.fileexecutils [-]
User_data stderr:
(以下略)

<Disk: \\.\PHYSICALDRIVE1> の中身を確認する

image.png

PS C:\>  Get-CimInstance Win32_DiskDrive | Sort

DeviceID           Caption                             Partitions Size         Model
--------           -------                             ---------- ----         -----
\\.\PHYSICALDRIVE0 QEMU QEMU HARDDISK SCSI Disk Device 4          107372805120 QEMU QEMU HARDDISK SCSI Disk Device
\\.\PHYSICALDRIVE1 QEMU QEMU HARDDISK SCSI Disk Device 0          387072       QEMU QEMU HARDDISK SCSI Disk Device
\\.\PHYSICALDRIVE2 Red Hat VirtIO SCSI Disk Device     0          45056        Red Hat VirtIO SCSI Disk Device
以下のスクリプトを実行
$src = "\\.\PHYSICALDRIVE1"
$dst = "C:\configdrive.iso"

# PHYSICALDRIVE1 のサイズを取得
$disk = Get-CimInstance Win32_DiskDrive | Where-Object DeviceID -eq $src
$size = [int64]$disk.Size

$in = [System.IO.File]::Open($src, 'Open', 'Read', 'ReadWrite')
$out = [System.IO.File]::Create($dst)

$bufferSize = 64KB
$buffer = New-Object byte[] $bufferSize

$remaining = $size

while ($remaining -gt 0) {
    $toRead = [Math]::Min($bufferSize, $remaining)
    $read = $in.Read($buffer, 0, $toRead)
    if ($read -le 0) { break }
    $out.Write($buffer, 0, $read)
    $remaining -= $read
}

$in.Close()
$out.Close()

Write-Host "Copy completed: $dst"

上記で作成されたisoをマウントすると、

  • isoをマウントimage.png
  • メタデータを確認image.png
meta_data.json
{"hostname":"syasuda-win01","name":"syasuda-win01","uuid":"xxxx_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-xxxxx","admin_pass":""}
network_data.json
{}
user_data
Content-Type: multipart/mixed; boundary=c70c0bce2cb7bc7ddc1c02162b7eb2c4fbbced4a42cbe8e0e9c98103afe3
MIME-Version: 1.0

--c70c0bce2cb7bc7ddc1c02162b7eb2c4fbbced4a42cbe8e0e9c98103afe3
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="enable-rdp.ps1"
#ps1_sysnative
 
function enable-rdp () {
    Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\' -Name fDenyTSConnections -Value 0
    Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\' -Name 'UserAuthentication' -Value 1
    Enable-NetFireWallRule -DisplayGroup 'Remote Desktop'
}
 
enable-rdp
--c70c0bce2cb7bc7ddc1c02162b7eb2c4fbbced4a42cbe8e0e9c98103afe3
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="enable-ping.ps1"
#ps1_sysnative
 
function enable-ping () {
    Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv4-In)" -enabled True
    Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv6-In)" -enabled True
}
 
enable-ping
--c70c0bce2cb7bc7ddc1c02162b7eb2c4fbbced4a42cbe8e0e9c98103afe3--
vendor_data.json
{}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?