Установка ОС в виртуальной машине из ISO-образа

Рассмотрим пример установки ОС из ISO-образа ОС Windows. Для этого загрузите и опубликуйте его на каком-либо HTTP-сервисе, доступном из кластера.

  1. Создайте пустой диск для установки ОС:

    1 apiVersion: virtualization.deckhouse.io/v1alpha2
    2 kind: VirtualDisk
    3 metadata:
    4   name: win-disk
    5   namespace: default
    6 spec:
    7   persistentVolumeClaim:
    8     size: 100Gi
    9     storageClassName: local-path
    
  2. Создайте ресурсы с ISO-образами ОС Windows и драйверами virtio:

    1 apiVersion: virtualization.deckhouse.io/v1alpha2
    2 kind: ClusterVirtualImage
    3 metadata:
    4   name: win-11-iso
    5 spec:
    6   dataSource:
    7     type: HTTP
    8     http:
    9       url: "http://example.com/win11.iso"
    
    1 apiVersion: virtualization.deckhouse.io/v1alpha2
    2 kind: ClusterVirtualImage
    3 metadata:
    4   name: win-virtio-iso
    5 spec:
    6   dataSource:
    7     type: HTTP
    8     http:
    9       url: "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso"
    
  3. Создайте виртуальную машину:

    1 apiVersion: virtualization.deckhouse.io/v1alpha2
    2 kind: VirtualMachine
    3 metadata:
    4   name: win-vm
    5   namespace: default
    6   labels:
    7     vm: win
    8 spec:
    9   virtualMachineClassName: generic
    10   runPolicy: Manual
    11   osType: Windows
    12   bootloader: EFI
    13   cpu:
    14     cores: 6
    15     coreFraction: 50%
    16   memory:
    17     size: 8Gi
    18   enableParavirtualization: true
    19   blockDeviceRefs:
    20     - kind: VirtualDisk
    21       name: win-disk
    22     - kind: ClusterVirtualImage
    23       name: win-11-iso
    24     - kind: ClusterVirtualImage
    25       name: win-virtio-iso
    
  4. После создания ресурса запустите ВМ:

    1 d8 v vnc -n default win-vm
    
  5. К ней необходимо подключиться и с помощью графического установщика и выполнить установку ОС и драйверов virtio:

    1d8 v vnc -n default win-vm
    
  6. После окончания установки перезагрузите виртуальную машину.

  7. Для продолжения работы с виртуальной машиной также используйте команду:

    1d8 v vnc -n default win-vm
    

Предоставление файла ответов Windows (Sysprep)

Чтобы выполнить автоматическую установку Windows, создайте файл ответов (обычно именуются unattend.xml или autounattend.xml). Для примера возьмем файл, позволяющий:

  • Добавить русский язык и раскладку;
  • Указать расположение virtio драйверов, необходимых для установки (поэтому важен порядок дисковых устройств в спецификации ВМ);
  • Разметить диски для установки Windows на ВМ c EFI;
  • Создать в группе администраторов пользователя cloud с паролем cloud;
  • Создать непривилегированного пользователя user с паролем user.

autounattend.xml

1<?xml version="1.0" encoding="utf-8"?>
2<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
3  <settings pass="offlineServicing"></settings>
4  <settings pass="windowsPE">
5    <component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
6      <SetupUILanguage>
7        <UILanguage>ru-RU</UILanguage>
8      </SetupUILanguage>
9      <InputLocale>0409:00000409;0419:00000419</InputLocale>
10      <SystemLocale>en-US</SystemLocale>
11      <UILanguage>ru-RU</UILanguage>
12      <UserLocale>en-US</UserLocale>
13    </component>
14    <component name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
15      <DriverPaths>
16        <PathAndCredentials wcm:keyValue="4b29ba63" wcm:action="add">
17          <Path>E:\amd64\w11</Path>
18        </PathAndCredentials>
19        <PathAndCredentials wcm:keyValue="25fe51ea" wcm:action="add">
20          <Path>E:\NetKVM\w11\amd64</Path>
21        </PathAndCredentials>
22      </DriverPaths>
23    </component>
24    <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
25      <DiskConfiguration>
26        <Disk wcm:action="add">
27          <DiskID>0</DiskID>
28          <WillWipeDisk>true</WillWipeDisk>
29          <CreatePartitions>
30            <!-- Recovery partition -->
31            <CreatePartition wcm:action="add">
32              <Order>1</Order>
33              <Type>Primary</Type>
34              <Size>250</Size>
35            </CreatePartition>
36            <!-- EFI system partition (ESP) -->
37            <CreatePartition wcm:action="add">
38              <Order>2</Order>
39              <Type>EFI</Type>
40              <Size>100</Size>
41            </CreatePartition>
42            <!-- Microsoft reserved partition (MSR) -->
43            <CreatePartition wcm:action="add">
44              <Order>3</Order>
45              <Type>MSR</Type>
46              <Size>128</Size>
47            </CreatePartition>
48            <!-- Windows partition -->
49            <CreatePartition wcm:action="add">
50              <Order>4</Order>
51              <Type>Primary</Type>
52              <Extend>true</Extend>
53            </CreatePartition>
54          </CreatePartitions>
55          <ModifyPartitions>
56            <!-- Recovery partition -->
57            <ModifyPartition wcm:action="add">
58              <Order>1</Order>
59              <PartitionID>1</PartitionID>
60              <Label>Recovery</Label>
61              <Format>NTFS</Format>
62              <TypeID>de94bba4-06d1-4d40-a16a-bfd50179d6ac</TypeID>
63            </ModifyPartition>
64            <!-- EFI system partition (ESP) -->
65            <ModifyPartition wcm:action="add">
66              <Order>2</Order>
67              <PartitionID>2</PartitionID>
68              <Label>System</Label>
69              <Format>FAT32</Format>
70            </ModifyPartition>
71            <!-- MSR partition does not need to be modified -->
72            <!-- Windows partition -->
73            <ModifyPartition wcm:action="add">
74              <Order>3</Order>
75              <PartitionID>4</PartitionID>
76              <Label>Windows</Label>
77              <Letter>C</Letter>
78              <Format>NTFS</Format>
79            </ModifyPartition>
80          </ModifyPartitions>
81        </Disk>
82        <WillShowUI>OnError</WillShowUI>
83      </DiskConfiguration>
84      <ImageInstall>
85        <OSImage>
86          <InstallTo>
87            <DiskID>0</DiskID>
88            <PartitionID>4</PartitionID>
89          </InstallTo>
90        </OSImage>
91      </ImageInstall>
92      <UserData>
93        <ProductKey>
94          <Key>VK7JG-NPHTM-C97JM-9MPGT-3V66T</Key>
95          <WillShowUI>OnError</WillShowUI>
96        </ProductKey>
97        <AcceptEula>true</AcceptEula>
98      </UserData>
99      <UseConfigurationSet>false</UseConfigurationSet>
100    </component>
101  </settings>
102  <settings pass="generalize"></settings>
103  <settings pass="specialize">
104    <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
105      <RunSynchronous>
106        <RunSynchronousCommand wcm:action="add">
107          <Order>1</Order>
108          <Path>powershell.exe -NoProfile -Command "$xml = [xml]::new(); $xml.Load('C:\Windows\Panther\unattend.xml'); $sb = [scriptblock]::Create( $xml.unattend.Extensions.ExtractScript ); Invoke-Command -ScriptBlock $sb -ArgumentList $xml;"</Path>
109        </RunSynchronousCommand>
110        <RunSynchronousCommand wcm:action="add">
111          <Order>2</Order>
112          <Path>powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\Specialize.ps1' -Raw | Invoke-Expression;"</Path>
113        </RunSynchronousCommand>
114        <RunSynchronousCommand wcm:action="add">
115          <Order>3</Order>
116          <Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
117        </RunSynchronousCommand>
118        <RunSynchronousCommand wcm:action="add">
119          <Order>4</Order>
120          <Path>powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\DefaultUser.ps1' -Raw | Invoke-Expression;"</Path>
121        </RunSynchronousCommand>
122        <RunSynchronousCommand wcm:action="add">
123          <Order>5</Order>
124          <Path>reg.exe unload "HKU\DefaultUser"</Path>
125        </RunSynchronousCommand>
126      </RunSynchronous>
127    </component>
128  </settings>
129  <settings pass="auditSystem"></settings>
130  <settings pass="auditUser"></settings>
131  <settings pass="oobeSystem">
132    <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
133      <InputLocale>0409:00000409;0419:00000419</InputLocale>
134      <SystemLocale>en-US</SystemLocale>
135      <UILanguage>ru-RU</UILanguage>
136      <UserLocale>en-US</UserLocale>
137    </component>
138    <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
139      <UserAccounts>
140        <LocalAccounts>
141          <LocalAccount wcm:action="add">
142            <Name>cloud</Name>
143            <DisplayName>cloud</DisplayName>
144            <Group>Administrators</Group>
145            <Password>
146              <Value>cloud</Value>
147              <PlainText>true</PlainText>
148            </Password>
149          </LocalAccount>
150          <LocalAccount wcm:action="add">
151            <Name>User</Name>
152            <DisplayName>user</DisplayName>
153            <Group>Users</Group>
154            <Password>
155              <Value>user</Value>
156              <PlainText>true</PlainText>
157            </Password>
158          </LocalAccount>
159        </LocalAccounts>
160      </UserAccounts>
161      <AutoLogon>
162        <Username>cloud</Username>
163        <Enabled>true</Enabled>
164        <LogonCount>1</LogonCount>
165        <Password>
166          <Value>cloud</Value>
167          <PlainText>true</PlainText>
168        </Password>
169      </AutoLogon>
170      <OOBE>
171        <ProtectYourPC>3</ProtectYourPC>
172        <HideEULAPage>true</HideEULAPage>
173        <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
174        <HideOnlineAccountScreens>false</HideOnlineAccountScreens>
175      </OOBE>
176      <FirstLogonCommands>
177        <SynchronousCommand wcm:action="add">
178          <Order>1</Order>
179          <CommandLine>powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\FirstLogon.ps1' -Raw | Invoke-Expression;"</CommandLine>
180        </SynchronousCommand>
181      </FirstLogonCommands>
182    </component>
183  </settings>
184</unattend>

Создайте секрет из этого xml файла:

1d8 k create secret generic sysprep-config --type="provisioning.virtualization.deckhouse.io/sysprep" --from-file=./autounattend.xml

Затем можно создать виртуальную машину, которая в процессе установки будет использовать файл ответов. Чтобы предоставить виртуальной машине Windows файл ответов, необходимо указать provisioning с типом SysprepRef. Вы также можете указать здесь другие файлы в формате base64 (customize.ps1, id_rsa.pub,…), необходимые для успешного выполнения скриптов внутри файла ответов.

1apiVersion: virtualization.deckhouse.io/v1alpha2
2kind: VirtualMachine
3metadata:
4  name: win-vm
5  namespace: default
6  labels:
7    vm: win
8spec:
9  virtualMachineClassName: generic
10  provisioning:
11    type: SysprepRef
12    sysprepRef:
13      kind: Secret
14      name: sysprep-config
15  runPolicy: AlwaysOn
16  osType: Windows
17  bootloader: EFI
18  cpu:
19    cores: 6
20    coreFraction: 50%
21  memory:
22    size: 8Gi
23  enableParavirtualization: true
24  blockDeviceRefs:
25    - kind: VirtualDisk
26      name: win-disk
27    - kind: ClusterVirtualImage
28      name: win-11-iso
29    - kind: ClusterVirtualImage
30      name: win-virtio-iso

Перенаправление трафика на виртуальную машину

Виртуальная машина функционирует в кластере Kubernetes, поэтому направление сетевого трафика осуществляется аналогично направлению трафика на поды.

В качестве примера приведена виртуальная машина с HTTP-сервисом, опубликованным на порте 80, и следующим набором меток:

  1. Создайте сервис с требуемыми настройками. В качестве примера приведена виртуальная машина с HTTP-сервисом, опубликованным на порте 80, и следующим набором меток:

    1 apiVersion: virtualization.deckhouse.io/v1alpha2
    2 kind: VirtualMachine
    3 metadata:
    4   name: web
    5   labels:
    6     vm: web
    7 spec: ...
    
  2. Чтобы направить сетевой трафик на 80-й порт виртуальной машины, создайте сервис:

    1 apiVersion: v1
    2 kind: Service
    3 metadata:
    4   name: svc-1
    5 spec:
    6   ports:
    7     - name: http
    8       port: 8080
    9       protocol: TCP
    10       targetPort: 80
    11   selector:
    12     app: old
    

Изменение меток виртуальной машины без необходимости перезапуска

Можно изменять метки виртуальной машины без необходимости перезапуска, что позволяет настраивать перенаправление сетевого трафика между различными сервисами в реальном времени.

Предположим, что был создан новый сервис и требуется перенаправить трафик на виртуальную машину от этого сервиса:

1apiVersion: v1
2kind: Service
3metadata:
4  name: svc-2
5spec:
6  ports:
7    - name: http
8      port: 8080
9      protocol: TCP
10      targetPort: 80
11  selector:
12    app: new

При изменении метки на виртуальной машине, трафик с сервиса svc-2 будет перенаправлен на виртуальную машину:

1metadata:
2labels:
3  app: old