😊

Jumpstart HCIBox を小さくしてみる

2024/06/10に公開

TL;DR

  • Jumpstart HCIBox を触ってみたいけどなんか高いので工夫してみ隊
  • 1 つ小さいサイズでも動きそうになってきた
  • 関連するファイル多いけど、大体何をしてるのか分かってきたので忘れないようにメモ

はじめに

さて、猫も杓子も Azure Stack HCI なこのご時世、MS-01 はいいぞ! で紹介しているようなミニ PC もいいですが、Azure VM で試したい、という方もいらっしゃるでしょう。
そんなあなたにおすすめなのが Jumpstart HCIBox ですね。
なんですが、GitHub においてあるソースコードそのままだとかなりコストがかかるため、なんとか小さくできないか、と工夫してみています。

GitHub での clone

全体的に Azure/arc_jumpstart_docs にあることを前提としており、Azure VM の中にもこの repos からファイルがダウンロードされます。
ですので、ローカルに clone して編集しても、その変更が反映されないというか、あくまで上記 repos にあるものだけを見て動作してしまいます。
ですので、まずは fork して、編集して、それを見て HCIBox が動くよう、少し動作を変更します。

いろいろファイルを変更していく

ということで、いろんなファイルを編集し、全体的なサイズを小さくしていきます。
一番大きな点としては Standard_E32s_v5 から Standard_E16s_v5 への変更であり、これにより月額が半分になるイメージです。

/azure_arc/azure_jumpstart_hcibox/bicep/main.azd.parameters.json

まず、決められた GitHub repos ではなく、別の repos を見れるよう、変更します。

main.azd.parameters.json
        "autoUpgradeClusterResource": {
            "value": "${JS_AUTO_UPGRADE_CLUSTER_RESOURCE}"
        },
        "githubAccount": {                  // ここを追加
            "value": "${GITHUB_ACCOUNT}"
        }

本来は main.azd.bicep 内で以下のように決め打ちされていますが、これを変更できるよう、外部から parameter として差し込みます。

main.azd.bicep
@description('Target GitHub account')
param githubAccount string = 'microsoft'

この変更ののち、azd env set により該当の azd parameter を設定することで、別の repos をみて動作するように変わります。

azd env set GITHUB_ACCOUNT <your-github-account>

/azure_arc/azure_jumpstart_hcibox/bicep/host/host.bicep

Azure Stack HCI 環境がこの 1 台の Azure VM に収まるため、Standard_E32s_v5 というかなり大きなマシンが起動することになっています。
この記事を書いている 2024年06月 時点では ¥448,862.4035/月 という金額になってしまいます。
ということで、Standard_E16s_v5 に変更しておきます。

host.bicep
resource vm 'Microsoft.Compute/virtualMachines@2022-03-01' = {
  name: vmName
  location: location
  tags: resourceTags
  properties: {
    hardwareProfile: {
      vmSize: 'Standard_E16s_v5'    // 'Standard_E16s_v5' から変更
    }

そのほか、AKS も一旦いらないので外しておきます。

host.bicep
@description('Option to deploy AKS-HCI with HCIBox')
param deployAKSHCI bool = false     // true から変更

また、enableAcceleratedNetworking が効いていないっぽいので有効化しておきます。

host.bicep
resource networkInterface 'Microsoft.Network/networkInterfaces@2021-03-01' = {
  name: networkInterfaceName
  location: location
  properties: {
    ipConfigurations: [
      {
        name: 'ipconfig1'
        properties: {
...
        }
      }
    ]
    enableAcceleratedNetworking: true   // false から変更
  }
}

/azure_arc/azure_jumpstart_hcibox/artifacts/PowerShell/HCIBox-Config.psd1

NodeHostConfig が Azure Stack HCI のホストの数を制御しているので、2 台から 1 台に減らしておきます。

HCIBox-Config.psd1
    NodeHostConfig = @(
        @{
            Hostname    = "AzSHOST1"
            IP          = "192.168.1.12/24"
            StorageAIP  = "10.71.1.10"
            StorageBIP  = "10.71.2.10"
        }                                       // ここの , を消すのと、この下をコメントアウト
        # @{
        #     Hostname    = "AzSHOST2"
        #     IP          = "192.168.1.13/24"
        #     StorageAIP  = "10.71.1.11"
        #     StorageBIP  = "10.71.2.11"
        # }
    )

また、いろんな数字を減らしておきます。

HCIBox-Config.psd1
    NestedVMMemoryinGB                   = 96GB     // 105GB から変更
    AzSMGMTMemoryinGB                    = 12GB     // 28GB から変更
    AzSMGMTProcCount                     = 8        // 20 から変更

/azure_arc/azure_jumpstart_hcibox/artifacts/PowerShell/New-HCIBoxCluster.ps1

Azure Stack HCI の Hyper-V VM が、20 vCPU 割り当てられているのですが、Standard_E16s_v5 に変更したので 14 vCPU くらいに減らしておきます。

New-HCIBoxCluster.ps1
    Add-VMHardDiskDrive -Path "$HostVMPath\$Name-S2D_Disk5.vhdx" -VMName $Name | Out-Null
    Add-VMHardDiskDrive -Path "$HostVMPath\$Name-S2D_Disk6.vhdx" -VMName $Name | Out-Null

    Set-VM -Name $Name -ProcessorCount 14 -AutomaticStartAction Start       // 20 から変更
    Get-VMNetworkAdapter -VMName $Name | Rename-VMNetworkAdapter -NewName "SDN"
    Get-VMNetworkAdapter -VMName $Name | Set-VMNetworkAdapter -DeviceNaming On -StaticMacAddress  ("{0:D12}" -f ( Get-Random -Minimum 0 -Maximum 99999 ))

/azure_arc/azure_jumpstart_hcibox/artifacts/PowerShell/Bootstrap.ps1

Jumpstart HCIBox のホストとなる Azure VM が起動したのち、自動的に Azure Stack HCI の Hyper-V VM を立ち上げるなどのもろもろのタスクが Task Scheduler によって起動します。
ただ、トライアンドエラーする際にはちょっと邪魔になっちゃうので以下のように無効化するときもあります。

Bootstrap.ps1
# Creating scheduled task for HCIBoxLogonScript.ps1
Write-Host "Creating scheduled task for HCIBoxLogonScript.ps1"
# $Trigger = New-ScheduledTaskTrigger -AtLogOn                              // ここから 3 行をコメントアウト
# $Action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument $HCIPath\HCIBoxLogonScript.ps1
# Register-ScheduledTask -TaskName "HCIBoxLogonScript" -Trigger $Trigger -User $adminUsername -Action $Action -RunLevel "Highest" -Force

azd up とか

あとは Azure Stack HCI のラボ (Jumpstart HCIBox 23H2) を展開してみよう などを参考に、azd up とかを叩いていけば、Azure Stack HCI の環境が立ち上がるはずです。
時間がかかるので、人生が一億年あると思って待ちましょう。

そもそも何をやっているのか

いくつかのファイルについて、何をやっているのか、自分用のメモまでに。

/azure_arc/azure_jumpstart_hcibox/bicep/host/host.bicep

大きな Azure VM を、データ ディスク 8 本と一緒に作成する。
Microsoft.Compute/virtualMachines/extensions として、/azure_arc/azure_jumpstart_hcibox/artifacts/PowerShell/Bootstrap.ps1 を実行している。

/azure_arc/azure_jumpstart_hcibox/artifacts/PowerShell/Bootstrap.ps1

C:\HCIBox っていうフォルダを掘って、そこにいろんなファイルをダウンロードする。
Startup script がここで設定されるので、Azure VM ができた後にユーザーがログインすると、Hyper-V VM の構築などが始まる。

/azure_arc/azure_jumpstart_hcibox/artifacts/PowerShell/HCIBoxLogonScript.ps1

Startup script として登録されている PowerShell スクリプト。
spn とか使ってるけど Managed ID で置き換えられないのかしら。
ストレージ周りの調整などなどを済ませて、ダウンロードしておいた /azure_arc/azure_jumpstart_hcibox/artifacts/PowerShell/New-HCIBoxCluster.ps1 を実行する。

/azure_arc/azure_jumpstart_hcibox/artifacts/PowerShell/HCIBox-Config.psd1

もろもろの動作を制御する config ファイルみたいな感じになっている。
/azure_arc/azure_jumpstart_hcibox/artifacts/PowerShell/New-HCIBoxCluster.ps1 などでも、冒頭で Import-PowerShellDataFile している。

New-HCIBoxCluster.ps1
# Import Configuration data file
$HCIBoxConfig = Import-PowerShellDataFile -Path $Env:HCIBoxConfigFile

/azure_arc/azure_jumpstart_hcibox/artifacts/PowerShell/New-HCIBoxCluster.ps1

ここでもろもろをセットアップする。

HCIBox の VHD をダウンロードする箇所があるんだが、ここがめちゃくちゃ時間がかかるので enableAcceleratedNetworking を使って少しでも高速化している。

New-HCIBoxCluster.ps1
# Download HCIBox VHDs
Write-Host "[Build cluster - Step 1/11] Downloading HCIBox VHDs" -ForegroundColor Green
BITSRequest -Params @{'Uri'='https://aka.ms/VHD-HCIBox-HCI-Prod'; 'Filename'="$($HCIBoxConfig.Paths.VHDDir)\AZSHCI.vhdx" }
BITSRequest -Params @{'Uri'='https://aka.ms/VHDHash-HCIBox-HCI-Prod'; 'Filename'="$($HCIBoxConfig.Paths.VHDDir)\AZSHCI.sha256" }

New-HCINodeVMSet-HCINodeVHDX などの function の内容をもとに、Azure Stack HCI を Hyper-V VM として構築する につながっている。
Install-WindowsFeature -Name Failover-Clustering -IncludeAllSubFeature -IncludeManagementTools が足りなさそう、とか。
Hyper-V VM を起動せず、VHDX ファイルに対して直接インストールする?みたいな動作は全く知らなかったので面白い。

GenerateAnswerFile がとても重要な function なんだが、unattend.xml を使うので黒魔術感がすごい。
詳しくは 応答ファイル (unattend.xml) などを参照ください。
なんとなく、IP アドレスの設定とか、パスワードの設定とか、いろんな設定を XML から流し込めるっぽい。

<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">
    <UserAccounts>
        <AdministratorPassword>
            <PlainText>false</PlainText>
            <Value>$encodedPassword</Value>
        </AdministratorPassword>
    </UserAccounts>
    <TimeZone>UTC</TimeZone>
    <OOBE>
        <HideEULAPage>true</HideEULAPage>
        <SkipUserOOBE>true</SkipUserOOBE>
        <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
        <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
        <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
        <NetworkLocation>Work</NetworkLocation>
        <ProtectYourPC>1</ProtectYourPC>
        <HideLocalAccountScreen>true</HideLocalAccountScreen>
    </OOBE>
</component>

はネットワーク関連っぽいな、とか。

<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">
    <UserAccounts>
        <AdministratorPassword>
            <PlainText>false</PlainText>
            <Value>$encodedPassword</Value>
        </AdministratorPassword>
    </UserAccounts>
    <TimeZone>UTC</TimeZone>
    <OOBE>
        <HideEULAPage>true</HideEULAPage>
        <SkipUserOOBE>true</SkipUserOOBE>
        <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
        <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
        <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
        <NetworkLocation>Work</NetworkLocation>
        <ProtectYourPC>1</ProtectYourPC>
        <HideLocalAccountScreen>true</HideLocalAccountScreen>
    </OOBE>
</component>

はパスワード設定してるっぽいな、とか。

まとめ

Jumpstart HCIBox を触ってみたいけどなんか高いので工夫してみた、という記事でした。
触っていく中で、構造も少しわかってきたので、メモとして残しておきます。

参考

  • Jumpstart HCIBox

https://azurearcjumpstart.io/azure_jumpstart_hcibox

  • Azure Stack HCI のラボ (Jumpstart HCIBox 23H2) を展開してみよう

https://zenn.dev/uedait/articles/azshci-23h2-hcibox

  • Azure Stack HCI を Hyper-V VM として構築する

https://zenn.dev/skmkzyk/articles/azshci-on-hyper-v

  • MS-01 はいいぞ!

https://zenn.dev/skmkzyk/articles/ms-01-must-buy

  • 応答ファイル (unattend.xml)

https://learn.microsoft.com/windows-hardware/manufacture/desktop/update-windows-settings-and-scripts-create-your-own-answer-file-sxs

Discussion