На странице представлены часто задаваемые вопросы по настройке и использованию Deckhouse Platform.
Дополнительные материалы и разбор типовых сценариев администрирования представлены в курсе «Администрирование Deckhouse Platform» в Deckhouse Академии.
Общее
Как принудительно обновить модуль?
Чтобы принудительно применить обновление конкретного модуля, установите аннотацию modules.deckhouse.io/apply-now: "true" в соответствующем ресурсе ModuleRelease.
Аннотация применяет релиз немедленно, не дожидаясь окна обновлений. Требования из spec.requirements при этом сохраняются — если они не выполняются, релиз не будет применен.
Пример установки аннотации для модуля console:
d8 k annotate mr console-v1.43.3 modules.deckhouse.io/apply-now="true"
Для удобства это можно сделать с помощью d8 CLI (имена модулей и версии автодополняются):
d8 system module apply-now console v1.43.3
Пример ресурса с установленной аннотацией:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleRelease
metadata:
name: console-v1.43.3
annotations:
modules.deckhouse.io/apply-now: "true"
...
Как применить обновление DP, минуя окна обновлений, canary-release и ручной режим обновлений?
Чтобы применить обновление DP немедленно, установите в соответствующем ресурсе DeckhouseRelease аннотацию release.deckhouse.io/apply-now: "true".
В этом случае будут проигнорированы окна обновления, настройки canary-release и режим ручного обновления кластера. Обновление применится сразу после установки аннотации.
Пример команды установки аннотации пропуска окон обновлений для версии v1.56.2:
d8 k annotate deckhousereleases v1.56.2 release.deckhouse.io/apply-now="true"
Пример ресурса с установленной аннотацией пропуска окон обновлений:
apiVersion: deckhouse.io/v1alpha1
kind: DeckhouseRelease
metadata:
annotations:
release.deckhouse.io/apply-now: "true"
...
Что делать, если при включенном VPN контейнер с установщиком не может получить доступ к сети?
Если на компьютере, с которого выполняется bootstrap кластера, включен VPN, контейнер с установщиком (включая графический инсталлятор) может потерять доступ к сети. Из-за этого, например, веб-интерфейс графического инсталлятора может не открываться в браузере.
Решить проблему можно одним из следующих способов:
- Отключите VPN на компьютере и перезапустите контейнер с установщиком.
-
Если отключить VPN нельзя (например, bootstrap кластера выполняется в сети VPN), используйте при запуске контейнера с установщиком параметр
--network host(для Docker Desktop на Mac OS параметр доступен, начиная с версии 4.34.0). Это позволит контейнеру получить доступ к сети.Пример запуска контейнера с установщиком при включённом VPN, с использованием параметра
--network host:docker run --network host --pull=always -it -v "$PWD/config.yml:/config.yml" -v "$HOME/.ssh/:/tmp/.ssh/" -v "$PWD/dhctl-tmp:/tmp/dhctl" registry.deckhouse.ru/deckhouse/ce/install:early-access bashПример запуска графического инсталлятора при включённом VPN, с использованием параметра
--network host:docker run --network host --rm --pull always -v $HOME/.d8installer:$HOME/.d8installer -v /var/run/docker.sock:/var/run/docker.sock -p 127.0.0.1:8080:8080 registry.deckhouse.ru/deckhouse/installer:latest -r $HOME/.d8installer
Как сменить канал обновлений для модуля?
Модуль может быть встроенным в DP или подключенным из источника модулей (определяется с помощью ModuleSource). Встроенные модули имеют общий с DP релизный цикл и обновляются вместе с DP. Канал обновлений встроенного модуля всегда соответствует каналу обновлений DP. Модуль, подключаемый из источника, имеет собственный релизный цикл, который не зависит от релизного цикла DP. Канал обновлений модуля, подключенного из источника, может быть изменен.
Далее рассматривается процесс смены канала обновлений для модуля, подключенного из источника.
По умолчанию канал обновлений для модулей наследуется от канала обновлений DP (указывается в параметре releaseChannel ModuleConfig deckhouse). Подробнее про каналы обновлений — в разделе «Каналы обновлений».
Для модулей из источника канал обновлений задается с помощью ModuleUpdatePolicy, который затем привязывается к модулю через параметр updatePolicy в ModuleConfig.
Чтобы сменить канал обновлений у модуля из источника, выполните следующие шаги:
-
Определите политику обновления модуля.
Создайте ModuleUpdatePolicy, в котором укажите канал обновлений в параметре
releaseChannel.Пример ModuleUpdatePolicy:
apiVersion: deckhouse.io/v1alpha2 kind: ModuleUpdatePolicy metadata: name: my-module-policy spec: releaseChannel: Alpha update: mode: AutoПри необходимости измените режим обновления и настройте окна обновлений.
Убедитесь, что политика создана:
d8 k get mup my-module-policyПример ответа:
NAME RELEASE CHANNEL UPDATE MODE my-module-policy Alpha AutoPatch -
Свяжите политику обновления с модулем.
Укажите имя созданной политики обновления в параметре updatePolicy ModuleConfig соответствующего модуля.
Для редактирования ModuleConfig используйте команду (укажите имя модуля):
d8 k edit mc my-moduleПример ModuleConfig:
apiVersion: deckhouse.io/v1alpha1 kind: ModuleConfig metadata: name: my-module spec: enabled: true # Имя ModuleUpdatePolicy. updatePolicy: my-module-policy
При изменении канала обновлений модуля, его установленная версия изменится согласно настроенному режиму обновления.
Чтобы посмотреть текущий канал обновлений модуля и другую информацию о его состоянии в кластере, используйте соответствующий объект Module.
Пример команды для получения информации о модуле:
d8 k get module my-module -o yaml
Используемая политика обновления будет указана в поле properties.updatePolicy, текущий канал обновлений — в поле properties.releaseChannel. Пример вывода:
apiVersion: deckhouse.io/v1alpha1
kind: Module
metadata:
name: my-module
# ...
properties:
# ...
releaseChannel: Alpha # Канал обновлений модуля.
updatePolicy: my-module-policy # Политика обновлений модуля.
version: v1.16.10 # Версия модуля.
# ...
Как сделать так, чтобы внешний модуль обновлялся только на патч-версии?
По умолчанию, если у модуля нет собственной политики обновления, режим обновления и окна наследуются из настроек DP.
Если для DP задан режим AutoPatch, внешний модуль тоже будет автоматически получать только патч-версии в рамках текущей минорной версии. Переход на новую минорную версию потребует ручного подтверждения. В этом случае отдельно ничего настраивать не нужно.
Подробнее о режимах обновления DP — в разделе «Настройка обновлений».
Если нужно управлять режимом обновления модуля независимо от DP, создайте ModuleUpdatePolicy с update.mode: AutoPatch и привяжите её к модулю через параметр updatePolicy в ModuleConfig:
-
Создайте политику обновления.
Пример ModuleUpdatePolicy:
apiVersion: deckhouse.io/v1alpha2 kind: ModuleUpdatePolicy metadata: name: my-update-policy spec: releaseChannel: Stable update: mode: AutoPatchУбедитесь, что политика создана:
d8 k get mup my-update-policy -
Свяжите политику с модулем.
Укажите имя политики в параметре updatePolicy ModuleConfig модуля:
d8 k edit mc moduleПример ModuleConfig:
apiVersion: deckhouse.io/v1alpha1 kind: ModuleConfig metadata: name: module spec: enabled: true updatePolicy: my-update-policy
В режиме AutoPatch патч-версии модуля (например, с v1.16.1 на v1.16.2) применяются автоматически с учётом окон обновлений, если они заданы. Для перехода на новую минорную версию (например, с v1.16.* на v1.17.*) подтвердите соответствующий ModuleRelease:
d8 k annotate mr module-v1.17.0 modules.deckhouse.io/approved="true"
Или с помощью d8 CLI:
d8 system module approve module v1.17.0
Что делать, если образ модуля не скачался и модуль не переустановился?
В некоторых случаях может возникнуть проблема с автоматическим скачиванием образа и переустановкой модуля. Среди этих случаев:
- Повреждение файловой системы или другие проблемы, из-за которых образ модуля стал невалидным.
- Переключение на использование другого хранилища образов.
- Переключение с одной редакции DP на другую.
При этом модуль может находиться в статусе Ready. А ошибка возникает в подах модуля. Чтобы найти проблемный под используйте команду:
d8 k -n d8-<module-name> get pods
У проблемного пода будет статус, отличающийся от Running.
Для просмотра информации о поде используйте команду:
d8 k -n d8-<module-name> describe pod <pod-name>
Пример сообщения об ошибке в поде при проблеме со скачиванием образа и переустановкой модуля:
Failed to pull image "registry.deckhouse.ru/deckhouse/ce/modules/console@sha256:a12b4f8de1d997005155d0ba0a7c968a015dd8d18bb5d54645ddb040ddab1ef4": rpc error: code = NotFound desc = failed to pull and unpack image "registry.deckhouse.ru/deckhouse/ce/modules/console@sha256:a12b4f8de1d997005155d0ba0a7c968a015dd8d18bb5d54645ddb040ddab1ef4": failed to resolve reference ...
Чтобы скачать образ и переустановить модуль, с которым возникла проблема:
-
Получите список релизов модуля:
d8 k get mr -l module=my-moduleПример вывода:
NAME PHASE UPDATE POLICY TRANSITIONTIME MESSAGE my-module-v3.7.4 Superseded 5d23h my-module-v3.7.5 Deployed 5d23hНайдите в списке релиз модуля, развернутый в кластере (он должен иметь статус
Deployed). -
Добавьте к развернутому релизу аннотацию
modules.deckhouse.io/reinstall=true:d8 k annotate mr my-module-v3.7.5 modules.deckhouse.io/reinstall=true
После добавления аннотации образ модуля заново скачивается из хранилища образов, модуль валидируется с текущими настройками из ModuleConfig и устанавливается в кластер. После успешной переустановки аннотация автоматически удаляется из ModuleRelease.
Чтобы убедиться, что переустановка модуля прошла успешно, и все поды работают, используйте команду:
d8 k -n d8-<module-name> get pods
Все поды модуля должны иметь статус Running. Пример:
NAME READY STATUS RESTARTS AGE
backend-567d6c6cdc-g5qgt 1/1 Running 0 2d2h
frontend-7c8b567759-h8jdf 1/1 Running 0 2d2h
observability-gw-86cf75f5d6-7xljh 1/1 Running 0 2d2h
Кластер и инфраструктура
Что делать в случае проблем с добавлением узла в кластер через Cluster API Provider Static?
Если при добавлении узла в кластер через Cluster API Provider Static (CAPS) он остается в статусе Pending или в Bootstrapping, выполните следующие действия:
-
Проверьте корректность ключей доступа, указанных в ресурсе SSHCredentials. Убедитесь, что имя пользователя и SSH-ключ, указанные в SSHCredentials, верны.
-
На узле, с добавлением которого возникла проблема, проверьте наличие в
authorized_keysпубличного ключа, соответствующего приватному из SSHCredentials. Пример команды для проверки:cat ~/.ssh/authorized_keys -
Проверьте количество узлов, указанное в NodeGroup, в которую должен входить добавляемый узел. Убедитесь, что не превышено максимальное количество узлов.
-
Проверьте статус службы
bashible.serviceна узле, с добавлением которого возникла проблема:systemctl status bashible.serviceОн должен быть в статусе
active (running). Если сервис находится в статусеinactiveилиfailed— служба не запустилась. Это указывает на проблему в процессе настройки. -
Если указанные выше шаги не помогли устранить проблему, удалите из кластера проблемный узел и его ресурс StaticInstance, чтобы система попыталась создать их заново. Для этого:
-
Получите список узлов и найдите в нем проблемный:
d8 k get nodes -
Найдите соответствующий ресурс StaticInstance:
d8 k get staticinstances -n <namespace-name> -
Удалите проблемный узел:
d8 k delete node <node-name> -
Удалите соответствующий ресурс StaticInstance:
d8 k delete staticinstances -n <namespace-name> <static-instance-name>
-
Как изменить тип инстанса у узлов с типом CloudPermanent?
Чтобы сменить тип инстанса у узлов с типом CloudPermanent, выполните следующие шаги:
- Сделайте резервную копию
etcdи папки/etc/kubernetes. - Скопируйте полученный архив за пределы кластера (например, на локальную машину).
- Убедитесь, что в кластере нет алертов, которые могут помешать обновлению master-узлов.
-
Убедитесь, что очередь Deckhouse пуста. Для просмотра состояния всех очередей заданий Deckhouse выполните следующую команду:
d8 s queue listПример вывода (очереди пусты):
Summary: - 'main' queue: empty. - 88 other queues (0 active, 88 empty): 0 tasks. - no tasks to handle. -
На локальной машине запустите контейнер установщика Deckhouse соответствующей редакции и версии (измените адрес container registry при необходимости):
DH_VERSION=$(d8 k -n d8-system get deployment deckhouse -o jsonpath='{.metadata.annotations.core\.deckhouse\.io\/version}') DH_EDITION=$(d8 k -n d8-system get deployment deckhouse -o jsonpath='{.metadata.annotations.core\.deckhouse\.io\/edition}' | tr '[:upper:]' '[:lower:]' ) docker run --pull=always -it -v "$HOME/.ssh/:/tmp/.ssh/" \ registry.deckhouse.ru/deckhouse/${DH_EDITION}/install:${DH_VERSION} bash -
В контейнере с инсталлятором выполните следующую команду, чтобы проверить состояние перед началом работы:
dhctl terraform check --ssh-agent-private-keys=/tmp/.ssh/<SSH_KEY_FILENAME> --ssh-user=<USERNAME> \ --ssh-host <MASTER-NODE-0-HOST> --ssh-host <MASTER-NODE-1-HOST> --ssh-host <MASTER-NODE-2-HOST>Ответ должен сообщить, что Terraform не нашел расхождений и изменений не требуется.
-
В контейнере с инсталлятором выполните команду для редактирования конфигурации кластера (укажите адреса всех master-узлов в параметре
--ssh-host):dhctl config edit provider-cluster-configuration --ssh-agent-private-keys=/tmp/.ssh/<SSH_KEY_FILENAME> --ssh-user=<USERNAME> \ --ssh-host <MASTER-NODE-0-HOST> --ssh-host <MASTER-NODE-1-HOST> --ssh-host <MASTER-NODE-2-HOST> -
Отредактируйте параметр
instanceClassнужной группы узлов, изменив тип инстанса, и сохраните изменения. Пример настроек дляmasterNodeGroupпровайдера Yandex Cloud:masterNodeGroup: replicas: 3 # требуемое количество master-узлов instanceClass: cores: 4 # изменить количество CPU memory: 8192 # изменить объем памяти (в MB) # другие параметры инстанса... externalIPAddresses: - "Auto" # для каждого master-узла - "Auto" - "Auto" -
В контейнере с инсталлятором выполните следующую команду, чтобы провести обновление узлов:
Внимательно изучите действия, которые планирует выполнить converge, когда запрашивает подтверждение.
При выполнении команды узлы будут заменены на новые с подтверждением на каждом узле. Замена будет выполняться по очереди в обратном порядке (2,1,0).
dhctl converge --ssh-agent-private-keys=/tmp/.ssh/<SSH_KEY_FILENAME> --ssh-user=<USERNAME> \ --ssh-host <MASTER-NODE-0-HOST> --ssh-host <MASTER-NODE-1-HOST> --ssh-host <MASTER-NODE-2-HOST>Следующие действия (п. 9-12) выполняйте поочередно на каждом master-узле, начиная с узла с наивысшим номером (с суффиксом 2) и заканчивая узлом с наименьшим номером (с суффиксом 0).
-
На созданном узле откройте журнал systemd-юнита
bashible.service. Дождитесь окончания настройки узла — в журнале должно появиться сообщениеnothing to do:journalctl -fu bashible.service -
Проверьте, что узел etcd отобразился в списке узлов кластера:
for pod in $(d8 k -n kube-system get pod -l component=etcd,tier=control-plane -o name); do d8 k -n kube-system exec "$pod" -- etcdctl --cacert /etc/kubernetes/pki/etcd/ca.crt \ --cert /etc/kubernetes/pki/etcd/ca.crt --key /etc/kubernetes/pki/etcd/ca.key \ --endpoints https://127.0.0.1:2379/ member list -w table if [ $? -eq 0 ]; then break fi done -
Убедитесь, что
control-plane-managerфункционирует на узле.d8 k -n kube-system wait pod --timeout=10m --for=condition=ContainersReady \ -l app=d8-control-plane-manager --field-selector spec.nodeName=<MASTER-NODE-N-NAME> - Перейдите к обновлению следующего узла.
Что делать, если переключение на заказ узлов в менее приоритетных группах занимает много времени?
При использовании в облачном кластере нескольких групп узлов с разными приоритетами (параметр spec.cloudInstances.priority) переключение на заказ узлов из групп с меньшим приоритетом может занимать много времени. Пример такого случая — когда для групп прерываемых узлов (spot, preemptible и т. д.) установлен наивысший приоритет и при недоступности таких инстансов заказ узлов из других групп происходит очень долго.
Для заказа узлов cluster autoscaler по очереди выбирает группу с наивысшим приоритетом, которая не находится в состоянии backoff. Backoff — это временная блокировка группы после неудачной попытки заказа узла (например, из-за отсутствия инстансов нужного типа в облаке).
Логика работы при использовании нескольких групп узлов:
- Cluster autoscaler пытается заказать узел в группе с наивысшим приоритетом.
- Если в течение времени, заданного в параметре
max-node-provision-time, узел не появился, попытка считается неудачной. - Группа помечается как
failedи блокируется на время, заданное в параметреinitial-node-group-backoff-duration. - При повторной неудаче для той же группы время блокировки удваивается, но не превышает время, заданное в параметре
max-node-group-backoff-duration. - Cluster autoscaler выбирает следующую по приоритету группу, которая не заблокирована.
Здесь:
| Параметр | Значение по умолчанию | Описание |
|---|---|---|
initial-node-group-backoff-duration |
5 минут | Начальная длительность блокировки группы после первой неудачи. Удваивается после каждой неудачной попытки заказа узла |
max-node-group-backoff-duration |
30 минут | Максимальная длительность блокировки группы |
max-node-provision-time |
15 минут | Время, после которого cluster autoscaler считает попытку заказа узла неудачной |
Если для этих параметров установлены значения по умолчанию, переключение на заказ узлов в менее приоритетных группах может занимать значительное время (подробнее — в примере).
Эти параметры можно изменять, чтобы ускорить переключение на заказ узлов в менее приоритетных группах.
Чтобы установить нужные значения для параметров initial-node-group-backoff-duration, max-node-group-backoff-duration и max-node-provision-time, отредактируйте объект Deployment cluster-autoscaler в неймспейсе d8-cloud-instance-manager. Параметры указываются в поле args контейнера cluster-autoscaler. Пример:
...
containers:
- name: cluster-autoscaler
args:
- --initial-node-group-backoff-duration=1m # Уменьшена начальная длительность блокировки группы после первой неудачи.
- --max-node-provision-time=5m # Уменьшено время, после которого cluster autoscaler считает попытку заказа узла неудачной.
...
Если в кластере с одной группой узлов возникают проблемы с заказом узлов
Если в облачном кластере используется только одна группа узлов (например, только для заказа прерываемых узлов (spot, preemptible)) и при автоматическом масштабировании возникают проблемы с заказом таких узлов, выполните следующие действия:
- Создайте один или несколько объектов InstanceClass, которые будут использоваться при создании инстансов в кластере. В InstanceClass укажите типы узлов, отличающиеся от указанных в упомянутой выше группе.
В DP объекты InstanceClass различаются в зависимости от провайдера. Примеры: AWSInstanceClass, AzureInstanceClass, YandexInstanceClass.
- Создайте одну или несколько новых групп узлов (объект NodeGroup). В параметре
spec.cloudInstances.classReferenceукажите созданные на предыдущем шаге объекты InstanceClass. В параметреspec.cloudInstances.priorityзадайте приоритет группы узлов. - При необходимости измените параметры
max-node-provision-time,max-node-group-backoff-durationиinitial-node-group-backoff-duration, чтобы ускорить переключение на менее приоритетные группы.
Пример процесса заказа узлов с настройками по умолчанию
Предположим, есть 3 группы узлов с разными приоритетами:
- группа A (приоритет 50);
- группа B (приоритет 30);
- группа C (приоритет 0).
В таком случае процесс заказа узлов может быть следующим:
| Время | Событие |
|---|---|
| 10:00 | Cluster autoscaler пытается заказать узел в A |
| 10:15 | Попытка заказа узла в A в течение 15 минут (max-node-provision-time) завершается неудачей → блокировка A на 5 минут (initial-node-group-backoff-duration) |
| 10:15:xx | Cluster autoscaler пытается заказать узел в B (следующая по приоритету, не заблокирована) |
| 10:30 | Попытка заказа узла в B в течение 15 минут (max-node-provision-time) завершается неудачей → блокировка B на 5 минут (initial-node-group-backoff-duration) |
| 10:30:xx | Cluster autoscaler снова пытается заказать узел в A, так как время блокировки (значение по умолчанию для initial-node-group-backoff-duration равно 5 минут) закончилось |
| 10:45 | Попытка заказа узла в A снова завершается неудачей → блокировка A на 10 минут (initial-node-group-backoff-duration для А удваивается) |
| … | И так далее, пока время блокировки A и B не превысит 15 минут (max-node-provision-time). До группы C в таком случае очередь может дойти только примерно через 1,5 часа |
Что делать, если после добавления объекта не создаются порождаемые им ресурсы?
Если после создания объекта в системе (например, dexAuthenticator) нужные ресурсы не появились, выполните следующие шаги:
-
Проверьте, есть ли в кластере критические алерты, которые могут блокировать создание нужных объектов. Для этого используйте команду:
d8 k get clusteralerts.deckhouse.ioПример вывода:
NAME ALERT SEVERITY AGE LAST RECEIVED STATUS 012f602592aa7a91 K8SSchedulerTargetDown 3 16h 54s firing 0836dc893d5ecc65 KubernetesDeploymentReplicasUnavailable 5 15h 62s firing 08742f87d62d0063 NTPDaemonOnNodeDoesNotSynchronizeTime 5 16h 46s firing 172cfd38d2f7fd19 D8DeckhouseQueueIsHung 7 12h 66s firing 1c5705daf731f5cf D8StrongholdNoActiveNodes 3 16h 55s firing 1d2c2f7d69f69f4b D8DeckhouseIsNotOnReleaseChannel 9 12h 53s firing 205a551243d795f3 D8LogShipperAgentNotScheduledInCluster 7 15h 63s firing 2e34039aa7a3018e D8NodeIsNotUpdating 9 12h 47s firing 31baf9a70d657275 D8StrongholdClusterNotHealthy 7 16h 55s firingПодробнее об алертах — в разделе «Список алертов».
-
Проверьте очередь заданий Deckhouse:
d8 s queue listПример вывода (очереди пусты):
Summary: - 'main' queue: empty. - 88 other queues (0 active, 88 empty): 0 tasks. - no tasks to handle.Если в очереди много необработанных или долго выполняющихся заданий, это может говорить о проблемах.
-
Проанализируйте логи и события DP:
-
Для просмотра логов в реальном времени используйте команду:
d8 k -n d8-system logs -f -l app=deckhouseПример вывода:
{"level":"info","logger":"addon-operator","msg":"ConvergeModules task for OperatorStartup in phase '', trigger is Operator-Startup","binding":"ConvergeModules","event.type":"OperatorStartup","queue":"main","task.flow":"start","task.id":"fde0eb3b-5c3e-4da6-a0d8-a52f8ae03428","time":"2025-11-26T08:29:33Z"} {"level":"warn","logger":"addon-operator.converge-modules","msg":"ConvergeModules: functional scheduler not finished","binding":"ConvergeModules","event.type":"OperatorStartup","queue":"main","task.id":"fde0eb3b-5c3e-4da6-a0d8-a52f8ae03428","time":"2025-11-26T08:29:33Z"}При анализе логов особое внимание обращайте на предупреждения (
WARNING) и сообщения об ошибках (ERROR). -
Для просмотра событий используйте команду:
d8 k -n d8-system get eventsПример вывода:
LAST SEEN TYPE REASON OBJECT MESSAGE 11m Warning Unhealthy pod/deckhouse-5886c9bd77-vgdbw Readiness probe failed: HTTP probe failed with statuscode: 500 7m22s Normal SuccessfulDelete replicaset/deckhouse-5886c9bd77 Deleted pod: deckhouse-5886c9bd77-vgdbw 7m20s Normal Scheduled pod/deckhouse-6bc5c4494-fwx6z Successfully assigned d8-system/deckhouse-6bc5c4494-fwx6z to sandbox1-master-0 7m20s Normal Pulling pod/deckhouse-6bc5c4494-fwx6z Pulling image "dev-registry.deckhouse.io/sys/deckhouse-oss@sha256:17ac07634e17422df52720264cddec3916ed6985a77782dc8a24fe5352290e6e"
При анализе событий особое внимание обращайте на те, у которых тип
Warning. -
Deckhouse
Как узнать версию DP на каждом из каналов обновлений?
Актуальная информация о версиях DP на разных каналах обновлений доступна на сайте releases.deckhouse.ru.
Как проверить очередь заданий в Deckhouse?
Как посмотреть состояние всех очередей заданий Deckhouse?
Для просмотра состояния всех очередей заданий Deckhouse выполните следующую команду:
d8 s queue list
Пример вывода (очереди пусты):
Summary:
- 'main' queue: empty.
- 88 other queues (0 active, 88 empty): 0 tasks.
- no tasks to handle.
Как посмотреть состояние очереди заданий main?
Для просмотра состояния очереди заданий main Deckhouse выполните следующую команду:
d8 s queue main
Пример вывода (в очереди main 38 заданий):
Queue 'main': length 38, status: 'run first task'
Пример вывода (очередь main пуста):
Queue 'main': length 0, status: 'waiting for task 0s'
Что делать, если DP не получает обновления из настроенного канала?
- Проверьте, что настроен нужный канал обновлений.
-
Проверьте корректность разрешения DNS-имени хранилища образов Deckhouse.
Получите и сравните IP-адреса хранилища образов Deckhouse (
registry.deckhouse.ru) на одном из узлов и в подеdeckhouse. Они должны совпадать.Пример получения IP-адреса хранилища образов Deckhouse на узле:
getent ahosts registry.deckhouse.ruПример вывода:
185.193.90.38 STREAM registry.deckhouse.ru 185.193.90.38 DGRAM 185.193.90.38 RAWПример получения IP-адреса хранилища образов Deckhouse в поде
deckhouse:d8 k -n d8-system exec -ti svc/deckhouse-leader -c deckhouse -- getent ahosts registry.deckhouse.ruПример вывода:
185.193.90.38 STREAM registry.deckhouse.ru 185.193.90.38 DGRAM registry.deckhouse.ruЕсли полученные IP-адреса не совпадают, проверьте настройки DNS на узле. В частности, обратите внимание на список доменов в параметре
searchфайла/etc/resolv.conf(он влияет на разрешение имен в подеdeckhouse). Если в параметреsearchфайла/etc/resolv.confуказан домен, в котором настроено разрешение wildcard-записей, это может привести к неверному разрешению IP-адреса хранилища образов Deckhouse (см. пример).
Пример настроек DNS, которые могут привести к ошибкам в разрешении IP-адреса хранилища образов DP
Далее описан пример, когда настройки DNS приводят к различному результату при разрешении имен на узле и в поде Kubernetes:
-
Пример файла
/etc/resolv.confна узле:nameserver 10.0.0.10 search company.myОбратите внимание, что по умолчанию на узле параметр
ndotравен 1 (options ndots:1). Но в подах Kubernetes параметрndotравен 5. Таким образом, логика разрешения DNS-имен, имеющих в имени 5 точек и менее, различается на узле и в поде. -
В DNS-зоне
company.myнастроено разрешение wildcard-записей*.company.myв адрес10.0.0.100. То есть любое DNS-имя в зонеcompany.my, для которого нет конкретной записи в DNS, разрешается в адрес10.0.0.100.
Тогда с учетом параметра search, указанного в файле /etc/resolv.conf, при обращении на адрес registry.deckhouse.ru на узле система попробует получить IP-адрес для имени registry.deckhouse.ru (так как считает его полностью определенным, учитывая настройку по умолчанию параметра options ndots:1).
При обращении же на адрес registry.deckhouse.ru из пода Kubernetes, учитывая параметры options ndots:5 (используется в Kubernetes по умолчанию) и search, система первоначально попробует получить IP-адрес для имени registry.deckhouse.ru.company.my. Имя registry.deckhouse.ru.company.my разрешится в IP-адрес 10.0.0.100, так как в DNS-зоне company.my настроено разрешение wildcard-записей *.company.my в адрес 10.0.0.100. В результате к хосту registry.deckhouse.ru будет невозможно подключиться и скачать информацию о доступных обновлениях Deckhouse.
Поддерживет ли Deckhouse установку на ОС c realtime (rt) и low-latency ядрами?
Deckhouse Platform может устанавливаться на ОС Linux с realtime (rt) и lowlatency ядрами без дополнительной настройки платформы. Работа DP с такими ядрами была проверена для DP EE начиная с версии v1.75.7 на следующих ОС и ядрах:
- CentOS 9 Stream, linux-5.14.0-706.el9.x86_64+rt
- RedOS 8, linux-6.12.85-1.red80.x86_64-rt
- Astra Linux 1.7.5, linux-5.15-lowlatency
Как узнать, что для кластера доступна новая версия DP?
Как только на установленном в кластере канале обновления появляется новая версия DP:
- Загорается алерт
DeckhouseReleaseIsWaitingManualApproval, если кластер использует ручной режим обновлений. - Появляется новый кастомный ресурс DeckhouseRelease. Используйте команду
d8 k get deckhousereleases, чтобы посмотреть список релизов. ЕслиDeckhouseReleaseновой версии находится в состоянииPending, указанная версия еще не установлена. Возможные причины, при которыхDeckhouseReleaseможет находиться вPending:- Установлен ручной режим обновлений.
- Установлен автоматический режим обновлений и настроены окна обновлений, интервал которых еще не наступил.
- Установлен автоматический режим обновлений, окна обновлений не настроены, но применение версии отложено на случайный период времени из-за механизма снижения нагрузки на репозиторий образов контейнеров. В поле
status.messageресурса DeckhouseRelease будет соответствующее сообщение. - Установлен параметр
update.notification.minimalNotificationTimeи заданный в нем интервал еще не прошел.
Как заранее получать информацию о предстоящем обновлении?
Получать заранее информацию об обновлении минорных версий DP на канале обновлений можно следующими способами:
- Настроить ручной режим обновлений. В этом случае при появлении новой версии на канале обновлений загорится алерт
DeckhouseReleaseIsWaitingManualApproval, и в кластере появится новый кастомный ресурс DeckhouseRelease. - Настроить автоматический режим обновлений и указать минимальное время в параметре
minimalNotificationTime, на которое будет отложено обновление. В этом случае при появлении новой версии на канале обновлений в кластере появится новый кастомный ресурс DeckhouseRelease. Если указать URL в параметреupdate.notification.webhook, через указанный вебхук будет отправлено уведомление об предстоящем обновлении.
Как понять, что обновление прошло успешно?
Если алерт DeckhouseUpdating перестал отображаться, это означает, что обновление завершено.
Также вы можете проверить состояние релизов DP в кластере, используя следующую команду:
d8 k get deckhouserelease
Пример вывода:
NAME PHASE TRANSITIONTIME MESSAGE
v1.46.8 Superseded 13d
v1.46.9 Superseded 11d
v1.47.0 Superseded 4h12m
v1.47.1 Deployed 4h12m
Статус Deployed говорит о том, что произошло переключение на соответствующую версию, но не гарантирует успешное завершение обновления.
Для проверки успешности обновления выведите состояние пода deckhouse:
d8 k -n d8-system get pods -l app=deckhouse
Пример вывода:
NAME READY STATUS RESTARTS AGE
deckhouse-7844b47bcd-qtbx9 1/1 Running 0 1d
- Если под находится в статусе
Runningи в колонкеREADYуказано1/1, это означает, что обновление завершилось успешно. - Если под находится в статусе
Running, но в колонкеREADYуказано0/1, это означает, что обновление еще не завершено. Если так продолжается более 20–30 минут, это может говорить о наличии проблем в работе DP. Необходима диагностика. - Если под не находится в статусе
Running, это может говорить о наличии проблем в работе DP. Необходима диагностика.
Если что-то пошло не так
-
Проверьте логи, используя следующую команду:
d8 k -n d8-system logs -f -l app=deckhouse | jq -Rr 'fromjson? | .msg' -
Соберите отладочную информацию и свяжитесь с технической поддержкой DP.
Как понять, что в кластере идет обновление?
Во время обновления:
- отображается алерт
DeckhouseUpdating; - под
deckhouseнаходится не в статусеReady. Если под долго не переходит в статусReady, это может говорить о наличии проблем в работе DP. Необходима диагностика.
Что делать при наличии проблем с обновлением DP?
Обновление Deckhouse Platform не проходит, один или несколько подов Deckhouse в нерабочем состоянии
Если обновление Deckhouse Platform не проходит, один или несколько подов Deckhouse в неймспейсе d8-system находятся в нерабочем состоянии, выполните следующие действия:
-
Проверьте логи Deckhouse с помощью команды:
d8 k -n d8-system logs -f -l app=deckhouse | jq -Rr 'fromjson? | .msg'При наличии проблем информация о них будет в выводе. При анализе логов особое внимание обращайте на предупреждения (
WARNING) и сообщения об ошибках (ERROR). -
Проверьте события подов Deckhouse с помощью команды:
d8 k -n d8-system describe po -l app=deckhouse | awk ' /^Name:/ { pod = $2; print "=== " pod " ==="; in_events = 0 } /Events:/ { in_events = 1; next } in_events && /^$/ { in_events = 0; print "---" } in_events && !/^Events:/ { print $0 } ' | sed '/^---$/N;/^\n$/D'В событиях подов содержится ключевая информация о проблемах (например, об ошибках планирования, загрузки образов и т.д.). При анализе событий особое внимание обращайте на те, у которых тип
Warning.Пример вывода:
Type Reason Age From Message ---- ------ ---- ---- ------- Warning Unhealthy 4m44s (x1918 over 154m) kubelet Readiness probe failed: HTTP probe failed with statuscode: 500
Обновление DP находится в статусе Release is suspended
Состояние релиза Release is suspended говорит о том, что он был отложен, и на данный момент недоступен (не рекомендуется) для установки. В таком случае предлагается оставаться на последнем доступном релизе, либо на установленном в данный момент (он будет иметь статус Deployed).
Для просмотра списка релизов используйте команду:
d8 k get deckhousereleases.deckhouse.io
Пример вывода:
NAME PHASE TRANSITIONTIME MESSAGE
v1.69.13 Skipped 3h46m
v1.69.14 Skipped 3h46m
v1.69.15 Skipped 3h46m
v1.69.16 Superseded 160m
v1.70.12 Suspended 49d Release is suspended
v1.70.13 Skipped 36d
v1.70.14 Skipped 34d
v1.70.15 Skipped 28d
v1.70.16 Skipped 19d
v1.70.17 Deployed 160m
v1.71.3 Suspended 14d Release is suspended
Идентификация и доступ
Что делать при проблемах с применением настроек DexProvider?
Если вы изменили настройки DexProvider в модуле user-authn и при этом наблюдается одна из следующих проблем:
- не видно никаких изменений (настройки не применяются);
- при попытке входа в веб-интерфейс платформы с любым типом авторизации возникает ошибка
500 Internal Server Errorбез подробного описания.
Выполните следующие действия:
-
Проверьте статус подов деплоймента dex:
d8 k -n d8-user-authn get podПример вывода:
NAME READY STATUS RESTARTS AGE dex-5ddb779b7d-6pbhs 2/2 Running 0 20h kubeconfig-generator-7c46977b9f-5kdmc 1/1 Running 0 20hЕсли модуль работает нормально и в DexProvider указана корректная конфигурация, все поды будут в статусе
Running. -
Посмотрите логи проблемного пода:
d8 k -n d8-user-authn logs dex-<pod-name>На основе информации из логов исправьте конфигурацию в ресурсе DexProvider и дождитесь перезапуска подов dex. В течение нескольких минут поды перезапустятся автоматически, а веб-интерфейс платформы (находится по адресу
console.<ШАБЛОН_ИМЕН_КЛАСТЕРА>) станет доступен и в нем отразятся внесенные изменения в ресурс DexProvider.
Kubernetes и планировщик
Что делать при высокой нагрузке на API-сервер?
О проблемах с нагрузкой и потреблением памяти API-сервером могут говорить следующие признаки:
kubectl (d8)долго отвечает или не отвечает совсем (команды выполняются медленно или не выполняются);- в кластере происходит пересоздание подов без явных причин.
При наличии этих признаков выполните следующие действия:
-
Проверьте потребление ресурсов подами API-сервера. Для этого используйте команду:
d8 k -n kube-system top po -l component=kube-apiserverОбратите внимание на потребление памяти (
MEMORY) иCPU.Пример вывода:
NAME CPU(cores) MEMORY(bytes) kube-apiserver-sandbox1-master-0 251m 1476Mi -
Проверьте метрики в Grafana.
Для просмотра метрик откройте дашборд «Home» → «Dashboards» → «Kubernetes Cluster» → «Control Plane Status». Изучите графики, связанные с API-сервером («Kube-apiserver CPU Usage», «Kube-apiserver Memory Usage», «Kube-apiserver latency» и т.д.).
-
Изучите аудит-логи API-сервера, чтобы выявить источник высокого потребления памяти. Одна из частых причин высокого потребления памяти — большое количество запросов.
Как проверить используемую версию Kubernetes?
Для проверки используемой версии Kubernetes выполните команду:
d8 k get nodes
Пример вывода:
NAME STATUS ROLES AGE VERSION
frontend-0 Ready frontend 118d v1.31.9
master-0 Ready control-plane,master 118d v1.31.9
master-1 Ready control-plane,master 118d v1.31.9
master-2 Ready control-plane,master 118d v1.31.9
system-0 Ready system 118d v1.31.9
system-1 Ready system 118d v1.31.9
worker-0 Ready worker 37d v1.31.9
worker-1 Ready worker 19d v1.31.9
Сеть
Поддерживается ли модуль ingress-nginx? Не помешает ли это пройти аудит PCI DSS?
Модуль ingress-nginx остаётся в сопровождении Deckhouse Platform на весь срок поддержки платформы и не зависит от статуса upstream-проекта. Команда Deckhouse отслеживает уязвимости в контроллере и связанных компонентах (NGINX, Lua-модули, базовые образы), поставляет исправления в релизах DP и обеспечивает план миграции на Gateway API.
Вендором, ответственным за поддержку, выступает «Флант». DP также проходит регулярную сертификацию ФСТЭК России. Вместе с регулярным сопровождением модуля и управлением уязвимостями это позволяет пройти аудит PCI DSS и соответствует ожиданиям к ответственности вендора за компонент платформы.
Виртуализация
Как автоматически сгенерировать inventory для Ansible?
Вместо ручного создания inventory-файла можно использовать команду d8 v ansible-inventory, которая автоматически генерирует инвентарь Ansible из виртуальных машин в указанном неймспейсе. Команда совместима с интерфейсом ansible inventory script.
Для использования команды d8 v ansible-inventory требуется версия d8 v0.27.0 или выше. Команда работает только для виртуальных машин, у которых подключена основная сеть кластера (Main).
В инвентарь попадают только машины в фазе Running, которым назначен IP-адрес. Имена хостов формируются в формате <VM_NAME>.<NAMESPACE> (например, frontend.demo-app).
-
При необходимости задайте переменные хоста через аннотации (например, пользователя для SSH):
d8 k -n demo-app annotate vm frontend vars.ansible.deckhouse.io/ansible_user="cloud" -
Запустите Ansible с динамически сформированным инвентарём:
ANSIBLE_INVENTORY_ENABLED=yaml ansible -m shell -a "uptime" all -i <(d8 v ansible-inventory -n demo-app -o yaml)
Конструкция <(...) необходима, потому что Ansible ожидает файл или скрипт в качестве источника списка хостов. Простое указание команды в кавычках не сработает, потому что Ansible попытается выполнить строку как скрипт. Конструкция <(...) передаёт вывод команды как файл, который Ansible может прочитать.
-
Либо сохраните инвентарь в файл и выполните проверку:
d8 v ansible-inventory --list -o yaml -n demo-app > inventory.yaml ansible -m shell -a "uptime" -i inventory.yaml all
Как использовать Ansible для конфигурирования виртуальных машин?
Ansible — инструмент автоматизации, который выполняет задачи на удалённых серверах по протоколу SSH. Ниже показано, как управлять с его помощью виртуальными машинами (ВМ) проекта demo-app.
В рамках примера предполагается, что:
- в неймспейсе
demo-appесть ВМfrontend; - в ВМ есть пользователь
cloudс доступом по SSH; - на машине, где запускается Ansible, приватный SSH-ключ хранится в файле
/home/user/.ssh/id_rsa.
-
Создайте файл
inventory.yaml:--- all: vars: ansible_ssh_common_args: '-o ProxyCommand="d8 v port-forward --stdio=true %h %p"' # Пользователь по умолчанию, для доступа по SSH. ansible_user: cloud # Путь к приватному ключу. ansible_ssh_private_key_file: /home/user/.ssh/id_rsa hosts: # Имя хоста в формате <VM_NAME>.<NAMESPACE>. frontend.demo-app: -
Проверьте значение
uptimeвиртуальной машины:ansible -m shell -a "uptime" -i inventory.yaml all # frontend.demo-app | CHANGED | rc=0 >> # 12:01:20 up 2 days, 4:59, 0 users, load average: 0.00, 0.00, 0.00
Если вы не хотите использовать файл inventory, передайте все параметры прямо в командной строке:
ansible -m shell -a "uptime" \
-i "frontend.demo-app," \
-e "ansible_ssh_common_args='-o ProxyCommand=\"d8 v port-forward --stdio=true %h %p\"'" \
-e "ansible_user=cloud" \
-e "ansible_ssh_private_key_file=/home/user/.ssh/id_rsa" \
all
Как использовать cloud-init для конфигурирования виртуальных машин?
Cloud-init применяется для первичной настройки гостевой ОС при первом запуске. Конфигурация задаётся в YAML и начинается с директивы #cloud-config.
Для образов, рассчитанных на cloud-init (в том числе официальных cloud-образов дистрибутивов), конфигурацию cloud-init нужно передать явно. Иначе на части дистрибутивов не поднимается сеть, и машина остаётся недоступной даже при подключённой основной сети (Main).
Кроме того, в cloud-образах по умолчанию отключён вход в систему. Добавьте SSH-ключи пользователю по умолчанию либо создайте нового пользователя с SSH-доступом, иначе к машине не подключиться.
Обновление и установка пакетов
Пример cloud-config для обновления системы и установки пакетов из списка:
#cloud-config
# Обновить списки пакетов.
package_update: true
# Обновить установленные пакеты до последних версий.
package_upgrade: true
# Список пакетов для установки.
packages:
- nginx
- curl
- htop
# Команды для выполнения после установки пакетов.
runcmd:
- systemctl enable --now nginx.service
Создание пользователя
Пример cloud-config для создания локального пользователя с паролем и SSH-ключом:
#cloud-config
# Список пользователей для создания.
users:
# Имя пользователя.
- name: cloud
# Хеш пароля.
passwd: "<PASSWORD_HASH>"
# Не блокировать учётную запись.
lock_passwd: false
# Права sudo без запроса пароля.
sudo: ALL=(ALL) NOPASSWD:ALL
# Оболочка по умолчанию.
shell: /bin/bash
# SSH-ключи для доступа.
ssh-authorized-keys:
- <SSH_PUBLIC_KEY>
# Разрешить аутентификацию по паролю через SSH.
ssh_pwauth: true
Чтобы получить хеш пароля для поля passwd, выполните команду:
mkpasswd --method=SHA-512 --rounds=4096
Создание файла с нужными правами
Пример cloud-config для создания файла с заданными правами доступа:
#cloud-config
# Список файлов для создания.
write_files:
# Путь к файлу.
- path: /opt/scripts/start.sh
# Содержимое файла.
content: |
#!/bin/bash
echo "Starting application"
# Владелец файла, пользователь и группа.
owner: cloud:cloud
# Права доступа в восьмеричном формате.
permissions: '0755'
Настройка диска и файловой системы
Пример cloud-config для разметки диска, создания файловой системы и монтирования:
#cloud-config
# Настройка разметки диска.
disk_setup:
# Устройство диска.
/dev/sdb:
# Тип таблицы разделов, gpt или mbr.
table_type: gpt
# Автоматически создать разделы.
layout: true
# Не перезаписывать существующие разделы.
overwrite: false
# Настройка файловых систем.
fs_setup:
# Метка файловой системы.
- label: data
# Тип файловой системы.
filesystem: ext4
# Устройство раздела.
device: /dev/sdb1
# Автоматически определить раздел.
partition: auto
# Монтирование файловых систем.
mounts:
# [устройство, точка_монтирования, тип_ФС, опции, dump, pass]
- ["/dev/sdb1", "/mnt/data", "ext4", "defaults", "0", "2"]
Настройка сетевых интерфейсов для дополнительных сетей
Настройки, описанные в этом разделе, применяются только для дополнительных сетей. Основная сеть (Main) настраивается автоматически через cloud-init и не требует ручной конфигурации.
Дополнительные сети настраиваются вручную через cloud-init. Конфигурационные файлы создаёт блок write_files, а применяет настройки блок runcmd.
Подключение дополнительных сетей к виртуальной машине описано в разделе «Дополнительные сетевые интерфейсы».
Ниже приведены примеры для распространённых способов настройки сети в гостевой ОС:
- systemd-networkd
- Netplan (Ubuntu)
- ifcfg (RHEL/CentOS)
- Alpine Linux
Пример cloud-config для дистрибутивов, использующих systemd-networkd (Debian, CoreOS и др.):
#cloud-config
write_files:
- path: /etc/systemd/network/10-eth1.network
content: |
[Match]
Name=eth1
[Network]
Address=192.168.1.10/24
Gateway=192.168.1.1
DNS=8.8.8.8
runcmd:
- systemctl restart systemd-networkd
Пример cloud-config для Ubuntu и других систем, использующих Netplan:
#cloud-config
write_files:
- path: /etc/netplan/99-custom.yaml
content: |
network:
version: 2
ethernets:
eth1:
addresses:
- 10.0.0.5/24
gateway4: 10.0.0.1
nameservers:
addresses: [8.8.8.8]
eth2:
dhcp4: true
runcmd:
- netplan apply
Пример cloud-config для RHEL-совместимых дистрибутивов, использующих схему ifcfg и NetworkManager:
#cloud-config
write_files:
- path: /etc/sysconfig/network-scripts/ifcfg-eth1
content: |
DEVICE=eth1
BOOTPROTO=none
ONBOOT=yes
IPADDR=192.168.1.10
PREFIX=24
GATEWAY=192.168.1.1
DNS1=8.8.8.8
runcmd:
- nmcli connection reload
- nmcli connection up eth1
Пример cloud-config для дистрибутивов, использующих традиционный формат /etc/network/interfaces (Alpine и аналоги):
#cloud-config
write_files:
- path: /etc/network/interfaces
append: true
content: |
auto eth1
iface eth1 inet static
address 192.168.1.10
netmask 255.255.255.0
gateway 192.168.1.1
runcmd:
- /etc/init.d/networking restart
Как увеличить размер DVCR?
Размер тома DVCR задаётся в ModuleConfig модуля virtualization (spec.settings.dvcr.storage.persistentVolumeClaim.size). Новое значение должно быть больше текущего.
-
Проверьте текущий размер DVCR:
d8 k get mc virtualization -o jsonpath='{.spec.settings.dvcr.storage.persistentVolumeClaim}'Пример вывода:
{"size":"58G","storageClass":"linstor-thick-data-r1"} -
Увеличьте
sizeчерезpatch(подставьте нужное значение):d8 k patch mc virtualization \ --type merge -p '{"spec": {"settings": {"dvcr": {"storage": {"persistentVolumeClaim": {"size":"59G"}}}}}}'Пример вывода:
moduleconfig.deckhouse.io/virtualization patched -
Убедитесь, что в ModuleConfig отображается новый размер:
d8 k get mc virtualization -o jsonpath='{.spec.settings.dvcr.storage.persistentVolumeClaim}'Пример вывода:
{"size":"59G","storageClass":"linstor-thick-data-r1"} -
Проверьте текущее состояние DVCR:
d8 k get pvc dvcr -n d8-virtualizationПример вывода:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE dvcr Bound pvc-6a6cedb8-1292-4440-b789-5cc9d15bbc6b 57617188Ki RWO linstor-thick-data-r1 7d
Как сменить StorageClass у DVCR, если PVC уже создан?
StorageClass хранилища DVCR можно сменить только пересозданием PVC. При этом теряются все ранее загруженные в DVCR образы, то есть существующие ресурсы ClusterVirtualImage и VirtualImage фактически перестают соответствовать данным в хранилище.
Поле spec.settings.dvcr.storage.persistentVolumeClaim.storageClassName в ModuleConfig модуля virtualization задаёт класс хранения тома хранилища образов виртуальных машин (DVCR). Пока в пространстве имён d8-virtualization существует PVC этого тома, изменить поле через API нельзя.
У уже созданного PVC в Kubernetes нельзя сменить storageClassName, а штатного переноса данных DVCR между классами хранения нет.
Чтобы сменить StorageClass у DVCR, выполните следующие шаги:
-
Остановите DVCR:
d8 k -n d8-virtualization scale deployment dvcr --replicas=0 -
Выведите список PVC в неймспейсе
d8-virtualizationи найдите PVC тома DVCR:d8 k get pvc -n d8-virtualization -
Удалите найденный PVC, подставив имя ресурса вместо
<PVC_NAME>. Если команда завершается ошибкой из-за недостаточных прав, выполните её от имениsystem:sudouser:d8 k --as system:sudouser -n d8-virtualization delete pvc/<PVC_NAME> -
Задайте новый StorageClass в ModuleConfig, подставив нужный класс вместо
<STORAGE_CLASS_NAME>:d8 k patch mc virtualization --type merge -p '{"spec":{"settings":{"dvcr":{"storage":{"persistentVolumeClaim":{"storageClassName":"<STORAGE_CLASS_NAME>"}}}}}}'Пример вывода:
moduleconfig.deckhouse.io/virtualization patched -
Запустите DVCR:
d8 k -n d8-virtualization scale deployment dvcr --replicas=1 -
Проверьте PVC:
d8 k get pvc -n d8-virtualizationПример вывода:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE dvcr Bound pvc-b43f2e33-32cc-435a-aa1d-b53df35b030a 100Gi RWO linstor-thin-r1-hdd <unset> 34s
Хранилище выбранного StorageClass должно быть доступно на узлах, где запускается DVCR, то есть на system-узлах либо на worker-узлах, если system-узлов в кластере нет.
Как установить ОС в виртуальной машине из ISO-образа?
Ниже приведён типовой сценарий установки гостевой ОС Windows из ISO-образа. Перед началом разместите ISO-образ на HTTP-ресурсе, доступном из кластера.
-
Создайте пустой VirtualDisk для установки ОС:
apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualDisk metadata: name: win-disk namespace: default spec: persistentVolumeClaim: size: 100Gi storageClassName: local-path -
Создайте ресурсы ClusterVirtualImage для ISO-образа ОС Windows и дистрибутива драйверов
VirtIO:apiVersion: virtualization.deckhouse.io/v1alpha2 kind: ClusterVirtualImage metadata: name: win-11-iso spec: dataSource: type: HTTP http: url: "http://example.com/win11.iso"apiVersion: virtualization.deckhouse.io/v1alpha2 kind: ClusterVirtualImage metadata: name: win-virtio-iso spec: dataSource: type: HTTP http: url: "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso" -
Создайте виртуальную машину (ВМ):
apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine metadata: name: win-vm namespace: default labels: vm: win spec: virtualMachineClassName: generic runPolicy: Manual osType: Windows bootloader: EFI cpu: cores: 6 coreFraction: 50% memory: size: 8Gi enableParavirtualization: true blockDeviceRefs: - kind: VirtualDisk name: win-disk - kind: ClusterVirtualImage name: win-11-iso - kind: ClusterVirtualImage name: win-virtio-iso -
Запустите виртуальную машину:
d8 v start win-vm -
Подключитесь к консоли ВМ и завершите установку ОС и драйверов
VirtIOпри помощи графического установщика.Подключение по VNC:
d8 v vnc -n default win-vm -
После завершения установки перезагрузите виртуальную машину.
-
Для дальнейшей работы снова подключитесь по VNC:
d8 v vnc -n default win-vm
Как создать golden image для Linux?
Golden image — это предварительно настроенный образ виртуальной машины (ВМ), который можно использовать для быстрого создания новых ВМ с уже установленным программным обеспечением и настройками.
-
Создайте виртуальную машину, установите на неё необходимое программное обеспечение и выполните все требуемые настройки.
-
Установите и настройте
qemu-guest-agent(рекомендуется):-
Для RHEL/CentOS:
yum install -y qemu-guest-agent -
Для Debian/Ubuntu:
apt-get update apt-get install -y qemu-guest-agent
-
-
Включите и запустите сервис:
systemctl enable qemu-guest-agent systemctl start qemu-guest-agent -
Задайте машине политику запуска
AlwaysOnUnlessStoppedManually, иначе выключить её не получится. -
Подготовьте образ. Очистите неиспользуемые блоки файловой системы:
fstrim -v / fstrim -v /boot -
Очистите сетевые настройки:
-
Для RHEL:
nmcli con delete $(nmcli -t -f NAME,DEVICE con show | grep -v ^lo: | cut -d: -f1) rm -f /etc/sysconfig/network-scripts/ifcfg-eth* -
Для Debian/Ubuntu:
rm -f /etc/network/interfaces.d/*
-
-
Очистите системные идентификаторы:
echo -n > /etc/machine-id rm -f /var/lib/dbus/machine-id ln -s /etc/machine-id /var/lib/dbus/machine-id -
Удалите ключи хоста SSH:
rm -f /etc/ssh/ssh_host_* -
Очистите журнал systemd:
journalctl --vacuum-size=100M --vacuum-time=7d -
Очистите кеш пакетных менеджеров:
-
Для RHEL:
yum clean all -
Для Debian/Ubuntu:
apt-get clean
-
-
Очистите временные файлы:
rm -rf /tmp/* rm -rf /var/tmp/* -
Очистите логи:
find /var/log -name "*.log" -type f -exec truncate -s 0 {} \; -
Очистите историю команд:
history -c -
В RHEL сбросьте и восстановите контексты SELinux одним из двух способов.
Восстановите контексты сразу:
restorecon -R /Либо запланируйте пересчёт контекстов на следующую загрузку:
touch /.autorelabel -
Проверьте, что в
/etc/fstabуказаны UUID илиLABEL, а не имена вида/dev/sdX:blkid cat /etc/fstab -
Сбросьте состояние cloud-init (логи и seed):
cloud-init clean --logs --seed -
Выполните финальную синхронизацию и очистку буферов:
sync echo 3 > /proc/sys/vm/drop_caches -
Выключите виртуальную машину:
poweroff -
Создайте ресурс VirtualImage, указав исходный ресурс VirtualDisk подготовленной ВМ:
d8 k apply -f -<<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualImage metadata: name: <IMAGE_NAME> namespace: <NAMESPACE> spec: dataSource: type: ObjectRef objectRef: kind: VirtualDisk name: <SOURCE_DISK_NAME> EOFЛибо создайте ресурс ClusterVirtualImage, чтобы образ был доступен на уровне кластера для всех проектов:
d8 k apply -f -<<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: ClusterVirtualImage metadata: name: <IMAGE_NAME> spec: dataSource: type: ObjectRef objectRef: kind: VirtualDisk name: <SOURCE_DISK_NAME> namespace: <NAMESPACE> EOFЗдесь
<IMAGE_NAME>— имя создаваемого образа,<NAMESPACE>— неймспейс подготовленной машины, а<SOURCE_DISK_NAME>— имя её диска. -
Создайте новый ресурс VirtualDisk из полученного образа:
d8 k apply -f -<<EOF apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualDisk metadata: name: <VM_DISK_NAME> namespace: <NAMESPACE> spec: dataSource: type: ObjectRef objectRef: kind: VirtualImage name: <IMAGE_NAME> EOFЗдесь
<VM_DISK_NAME>— имя диска новой машины.
После этих шагов golden image готов, и из него быстро создаются новые машины с уже установленным программным обеспечением и настройками.
Как восстановить кластер, если после смены лицензии образы из registry.deckhouse.io не загружаются?
После смены лицензии на кластере с containerd v1 и удаления устаревшей лицензии образы из registry.deckhouse.io могут перестать загружаться. При этом на узлах остаётся устаревший файл конфигурации /etc/containerd/conf.d/dvcr.toml, который не удаляется автоматически. Из-за него не запускается модуль registry, без которого не работает DVCR.
Манифест NodeGroupConfiguration (NGC) после применения удалит файл на узлах. После запуска модуля registry манифест нужно удалить, так как это разовое исправление.
-
Сохраните манифест в файл (например,
containerd-dvcr-remove-old-config.yaml):apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: containerd-dvcr-remove-old-config.sh spec: weight: 32 # Должен быть в диапазоне 32–90. nodeGroups: ["*"] bundles: ["*"] content: | # Copyright 2023 Flant JSC # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. rm -f /etc/containerd/conf.d/dvcr.toml -
Примените сохранённый манифест:
d8 k apply -f containerd-dvcr-remove-old-config.yaml -
Проверьте, что модуль
registryзапущен:d8 k -n d8-system -o yaml get secret registry-state | yq -C -P '.data | del .state | map_values(@base64d) | .conditions = (.conditions | from_yaml)'Пример вывода при успешном запуске:
conditions: # ... - lastTransitionTime: "..." message: "" reason: "" status: "True" type: Ready -
Удалите разовый манифест NodeGroupConfiguration:
d8 k delete -f containerd-dvcr-remove-old-config.yaml
Порядок миграции описан в разделе «Миграция container runtime на containerd v2».
Как перенаправить трафик на виртуальную машину?
Виртуальная машина работает в кластере Kubernetes, поэтому трафик к ней направляется так же, как к любой другой рабочей нагрузке. За маршрутизацию отвечает стандартный ресурс Kubernetes Service, который выбирает целевые объекты по лейблам.
-
Создайте сервис с требуемыми настройками.
В качестве примера приведена виртуальная машина с меткой
vm: frontend-0, HTTP-сервисом, опубликованным на портах 80 и 443, и открытым SSH на порту 22:apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine metadata: name: frontend-0 namespace: dev labels: vm: frontend-0 spec: ... -
Чтобы направить сетевой трафик на порты виртуальной машины, создайте сервис:
Следующий сервис обеспечивает доступ к виртуальной машине: он слушает порты 80 и 443 и перенаправляет трафик на соответствующие порты целевой виртуальной машины. SSH-доступ извне предоставляется по порту 2211:
apiVersion: v1 kind: Service metadata: name: frontend-0-svc namespace: dev spec: type: LoadBalancer ports: - name: ssh port: 2211 protocol: TCP targetPort: 22 - name: http port: 80 protocol: TCP targetPort: 80 - name: https port: 443 protocol: TCP targetPort: 443 selector: vm: frontend-0
Почему к виртуальной машине доступен только один способ подключения?
К виртуальной машине (ВМ) можно подключиться через серийную консоль (d8 v console) или по VNC (d8 v vnc).
Способы используют разные каналы связи с гостевой ОС и зависят от её настройки.
Оба способа описаны в разделе «Подключение к виртуальной машине».
Ниже перечислены типовые ситуации, когда доступен только один из способов подключения.
Почему не работает VNC, если серийная консоль доступна?
VNC выводит изображение экрана гостевой ОС и требует поддержки виртуального терминала в ядре. Серийная консоль при этом работает независимо от графической подсистемы.
Проверьте в гостевой ОС, включена ли поддержка виртуального терминала в конфигурации ядра:
cat /boot/config-$(uname -r) | grep CONFIG_VT
В выводе значение CONFIG_VT должно быть y:
CONFIG_VT=y
Если в выводе указано CONFIG_VT is not set, пересоберите ядро с включённым параметром либо используйте образ ОС с подходящей конфигурацией ядра.
Почему не работает серийная консоль, если VNC доступен?
Серийная консоль подключается к порту ttyS0 в гостевой ОС.
Если служба getty для этого порта не запущена, при подключении через d8 v console не появится приглашение ко входу, хотя VNC продолжит работать.
В гостевой ОС включите и запустите службу serial-getty для ttyS0:
sudo systemctl enable --now serial-getty@ttyS0.service
После этого снова подключитесь к серийной консоли.
Как предоставить файл ответов Windows (Sysprep)?
Автоматическая установка Windows выполняется с файлом ответов (unattend.xml или autounattend.xml).
В примере ниже файл ответов:
- задаёт русский язык интерфейса и раскладку;
- подключает драйверы
VirtIOдля этапа установки (порядок устройств вblockDeviceRefsу ресурса VirtualMachine должен совпадать с путями в файле); - создаёт разметку диска для установки с EFI;
- создаёт администратора
cloudи обычного пользователяuser.
<p><b>Пример содержимого файла autounattend.xml…</b></summary></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?xml version="1.0" encoding="utf-8"?></span> <span class="nt"><unattend</span> <span class="na">xmlns=</span><span class="s">"urn:schemas-microsoft-com:unattend"</span> <span class="na">xmlns:wcm=</span><span class="s">"http://schemas.microsoft.com/WMIConfig/2002/State"</span><span class="nt">></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"offlineServicing"</span><span class="nt">></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"windowsPE"</span><span class="nt">></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-International-Core-WinPE"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><SetupUILanguage></span>
<span class="nt"><UILanguage></span>ru-RU<span class="nt"></UILanguage></span>
<span class="nt"></SetupUILanguage></span>
<span class="nt"><InputLocale></span>0409:00000409;0419:00000419<span class="nt"></InputLocale></span>
<span class="nt"><SystemLocale></span>en-US<span class="nt"></SystemLocale></span>
<span class="nt"><UILanguage></span>ru-RU<span class="nt"></UILanguage></span>
<span class="nt"><UserLocale></span>en-US<span class="nt"></UserLocale></span>
<span class="nt"></component></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-PnpCustomizationsWinPE"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><DriverPaths></span>
<span class="nt"><PathAndCredentials</span> <span class="na">wcm:keyValue=</span><span class="s">"4b29ba63"</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Path></span>E:\amd64\w11<span class="nt"></Path></span>
<span class="nt"></PathAndCredentials></span>
<span class="nt"><PathAndCredentials</span> <span class="na">wcm:keyValue=</span><span class="s">"25fe51ea"</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Path></span>E:\NetKVM\w11\amd64<span class="nt"></Path></span>
<span class="nt"></PathAndCredentials></span>
<span class="nt"></DriverPaths></span>
<span class="nt"></component></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-Setup"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><DiskConfiguration></span>
<span class="nt"><Disk</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><DiskID></span>0<span class="nt"></DiskID></span>
<span class="nt"><WillWipeDisk></span>true<span class="nt"></WillWipeDisk></span>
<span class="nt"><CreatePartitions></span>
<span class="c"><!-- Recovery partition --></span>
<span class="nt"><CreatePartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>1<span class="nt"></Order></span>
<span class="nt"><Type></span>Primary<span class="nt"></Type></span>
<span class="nt"><Size></span>250<span class="nt"></Size></span>
<span class="nt"></CreatePartition></span>
<span class="c"><!-- EFI system partition (ESP) --></span>
<span class="nt"><CreatePartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>2<span class="nt"></Order></span>
<span class="nt"><Type></span>EFI<span class="nt"></Type></span>
<span class="nt"><Size></span>100<span class="nt"></Size></span>
<span class="nt"></CreatePartition></span>
<span class="c"><!-- Microsoft reserved partition (MSR) --></span>
<span class="nt"><CreatePartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>3<span class="nt"></Order></span>
<span class="nt"><Type></span>MSR<span class="nt"></Type></span>
<span class="nt"><Size></span>128<span class="nt"></Size></span>
<span class="nt"></CreatePartition></span>
<span class="c"><!-- Windows partition --></span>
<span class="nt"><CreatePartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>4<span class="nt"></Order></span>
<span class="nt"><Type></span>Primary<span class="nt"></Type></span>
<span class="nt"><Extend></span>true<span class="nt"></Extend></span>
<span class="nt"></CreatePartition></span>
<span class="nt"></CreatePartitions></span>
<span class="nt"><ModifyPartitions></span>
<span class="c"><!-- Recovery partition --></span>
<span class="nt"><ModifyPartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>1<span class="nt"></Order></span>
<span class="nt"><PartitionID></span>1<span class="nt"></PartitionID></span>
<span class="nt"><Label></span>Recovery<span class="nt"></Label></span>
<span class="nt"><Format></span>NTFS<span class="nt"></Format></span>
<span class="nt"><TypeID></span>de94bba4-06d1-4d40-a16a-bfd50179d6ac<span class="nt"></TypeID></span>
<span class="nt"></ModifyPartition></span>
<span class="c"><!-- EFI system partition (ESP) --></span>
<span class="nt"><ModifyPartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>2<span class="nt"></Order></span>
<span class="nt"><PartitionID></span>2<span class="nt"></PartitionID></span>
<span class="nt"><Label></span>System<span class="nt"></Label></span>
<span class="nt"><Format></span>FAT32<span class="nt"></Format></span>
<span class="nt"></ModifyPartition></span>
<span class="c"><!-- MSR partition does not need to be modified --></span>
<span class="c"><!-- Windows partition --></span>
<span class="nt"><ModifyPartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>3<span class="nt"></Order></span>
<span class="nt"><PartitionID></span>4<span class="nt"></PartitionID></span>
<span class="nt"><Label></span>Windows<span class="nt"></Label></span>
<span class="nt"><Letter></span>C<span class="nt"></Letter></span>
<span class="nt"><Format></span>NTFS<span class="nt"></Format></span>
<span class="nt"></ModifyPartition></span>
<span class="nt"></ModifyPartitions></span>
<span class="nt"></Disk></span>
<span class="nt"><WillShowUI></span>OnError<span class="nt"></WillShowUI></span>
<span class="nt"></DiskConfiguration></span>
<span class="nt"><ImageInstall></span>
<span class="nt"><OSImage></span>
<span class="nt"><InstallTo></span>
<span class="nt"><DiskID></span>0<span class="nt"></DiskID></span>
<span class="nt"><PartitionID></span>4<span class="nt"></PartitionID></span>
<span class="nt"></InstallTo></span>
<span class="nt"></OSImage></span>
<span class="nt"></ImageInstall></span>
<span class="nt"><UserData></span>
<span class="nt"><ProductKey></span>
<span class="nt"><Key><PRODUCT_KEY></Key></span>
<span class="nt"><WillShowUI></span>OnError<span class="nt"></WillShowUI></span>
<span class="nt"></ProductKey></span>
<span class="nt"><AcceptEula></span>true<span class="nt"></AcceptEula></span>
<span class="nt"></UserData></span>
<span class="nt"><UseConfigurationSet></span>false<span class="nt"></UseConfigurationSet></span>
<span class="nt"></component></span> <span class="nt"></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"generalize"</span><span class="nt">></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"specialize"</span><span class="nt">></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-Deployment"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><RunSynchronous></span>
<span class="nt"><RunSynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>1<span class="nt"></Order></span>
<span class="nt"><Path></span>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;"<span class="nt"></Path></span>
<span class="nt"></RunSynchronousCommand></span>
<span class="nt"><RunSynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>2<span class="nt"></Order></span>
<span class="nt"><Path></span>powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\Specialize.ps1' -Raw | Invoke-Expression;"<span class="nt"></Path></span>
<span class="nt"></RunSynchronousCommand></span>
<span class="nt"><RunSynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>3<span class="nt"></Order></span>
<span class="nt"><Path></span>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"<span class="nt"></Path></span>
<span class="nt"></RunSynchronousCommand></span>
<span class="nt"><RunSynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>4<span class="nt"></Order></span>
<span class="nt"><Path></span>powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\DefaultUser.ps1' -Raw | Invoke-Expression;"<span class="nt"></Path></span>
<span class="nt"></RunSynchronousCommand></span>
<span class="nt"><RunSynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>5<span class="nt"></Order></span>
<span class="nt"><Path></span>reg.exe unload "HKU\DefaultUser"<span class="nt"></Path></span>
<span class="nt"></RunSynchronousCommand></span>
<span class="nt"></RunSynchronous></span>
<span class="nt"></component></span> <span class="nt"></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"auditSystem"</span><span class="nt">></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"auditUser"</span><span class="nt">></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"oobeSystem"</span><span class="nt">></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-International-Core"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><InputLocale></span>0409:00000409;0419:00000419<span class="nt"></InputLocale></span>
<span class="nt"><SystemLocale></span>en-US<span class="nt"></SystemLocale></span>
<span class="nt"><UILanguage></span>ru-RU<span class="nt"></UILanguage></span>
<span class="nt"><UserLocale></span>en-US<span class="nt"></UserLocale></span>
<span class="nt"></component></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-Shell-Setup"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><UserAccounts></span>
<span class="nt"><LocalAccounts></span>
<span class="nt"><LocalAccount</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Name></span>cloud<span class="nt"></Name></span>
<span class="nt"><DisplayName></span>cloud<span class="nt"></DisplayName></span>
<span class="nt"><Group></span>Administrators<span class="nt"></Group></span>
<span class="nt"><Password></span>
<span class="nt"><Value><ADMIN_PASSWORD></Value></span>
<span class="nt"><PlainText></span>true<span class="nt"></PlainText></span>
<span class="nt"></Password></span>
<span class="nt"></LocalAccount></span>
<span class="nt"><LocalAccount</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Name></span>User<span class="nt"></Name></span>
<span class="nt"><DisplayName></span>user<span class="nt"></DisplayName></span>
<span class="nt"><Group></span>Users<span class="nt"></Group></span>
<span class="nt"><Password></span>
<span class="nt"><Value><USER_PASSWORD></Value></span>
<span class="nt"><PlainText></span>true<span class="nt"></PlainText></span>
<span class="nt"></Password></span>
<span class="nt"></LocalAccount></span>
<span class="nt"></LocalAccounts></span>
<span class="nt"></UserAccounts></span>
<span class="nt"><AutoLogon></span>
<span class="nt"><Username></span>cloud<span class="nt"></Username></span>
<span class="nt"><Enabled></span>true<span class="nt"></Enabled></span>
<span class="nt"><LogonCount></span>1<span class="nt"></LogonCount></span>
<span class="nt"><Password></span>
<span class="nt"><Value><ADMIN_PASSWORD></Value></span>
<span class="nt"><PlainText></span>true<span class="nt"></PlainText></span>
<span class="nt"></Password></span>
<span class="nt"></AutoLogon></span>
<span class="nt"><OOBE></span>
<span class="nt"><ProtectYourPC></span>3<span class="nt"></ProtectYourPC></span>
<span class="nt"><HideEULAPage></span>true<span class="nt"></HideEULAPage></span>
<span class="nt"><HideWirelessSetupInOOBE></span>true<span class="nt"></HideWirelessSetupInOOBE></span>
<span class="nt"><HideOnlineAccountScreens></span>false<span class="nt"></HideOnlineAccountScreens></span>
<span class="nt"></OOBE></span>
<span class="nt"><FirstLogonCommands></span>
<span class="nt"><SynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>1<span class="nt"></Order></span>
<span class="nt"><CommandLine></span>powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\FirstLogon.ps1' -Raw | Invoke-Expression;"<span class="nt"></CommandLine></span>
<span class="nt"></SynchronousCommand></span>
<span class="nt"></FirstLogonCommands></span>
<span class="nt"></component></span> <span class="nt"></settings></span> <span class="nt"></unattend></span> </code></pre></div> </div>
<p></details></p>
<p>Вместо <code class="language-plaintext highlighter-rouge"><PRODUCT_KEY></code> подставьте ключ продукта Windows, а вместо <code class="language-plaintext highlighter-rouge"><ADMIN_PASSWORD></code> и <code class="language-plaintext highlighter-rouge"><USER_PASSWORD></code> подставьте пароли создаваемых учётных записей. Windows читает эти пароли из файла в открытом виде, поэтому не оставляйте готовый файл ответов на общедоступном ресурсе.</p>
<ol>
<li>
<p>Сохраните файл ответов в <code class="language-plaintext highlighter-rouge">autounattend.xml</code> (воспользуйтесь примером из блока выше или измените его под свои требования).</p>
</li>
<li>
<p>Создайте секрет с типом <code class="language-plaintext highlighter-rouge">provisioning.virtualization.deckhouse.io/sysprep</code>:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>d8 k create secret generic sysprep-config <span class="nt">--type</span><span class="o">=</span><span class="s2">"provisioning.virtualization.deckhouse.io/sysprep"</span> <span class="nt">--from-file</span><span class="o">=</span>./autounattend.xml </code></pre></div> </div>
</li>
<li>
<p>Создайте виртуальную машину, которая в процессе установки будет использовать файл ответов. Укажите в спецификации <code class="language-plaintext highlighter-rouge">provisioning</code> с типом <code class="language-plaintext highlighter-rouge">SysprepRef</code>. При необходимости добавьте в спецификацию другие файлы в формате Base64, необходимые для успешного выполнения скриптов внутри файла ответов:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">apiVersion</span><span class="pi">:</span> <span class="s">virtualization.deckhouse.io/v1alpha2</span> <span class="na">kind</span><span class="pi">:</span> <span class="s">VirtualMachine</span> <span class="na">metadata</span><span class="pi">:</span> <span class="na">name</span><span class="pi">:</span> <span class="s">win-vm</span> <span class="na">namespace</span><span class="pi">:</span> <span class="s">default</span> <span class="na">labels</span><span class="pi">:</span>
<span class="na">vm</span><span class="pi">:</span> <span class="s">win</span> <span class="na">spec</span><span class="pi">:</span> <span class="na">virtualMachineClassName</span><span class="pi">:</span> <span class="s">generic</span> <span class="na">provisioning</span><span class="pi">:</span>
<span class="na">type</span><span class="pi">:</span> <span class="s">SysprepRef</span>
<span class="na">sysprepRef</span><span class="pi">:</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">Secret</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">sysprep-config</span> <span class="na">runPolicy</span><span class="pi">:</span> <span class="s">AlwaysOn</span> <span class="na">osType</span><span class="pi">:</span> <span class="s">Windows</span> <span class="na">bootloader</span><span class="pi">:</span> <span class="s">EFI</span> <span class="na">cpu</span><span class="pi">:</span>
<span class="na">cores</span><span class="pi">:</span> <span class="m">6</span>
<span class="na">coreFraction</span><span class="pi">:</span> <span class="s">50%</span> <span class="na">memory</span><span class="pi">:</span>
<span class="na">size</span><span class="pi">:</span> <span class="s">8Gi</span> <span class="na">enableParavirtualization</span><span class="pi">:</span> <span class="kc">true</span> <span class="na">blockDeviceRefs</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">kind</span><span class="pi">:</span> <span class="s">VirtualDisk</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">win-disk</span>
<span class="pi">-</span> <span class="na">kind</span><span class="pi">:</span> <span class="s">ClusterVirtualImage</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">win-11-iso</span>
<span class="pi">-</span> <span class="na">kind</span><span class="pi">:</span> <span class="s">ClusterVirtualImage</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">win-virtio-iso</span> </code></pre></div> </div>
</li>
</ol>
<p><b>Пример содержимого файла autounattend.xml…</b></summary></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?xml version="1.0" encoding="utf-8"?></span> <span class="nt"><unattend</span> <span class="na">xmlns=</span><span class="s">"urn:schemas-microsoft-com:unattend"</span> <span class="na">xmlns:wcm=</span><span class="s">"http://schemas.microsoft.com/WMIConfig/2002/State"</span><span class="nt">></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"offlineServicing"</span><span class="nt">></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"windowsPE"</span><span class="nt">></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-International-Core-WinPE"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><SetupUILanguage></span>
<span class="nt"><UILanguage></span>ru-RU<span class="nt"></UILanguage></span>
<span class="nt"></SetupUILanguage></span>
<span class="nt"><InputLocale></span>0409:00000409;0419:00000419<span class="nt"></InputLocale></span>
<span class="nt"><SystemLocale></span>en-US<span class="nt"></SystemLocale></span>
<span class="nt"><UILanguage></span>ru-RU<span class="nt"></UILanguage></span>
<span class="nt"><UserLocale></span>en-US<span class="nt"></UserLocale></span>
<span class="nt"></component></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-PnpCustomizationsWinPE"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><DriverPaths></span>
<span class="nt"><PathAndCredentials</span> <span class="na">wcm:keyValue=</span><span class="s">"4b29ba63"</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Path></span>E:\amd64\w11<span class="nt"></Path></span>
<span class="nt"></PathAndCredentials></span>
<span class="nt"><PathAndCredentials</span> <span class="na">wcm:keyValue=</span><span class="s">"25fe51ea"</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Path></span>E:\NetKVM\w11\amd64<span class="nt"></Path></span>
<span class="nt"></PathAndCredentials></span>
<span class="nt"></DriverPaths></span>
<span class="nt"></component></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-Setup"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><DiskConfiguration></span>
<span class="nt"><Disk</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><DiskID></span>0<span class="nt"></DiskID></span>
<span class="nt"><WillWipeDisk></span>true<span class="nt"></WillWipeDisk></span>
<span class="nt"><CreatePartitions></span>
<span class="c"><!-- Recovery partition --></span>
<span class="nt"><CreatePartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>1<span class="nt"></Order></span>
<span class="nt"><Type></span>Primary<span class="nt"></Type></span>
<span class="nt"><Size></span>250<span class="nt"></Size></span>
<span class="nt"></CreatePartition></span>
<span class="c"><!-- EFI system partition (ESP) --></span>
<span class="nt"><CreatePartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>2<span class="nt"></Order></span>
<span class="nt"><Type></span>EFI<span class="nt"></Type></span>
<span class="nt"><Size></span>100<span class="nt"></Size></span>
<span class="nt"></CreatePartition></span>
<span class="c"><!-- Microsoft reserved partition (MSR) --></span>
<span class="nt"><CreatePartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>3<span class="nt"></Order></span>
<span class="nt"><Type></span>MSR<span class="nt"></Type></span>
<span class="nt"><Size></span>128<span class="nt"></Size></span>
<span class="nt"></CreatePartition></span>
<span class="c"><!-- Windows partition --></span>
<span class="nt"><CreatePartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>4<span class="nt"></Order></span>
<span class="nt"><Type></span>Primary<span class="nt"></Type></span>
<span class="nt"><Extend></span>true<span class="nt"></Extend></span>
<span class="nt"></CreatePartition></span>
<span class="nt"></CreatePartitions></span>
<span class="nt"><ModifyPartitions></span>
<span class="c"><!-- Recovery partition --></span>
<span class="nt"><ModifyPartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>1<span class="nt"></Order></span>
<span class="nt"><PartitionID></span>1<span class="nt"></PartitionID></span>
<span class="nt"><Label></span>Recovery<span class="nt"></Label></span>
<span class="nt"><Format></span>NTFS<span class="nt"></Format></span>
<span class="nt"><TypeID></span>de94bba4-06d1-4d40-a16a-bfd50179d6ac<span class="nt"></TypeID></span>
<span class="nt"></ModifyPartition></span>
<span class="c"><!-- EFI system partition (ESP) --></span>
<span class="nt"><ModifyPartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>2<span class="nt"></Order></span>
<span class="nt"><PartitionID></span>2<span class="nt"></PartitionID></span>
<span class="nt"><Label></span>System<span class="nt"></Label></span>
<span class="nt"><Format></span>FAT32<span class="nt"></Format></span>
<span class="nt"></ModifyPartition></span>
<span class="c"><!-- MSR partition does not need to be modified --></span>
<span class="c"><!-- Windows partition --></span>
<span class="nt"><ModifyPartition</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>3<span class="nt"></Order></span>
<span class="nt"><PartitionID></span>4<span class="nt"></PartitionID></span>
<span class="nt"><Label></span>Windows<span class="nt"></Label></span>
<span class="nt"><Letter></span>C<span class="nt"></Letter></span>
<span class="nt"><Format></span>NTFS<span class="nt"></Format></span>
<span class="nt"></ModifyPartition></span>
<span class="nt"></ModifyPartitions></span>
<span class="nt"></Disk></span>
<span class="nt"><WillShowUI></span>OnError<span class="nt"></WillShowUI></span>
<span class="nt"></DiskConfiguration></span>
<span class="nt"><ImageInstall></span>
<span class="nt"><OSImage></span>
<span class="nt"><InstallTo></span>
<span class="nt"><DiskID></span>0<span class="nt"></DiskID></span>
<span class="nt"><PartitionID></span>4<span class="nt"></PartitionID></span>
<span class="nt"></InstallTo></span>
<span class="nt"></OSImage></span>
<span class="nt"></ImageInstall></span>
<span class="nt"><UserData></span>
<span class="nt"><ProductKey></span>
<span class="nt"><Key><PRODUCT_KEY></Key></span>
<span class="nt"><WillShowUI></span>OnError<span class="nt"></WillShowUI></span>
<span class="nt"></ProductKey></span>
<span class="nt"><AcceptEula></span>true<span class="nt"></AcceptEula></span>
<span class="nt"></UserData></span>
<span class="nt"><UseConfigurationSet></span>false<span class="nt"></UseConfigurationSet></span>
<span class="nt"></component></span> <span class="nt"></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"generalize"</span><span class="nt">></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"specialize"</span><span class="nt">></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-Deployment"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><RunSynchronous></span>
<span class="nt"><RunSynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>1<span class="nt"></Order></span>
<span class="nt"><Path></span>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;"<span class="nt"></Path></span>
<span class="nt"></RunSynchronousCommand></span>
<span class="nt"><RunSynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>2<span class="nt"></Order></span>
<span class="nt"><Path></span>powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\Specialize.ps1' -Raw | Invoke-Expression;"<span class="nt"></Path></span>
<span class="nt"></RunSynchronousCommand></span>
<span class="nt"><RunSynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>3<span class="nt"></Order></span>
<span class="nt"><Path></span>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"<span class="nt"></Path></span>
<span class="nt"></RunSynchronousCommand></span>
<span class="nt"><RunSynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>4<span class="nt"></Order></span>
<span class="nt"><Path></span>powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\DefaultUser.ps1' -Raw | Invoke-Expression;"<span class="nt"></Path></span>
<span class="nt"></RunSynchronousCommand></span>
<span class="nt"><RunSynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>5<span class="nt"></Order></span>
<span class="nt"><Path></span>reg.exe unload "HKU\DefaultUser"<span class="nt"></Path></span>
<span class="nt"></RunSynchronousCommand></span>
<span class="nt"></RunSynchronous></span>
<span class="nt"></component></span> <span class="nt"></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"auditSystem"</span><span class="nt">></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"auditUser"</span><span class="nt">></settings></span> <span class="nt"><settings</span> <span class="na">pass=</span><span class="s">"oobeSystem"</span><span class="nt">></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-International-Core"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><InputLocale></span>0409:00000409;0419:00000419<span class="nt"></InputLocale></span>
<span class="nt"><SystemLocale></span>en-US<span class="nt"></SystemLocale></span>
<span class="nt"><UILanguage></span>ru-RU<span class="nt"></UILanguage></span>
<span class="nt"><UserLocale></span>en-US<span class="nt"></UserLocale></span>
<span class="nt"></component></span>
<span class="nt"><component</span> <span class="na">name=</span><span class="s">"Microsoft-Windows-Shell-Setup"</span> <span class="na">processorArchitecture=</span><span class="s">"amd64"</span> <span class="na">publicKeyToken=</span><span class="s">"31bf3856ad364e35"</span> <span class="na">language=</span><span class="s">"neutral"</span> <span class="na">versionScope=</span><span class="s">"nonSxS"</span><span class="nt">></span>
<span class="nt"><UserAccounts></span>
<span class="nt"><LocalAccounts></span>
<span class="nt"><LocalAccount</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Name></span>cloud<span class="nt"></Name></span>
<span class="nt"><DisplayName></span>cloud<span class="nt"></DisplayName></span>
<span class="nt"><Group></span>Administrators<span class="nt"></Group></span>
<span class="nt"><Password></span>
<span class="nt"><Value><ADMIN_PASSWORD></Value></span>
<span class="nt"><PlainText></span>true<span class="nt"></PlainText></span>
<span class="nt"></Password></span>
<span class="nt"></LocalAccount></span>
<span class="nt"><LocalAccount</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Name></span>User<span class="nt"></Name></span>
<span class="nt"><DisplayName></span>user<span class="nt"></DisplayName></span>
<span class="nt"><Group></span>Users<span class="nt"></Group></span>
<span class="nt"><Password></span>
<span class="nt"><Value><USER_PASSWORD></Value></span>
<span class="nt"><PlainText></span>true<span class="nt"></PlainText></span>
<span class="nt"></Password></span>
<span class="nt"></LocalAccount></span>
<span class="nt"></LocalAccounts></span>
<span class="nt"></UserAccounts></span>
<span class="nt"><AutoLogon></span>
<span class="nt"><Username></span>cloud<span class="nt"></Username></span>
<span class="nt"><Enabled></span>true<span class="nt"></Enabled></span>
<span class="nt"><LogonCount></span>1<span class="nt"></LogonCount></span>
<span class="nt"><Password></span>
<span class="nt"><Value><ADMIN_PASSWORD></Value></span>
<span class="nt"><PlainText></span>true<span class="nt"></PlainText></span>
<span class="nt"></Password></span>
<span class="nt"></AutoLogon></span>
<span class="nt"><OOBE></span>
<span class="nt"><ProtectYourPC></span>3<span class="nt"></ProtectYourPC></span>
<span class="nt"><HideEULAPage></span>true<span class="nt"></HideEULAPage></span>
<span class="nt"><HideWirelessSetupInOOBE></span>true<span class="nt"></HideWirelessSetupInOOBE></span>
<span class="nt"><HideOnlineAccountScreens></span>false<span class="nt"></HideOnlineAccountScreens></span>
<span class="nt"></OOBE></span>
<span class="nt"><FirstLogonCommands></span>
<span class="nt"><SynchronousCommand</span> <span class="na">wcm:action=</span><span class="s">"add"</span><span class="nt">></span>
<span class="nt"><Order></span>1<span class="nt"></Order></span>
<span class="nt"><CommandLine></span>powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\FirstLogon.ps1' -Raw | Invoke-Expression;"<span class="nt"></CommandLine></span>
<span class="nt"></SynchronousCommand></span>
<span class="nt"></FirstLogonCommands></span>
<span class="nt"></component></span> <span class="nt"></settings></span> <span class="nt"></unattend></span> </code></pre></div> </div>
<p></details></p>
<p>Вместо <code class="language-plaintext highlighter-rouge"><PRODUCT_KEY></code> подставьте ключ продукта Windows, а вместо <code class="language-plaintext highlighter-rouge"><ADMIN_PASSWORD></code> и <code class="language-plaintext highlighter-rouge"><USER_PASSWORD></code> подставьте пароли создаваемых учётных записей. Windows читает эти пароли из файла в открытом виде, поэтому не оставляйте готовый файл ответов на общедоступном ресурсе.</p>
<ol>
<li>
<p>Сохраните файл ответов в <code class="language-plaintext highlighter-rouge">autounattend.xml</code> (воспользуйтесь примером из блока выше или измените его под свои требования).</p>
</li>
<li>
<p>Создайте секрет с типом <code class="language-plaintext highlighter-rouge">provisioning.virtualization.deckhouse.io/sysprep</code>:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>d8 k create secret generic sysprep-config <span class="nt">--type</span><span class="o">=</span><span class="s2">"provisioning.virtualization.deckhouse.io/sysprep"</span> <span class="nt">--from-file</span><span class="o">=</span>./autounattend.xml </code></pre></div> </div>
</li>
<li>
<p>Создайте виртуальную машину, которая в процессе установки будет использовать файл ответов. Укажите в спецификации <code class="language-plaintext highlighter-rouge">provisioning</code> с типом <code class="language-plaintext highlighter-rouge">SysprepRef</code>. При необходимости добавьте в спецификацию другие файлы в формате Base64, необходимые для успешного выполнения скриптов внутри файла ответов:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">apiVersion</span><span class="pi">:</span> <span class="s">virtualization.deckhouse.io/v1alpha2</span> <span class="na">kind</span><span class="pi">:</span> <span class="s">VirtualMachine</span> <span class="na">metadata</span><span class="pi">:</span> <span class="na">name</span><span class="pi">:</span> <span class="s">win-vm</span> <span class="na">namespace</span><span class="pi">:</span> <span class="s">default</span> <span class="na">labels</span><span class="pi">:</span>
<span class="na">vm</span><span class="pi">:</span> <span class="s">win</span> <span class="na">spec</span><span class="pi">:</span> <span class="na">virtualMachineClassName</span><span class="pi">:</span> <span class="s">generic</span> <span class="na">provisioning</span><span class="pi">:</span>
<span class="na">type</span><span class="pi">:</span> <span class="s">SysprepRef</span>
<span class="na">sysprepRef</span><span class="pi">:</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">Secret</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">sysprep-config</span> <span class="na">runPolicy</span><span class="pi">:</span> <span class="s">AlwaysOn</span> <span class="na">osType</span><span class="pi">:</span> <span class="s">Windows</span> <span class="na">bootloader</span><span class="pi">:</span> <span class="s">EFI</span> <span class="na">cpu</span><span class="pi">:</span>
<span class="na">cores</span><span class="pi">:</span> <span class="m">6</span>
<span class="na">coreFraction</span><span class="pi">:</span> <span class="s">50%</span> <span class="na">memory</span><span class="pi">:</span>
<span class="na">size</span><span class="pi">:</span> <span class="s">8Gi</span> <span class="na">enableParavirtualization</span><span class="pi">:</span> <span class="kc">true</span> <span class="na">blockDeviceRefs</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">kind</span><span class="pi">:</span> <span class="s">VirtualDisk</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">win-disk</span>
<span class="pi">-</span> <span class="na">kind</span><span class="pi">:</span> <span class="s">ClusterVirtualImage</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">win-11-iso</span>
<span class="pi">-</span> <span class="na">kind</span><span class="pi">:</span> <span class="s">ClusterVirtualImage</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">win-virtio-iso</span> </code></pre></div> </div>
</li>
</ol>