The page contains frequently asked questions about configuring and using the Deckhouse Platform.
Common
How can I apply an update for a specific module immediately?
To apply an update for a specific module immediately, set the modules.deckhouse.io/apply-now: "true" annotation on the corresponding ModuleRelease resource.
This annotation applies the release immediately without waiting for the update window. The requirements from spec.requirements still apply. If they are not met, the release will not be applied.
Example of setting the annotation for the console module:
d8 k annotate mr console-v1.43.3 modules.deckhouse.io/apply-now="true"
This can also be done using the d8 CLI for convenience (module names and versions are autocompleted):
d8 system module apply-now console v1.43.3
Example resource with the annotation set:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleRelease
metadata:
name: console-v1.43.3
annotations:
modules.deckhouse.io/apply-now: "true"
...
How can I apply an update DP immediately, bypassing update windows, canary releases, and manual update mode?
To apply a Deckhouse Platform (DP) update immediately, add the annotation release.deckhouse.io/apply-now: "true" to the corresponding DeckhouseRelease resource.
This will bypass update windows, canary release settings, and the manual cluster update mode. The update will be applied immediately after the annotation is set.
Example command to set the annotation and skip update windows for version v1.56.2:
d8 k annotate deckhousereleases v1.56.2 release.deckhouse.io/apply-now="true"
Example of a resource with the annotation set:
apiVersion: deckhouse.io/v1alpha1
kind: DeckhouseRelease
metadata:
annotations:
release.deckhouse.io/apply-now: "true"
...
What to do if, with VPN enabled, the container with the installer cannot access the network?
If a VPN is installed on the computer from which the cluster bootstrap is performed, there may be a problem with the container with the installer (or graphical installer) accessing the network. Because of this, for example, the graphical installer may not be displayed in the browser.
The problem can be solved in one of the following ways:
- Disable VPN on your computer and restart the container with the installer.
-
If you cannot disable VPN (for example, if the cluster bootstrap is running on a VPN network), use the
--network hostparameter when starting the container with the installer (for Docker Desktop on Mac OS, the parameter is available starting with version 4.34.0). This will allow the container to access the network.Example of launching a container with an installer with VPN enabled, using the
--network hostparameter: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 bashExample of running the graphical installer with VPN enabled, using the
--network hostparameter: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
How do I change the release channel for a module?
A module can be built-in to DP or connected from a module source (defined using ModuleSource). Built-in modules have a common release cycle with DP and are updated together with DP. The release channel of a built-in module always matches the DP release channel. A module connected from a source has its own release cycle, which is independent of the DP release cycle. The release channel of a module connected from a source can be changed.
Below is the process of changing the release channel for a module connected from a source.
By default, the release channel for modules is inherited from the DP release channel (specified in the releaseChannel parameter of the deckhouse ModuleConfig). For more information about release channels, see the Release Channels section.
For modules from a source, the release channel is specified using ModuleUpdatePolicy, which is then linked to the module via the updatePolicy parameter in ModuleConfig.
To change the release channel for a module from a source, follow these steps:
-
Define the module update policy.
Create a ModuleUpdatePolicy where you specify the release channel in the
releaseChannelparameter.Example ModuleUpdatePolicy:
apiVersion: deckhouse.io/v1alpha2 kind: ModuleUpdatePolicy metadata: name: my-module-policy spec: releaseChannel: Alpha update: mode: AutoIf necessary, change the update mode and configure update windows.
Ensure that the policy has been created:
d8 k get mup my-module-policyOutput example:
NAME RELEASE CHANNEL UPDATE MODE my-module-policy Alpha AutoPatch -
Link the update policy to the module.
Specify the name of the created update policy in the updatePolicy parameter of the corresponding module’s ModuleConfig.
To edit the ModuleConfig, use the command (specify the module name):
d8 k edit mc my-moduleExample ModuleConfig:
apiVersion: deckhouse.io/v1alpha1 kind: ModuleConfig metadata: name: my-module spec: enabled: true # ModuleUpdatePolicy name. updatePolicy: my-module-policy
When you change the module’s release channel, its version will change according to the configured update mode.
To view the current release channel of the module and other information about the module’s state in the cluster, use the corresponding Module object.
Example command to get information about the module:
d8 k get module my-module -o yaml
The update policy used will be specified in the properties.updatePolicy field, and the current release channel in the properties.releaseChannel field. Example output:
apiVersion: deckhouse.io/v1alpha1
kind: Module
metadata:
name: my-module
# ...
properties:
# ...
releaseChannel: Alpha # Module release channel.
updatePolicy: my-module-policy # Module update policy.
version: v1.16.10 # Module version.
# ...
How do I configure an external module to update to patch versions only?
By default, if a module has no dedicated update policy, the update mode and windows are inherited from the DP settings.
If DP is set to the AutoPatch mode, the external module will also automatically receive only patch versions within the current minor version. Moving to a new minor version will require manual approval. In this case, no additional configuration is needed.
For more information about DP update modes, see Configuring updates.
If you need to manage the module update mode independently of DP, create a ModuleUpdatePolicy with update.mode: AutoPatch and link it to the module via the updatePolicy parameter in ModuleConfig:
-
Create an update policy.
Example ModuleUpdatePolicy:
apiVersion: deckhouse.io/v1alpha2 kind: ModuleUpdatePolicy metadata: name: my-update-policy spec: releaseChannel: Stable update: mode: AutoPatchEnsure that the policy has been created:
d8 k get mup my-update-policy -
Link the policy to the module.
Specify the policy name in the updatePolicy parameter of the module’s ModuleConfig:
d8 k edit mc moduleExample ModuleConfig:
apiVersion: deckhouse.io/v1alpha1 kind: ModuleConfig metadata: name: module spec: enabled: true updatePolicy: my-update-policy
In the AutoPatch mode, module patch versions (for example, from v1.16.1 to v1.16.2) are applied automatically, taking update windows into account if they are configured. To move to a new minor version (for example, from v1.16.* to v1.17.*), approve the corresponding ModuleRelease:
d8 k annotate mr module-v1.17.0 modules.deckhouse.io/approved="true"
Or using the d8 CLI:
d8 system module approve module v1.17.0
What should I do if the module image did not download and the module did not reinstall?
In some cases, there may be a problem with automatically downloading the image and reinstalling the module. These cases include:
- Damage to the file system or other problems that have rendered the module image invalid.
- Switching to a different registry.
- Switching from one DP edition to another.
In this case, the module may be in the Ready state. The error occurs in the module’s pods. To find the problematic pod, use the command:
d8 k -n d8-<module-name> get pods
A problematic pod will have a status other than Running.
To view information about a pod, use the command:
d8 k -n d8-<module-name> describe pod <pod-name>
Example of an error message in the pod when there is a problem with downloading the image and reinstalling the module:
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 ...
To download the image and reinstall the module that caused the problem:
-
Get a list of module releases:
d8 k get mr -l module=my-moduleOutput example:
NAME PHASE UPDATE POLICY TRANSITIONTIME MESSAGE my-module-v3.7.4 Superseded 5d23h my-module-v3.7.5 Deployed 5d23hFind the module release deployed in the cluster in the list (it should have the status
Deployed). -
Add the annotation
modules.deckhouse.io/reinstall=trueto the expanded release:d8 k annotate mr my-module-v3.7.5 modules.deckhouse.io/reinstall=true
After adding the annotation, the module image is re-downloaded from the registry, the module is validated with the current settings from ModuleConfig, and installed in the cluster. After successful reinstallation, the annotation is automatically removed from ModuleRelease.
To verify that the module has been successfully reinstalled and all module pods are working, use the command:
d8 k -n d8-<module-name> get pods
All pods in the module must have the status Running. Example:
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 and Infrastructure
What to do if you encounter problems updating Kubernetes components on cluster nodes, synchronizing nodes, or applying NodeGroup Configuration?
If Kubernetes components are not updated on the cluster node, the NodeGroup configuration is not applied, and not all NodeGroup nodes are synchronized (have the UPTODATE status), perform the following steps:
-
Check the bashible logs on the node where the problems are occurring. The bashible mechanism is used to keep cluster nodes up to date. It is started by the
bashible.timertimer at regular intervals as a service on the cluster nodes. This involves restarting, synchronizing scripts, and executing them (if necessary).To check bashible logs, use the command:
journalctl -u bashibleIf the response contains the message
Configuration is in sync, nothing to do, the node is synchronized and there are no problems. The absence of this message or the presence of errors indicates a problem. -
Check the synchronization status of cluster nodes using the command:
d8 k get ngThe number of nodes in the
UPTODATEstate must match the total number of nodes in each group.Example output:
NAME TYPE READY NODES UPTODATE INSTANCES DESIRED MIN MAX STANDBY STATUS AGE SYNCED frontend Static 1 1 1 118d True master Static 3 3 3 118d True system Static 2 2 2 118d True worker Static 2 2 2 118d True
What to do if problems adding a node to the cluster via Cluster API Provider Static are present?
If, when adding a node to the cluster via Cluster API Provider Static (CAPS), it remains in Pending or Bootstrapping status, perform the following steps:
-
Verify that the access keys specified in the SSHCredentials resource are correct. Ensure that the username and SSH key specified in SSHCredentials are correct.
-
On the node where the problem occurred, check that the public key corresponding to the private key from SSHCredentials is present in
authorized_keys. Example command for checking:cat ~/.ssh/authorized_keys -
Check the number of nodes specified in NodeGroup, which should include the node being added. Make sure that the maximum number of nodes is not exceeded.
-
Check the status of the
bashible.serviceon the node that caused the problem:systemctl status bashible.serviceIt must have the status
active (running). If the service has the statusinactiveorfailed, the service has not started. This indicates a problem with the configuration process. -
If the steps above did not resolve the issue, remove the problematic node and its StaticInstance resource from the cluster so that the system will attempt to recreate them. To do this:
-
Get a list of nodes and locate the problematic one:
d8 k get nodes -
Find the corresponding StaticInstance resource:
kubectl get staticinstances -n <namespace-name> -
Remove the problematic node:
kubectl delete node <node-name> -
Remove the corresponding StaticInstance resource:
kubectl delete staticinstances -n <namespace-name> <static-instance-name>
-
How to change the instance type for nodes with the CloudPermanent type?
To change the instance type for nodes with the CloudPermanent type, follow these steps:
- Make a backup of etcd and the
/etc/kubernetesdirectory. - Transfer the archive to a server outside the cluster (e.g., on a local machine).
- Ensure there are no alerts in the cluster that can prevent the update of the master nodes.
-
Make sure that Deckhouse queue is empty. To view the status of all Deckhouse job queues, run the following command:
d8 s queue listExample output (queues are empty):
Summary: - 'main' queue: empty. - 88 other queues (0 active, 88 empty): 0 tasks. - no tasks to handle. -
Run the appropriate edition and version of the Deckhouse installer container on the local machine (change the container registry address if necessary):
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 -
In the installer container, run the following command to check the state before working:
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>The command output should indicate that Terraform found no inconsistencies and no changes are required.
-
In the installer container, run the command to edit the cluster configuration (specify the addresses of all master nodes in the
--ssh-hostparameter):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> -
Edit the
instanceClassparameter of the desired node group by changing the instance type and save the changes. Example settings for themasterNodeGroupof the Yandex Cloud provider:masterNodeGroup: replicas: 3 # required number of master nodes instanceClass: cores: 4 # change the number of CPUs memory: 8192 # change the memory size (in MB) # other instance parameters... externalIPAddresses: - "Auto" # for each master node - "Auto" - "Auto" -
In the installer container, run the following command to perform nodes upgrade:
You should read carefully what converge is going to do when it asks for approval.
When the command is executed, the nodes will be replaced by new nodes with confirmation on each node. The replacement will be performed one by one in reverse order (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>Repeat the steps below (Sec. 9-12) for each master node one by one, starting with the node with the highest number (suffix 2) and ending with the node with the lowest number (suffix 0).
-
On the newly created node, check the systemd-unit log for the
bashible.service. Wait until the node configuration is complete (you will see a messagenothing to doin the log):journalctl -fu bashible.service -
Make sure the node is listed as an etcd cluster member:
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 -
Make sure
control-plane-manageris running on the node: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> - Proceed to update the next node (repeat the steps above).
What to do if it takes a long time to switch to custom nodes in lower-priority groups?
When using multiple node groups with different priorities in a cloud cluster (the spec.cloudInstances.priority parameter), switching to nodes from groups with lower priority can take a long time. An example of this scenario is when groups of preemptible nodes (spot, etc.) are set to the highest priority, and if such instances are unavailable, ordering nodes from other groups takes a very long time.
When provisioning nodes, the cluster autoscaler sequentially selects the group with the highest priority that is not in a backoff state. A backoff is a temporary lock on a group following a failed attempt to provision a node (for example, due to a lack of instances of the required type in the cloud).
How it works when using multiple node groups:
- The cluster autoscaler attempts to provision a node in the group with the highest priority.
- If the node is not provisioned within the time specified by the
max-node-provision-timeparameter, the attempt is considered a failure. - The group is marked as
failedand blocked for the duration specified in theinitial-node-group-backoff-durationparameter. - If the same group fails again, the lockout time is doubled, but does not exceed the time specified in the
max-node-group-backoff-durationparameter. - The cluster autoscaler selects the next highest-priority group that is not locked out.
Here:
| Parameter | Default value | Description |
|---|---|---|
initial-node-group-backoff-duration |
5 minutes | Initial duration of the group lockout after the first failure. Doubles after each failed node ordering attempt |
max-node-group-backoff-duration |
30 minutes | Maximum duration of the group lockout |
max-node-provision-time |
15 minutes | The time after which the cluster autoscaler considers a node provisioning attempt to have failed |
If these parameters are set to their default values, switching to node ordering in lower-priority groups may take a considerable amount of time (for more details, see this example).
These settings can be adjusted to speed up the switching of nodes in lower-priority groups.
To set the desired values for the initial-node-group-backoff-duration, max-node-group-backoff-duration, and max-node-provision-time parameters, edit the cluster-autoscaler Deployment object in the d8-cloud-instance-manager namespace. The parameters are specified in the args field of the cluster-autoscaler container. Example:
...
containers:
- name: cluster-autoscaler
args:
- --initial-node-group-backoff-duration=1m # The initial duration of the group lockout after the first failure has been reduced.
- --max-node-provision-time=5m # The time after which the cluster autoscaler considers a node request to have failed has been reduced.
...
If you encounter issues with node ordering in a cluster with a single node group
If cloud cluster uses only one node group (for example, exclusively for ordering spot or preemptible nodes) and you encounter issues with ordering such nodes during automatic scaling, follow these steps:
- Create one or more InstanceClass objects to be used when creating instances in the cluster. In the InstanceClass, specify node types that differ from those listed in the group mentioned above.
In DP, InstanceClass objects vary depending on the provider. Examples: AWSInstanceClass, AzureInstanceClass, YandexInstanceClass.
- Create one or more new node groups (NodeGroup). In the
spec.cloudInstances.classReferenceparameter, specify the InstanceClass objects created in the previous step. In thespec.cloudInstances.priorityparameter, set the priority of the node group. - If necessary, modify the
max-node-provision-time,max-node-group-backoff-duration, andinitial-node-group-backoff-durationparameters to speed up switching to lower-priority groups.
Example of the node ordering process with default settings
Suppose there are 3 groups of nodes with different priorities:
- Group A (priority 50)
- Group B (priority 30)
- Group C (priority 0)
In this case, the node ordering process might be as follows:
| Time | Event |
|---|---|
| 10:00 | The cluster autoscaler attempts to order a node in A |
| 10:15 | The attempt to provision a node in A within 15 minutes (max-node-provision-time) fails → A blocked for 5 minutes (initial-node-group-backoff-duration) |
| 10:15:xx | The cluster autoscaler attempts to order a node in B (next in priority, not blocked) |
| 10:30 | The attempt to provision a node in B within 15 minutes (max-node-provision-time) fails → B blocked for 5 minutes (initial-node-group-backoff-duration) |
| 10:30:xx | The cluster autoscaler attempts to order a node in A again, as the lockout period (the default value for initial-node-group-backoff-duration is 5 minutes) has ended |
| 10:45 | The attempt to order a node in A fails again → A is blocked for 10 minutes (initial-node-group-backoff-duration for A is doubled) |
| … | And so on, until the lockout time for A and B exceeds 15 minutes (max-node-provision-time). In this case, the queue may not reach group C for about 1.5 hours |
What to do if the resources generated by an object are not created after adding the object?
If the required resources do not appear after creating an object in the system (for example, dexAuthenticator), follow these steps:
-
Check if there are any critical alerts in the cluster that may block the creation of the required objects. To do this, use the command:
d8 k get clusteralerts.deckhouse.ioExample output:
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 firingFor more information about alerts, see the The list of alerts section.
-
Check the Deckhouse task queue:
d8 s queue listExample output (queues are empty):
Summary: - 'main' queue: empty. - 88 other queues (0 active, 88 empty): 0 tasks. - no tasks to handle.If there are many unprocessed or long-running tasks in the queue, this may indicate problems.
-
Analyze DP logs and events:
-
To view logs in real time, use the command:
d8 k -n d8-system logs -f -l app=deckhouseExample output:
{"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"}When analyzing logs, pay special attention to warnings (
WARNING) and error messages (ERROR). -
To view events, use the command:
d8 k -n d8-system get eventsExample output:
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"
When analyzing events, pay special attention to those with the
Warningtype. -
Deckhouse
How can I check DP versions available in different release channels?
For information about the current DP versions across all release channels, visit releases.deckhouse.io.
How to check the job queue in Deckhouse?
How to check the status of all Deckhouse task queues?
To view the status of all Deckhouse job queues, run the following command:
d8 s queue list
Example output (queues are empty):
Summary:
- 'main' queue: empty.
- 88 other queues (0 active, 88 empty): 0 tasks.
- no tasks to handle.
How to view the status of the main task queue?
To view the status of the Deckhouse main task queue, run the following command:
d8 s queue main
Example output (38 tasks in the main queue):
Queue 'main': length 38, status: 'run first task'
Example output (the main queue is empty):
Queue 'main': length 0, status: 'waiting for task 0s'
What should I do if DP is not receiving updates from the configured channel?
- Ensure the correct release channel is configured.
-
Check that DNS resolution for the Deckhouse image registry is working correctly.
Get and compare the IP addresses of
registry.deckhouse.iofrom both a node and thedeckhousePod. They must match.Example of obtaining an IP of
registry.deckhouse.iofrom a node:getent ahosts registry.deckhouse.ioExample output:
185.193.90.38 STREAM registry.deckhouse.io 185.193.90.38 DGRAM 185.193.90.38 RAWExample of obtaining an IP of
registry.deckhouse.iofrom thedeckhousePod:d8 k -n d8-system exec -ti svc/deckhouse-leader -c deckhouse -- getent ahosts registry.deckhouse.ioExample output:
185.193.90.38 STREAM registry.deckhouse.io 185.193.90.38 DGRAM registry.deckhouse.ioIf the resulted IPs do not match, check DNS settings on the node. Pay attention to the
searchdomain list in/etc/resolv.conf, which affects name resolution in thedeckhousePod. If thesearchparameter in/etc/resolv.conffile specifies a domain with wildcard DNS resolution configured, this may lead to incorrect IP address resolution for the Deckhouse image registry (see example below).
Example DNS settings that may cause issues resolving the DP image registry IP address
Below is an example of how DNS settings may result in different resolution behavior on the node and in a Kubernetes Pod:
-
Example of
/etc/resolv.confon the node:nameserver 10.0.0.10 search company.myOn nodes, the default
ndotsetting is 1 (options ndots:1), while in Kubernetes Pods, it’s 5. This causes different resolution logic for DNS names with 5 or fewer dots on a node and on the Pod. -
The DNS zone
company.myhas a wildcard entry*.company.mythat resolves to10.0.0.100. This means any undefined DNS name in thecompany.myzone resolves to10.0.0.100.
Taking into account the search parameter in /etc/resolv.conf, when accessing registry.deckhouse.io from a node,
the system will attempt to resolve the IP address for registry.deckhouse.io
(because it considers it fully qualified due to the default options ndots:1 setting).
However, when accessing registry.deckhouse.io from a Kubernetes Pod,
considering the options ndots:5 setting used by default in Kubernetes and the search parameter,
the system will first attempt to resolve the name registry.deckhouse.io.company.my.
This name will resolve to the IP address 10.0.0.100 because,
according to the company.my DNS zone’s wildcard configuration,
*.company.my is resolved to 10.0.0.100.
As a result, the Pod will fail to connect to the registry.deckhouse.io host and will be unable to download information about available Deckhouse updates.
Does Deckhouse support realtime (rt) and low-latency Linux kernels?
In general, realtime (rt) and lowlatency kernels are supported with no extra configuration needed for Deckhouse Platform. Such kernels have been tested with DP EE version v1.75.7 and above on the following OSes and kernels:
- 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
How can I know when a new DP version is available for the cluster?
As soon as a new version appears on the configured release channel:
- The
DeckhouseReleaseIsWaitingManualApprovalalert will appear if the cluster is in manual update mode. - A new DeckhouseRelease custom resource will be created.
To see the list of releases, run
d8 k get deckhousereleases. If the new version is inPendingstate, it means it hasn’t been installed yet. Possible reasons:- Manual update mode is enabled.
- Automatic update mode is enabled and update windows are scheduled, but the window hasn’t started yet.
- Automatic update mode is enabled and update windows are not scheduled,
but the update is delayed by a random period to reduce load on the container image registry.
The
status.messagefield of the DeckhouseRelease resource will show a corresponding message. - The
update.notification.minimalNotificationTimeparameter is set, and the delay period hasn’t elapsed.
How can I receive information about upcoming updates in advance?
You can get information about upcoming minor DP version updates on the release channel in one of the following ways:
- Enable manual update mode.
A new DeckhouseRelease resource and the
DeckhouseReleaseIsWaitingManualApprovalalert will appear when a new version is available. - Enable automatic update mode and set a delay using the
minimalNotificationTimeparameter. A new DeckhouseRelease resource will appear when a new version is available. If you also set a webhook URL in theupdate.notification.webhookparameter, a notification will be sent about the upcoming update.
How can I tell that the update was successful?
If the DeckhouseUpdating alert is gone, the update has finished.
You can also check the status of DP releases in the cluster with the following command:
d8 k get deckhouserelease
Example output:
NAME PHASE TRANSITIONTIME MESSAGE
v1.46.8 Superseded 13d
v1.46.9 Superseded 11d
v1.47.0 Superseded 4h12m
v1.47.1 Deployed 4h12m
The Deployed status means the cluster has switched to the corresponding version,
but it doesn’t guarantee that the update has been successful.
To ensure the update completed successfully, check the state of the deckhouse Pod with the following command:
d8 k -n d8-system get pods -l app=deckhouse
Example output:
NAME READY STATUS RESTARTS AGE
deckhouse-7844b47bcd-qtbx9 1/1 Running 0 1d
- If the Pod is
Runningand shows1/1underREADY, it means the update completed successfully. - If the Pod is
Runningbut shows0/1underREADY, it means the update is still in progress. If it stays like this for more than 20–30 minutes, it may indicate a problem with DP that requires investigation. - If the Pod is not
Running, it may indicate a problem with DP that requires investigation.
If something goes wrong
-
Check the logs using the following command:
d8 k -n d8-system logs -f -l app=deckhouse | jq -Rr 'fromjson? | .msg' -
Collect debug information and contact DP technical support.
How can I tell that an update is in progress?
During an update:
- The
DeckhouseUpdatingalert is active. - The
deckhousePod is not in theReadystate. If the Pod stays in a non-Readystate for a long time, it may indicate an issue with DP that requires investigation.
What to do if there are problems updating DP?
Deckhouse Platform update fails, one or more Deckhouse pods are in an unworkable state
If the Deckhouse Platform update fails, one or more Deckhouse pods in the d8-system namespace are in an unworkable state. Perform the following steps:
-
Check the Deckhouse logs using the command:
d8 k -n d8-system logs -f -l app=deckhouse | jq -Rr 'fromjson? | .msg'If there are any problems, information about them will be included in the output. When analyzing logs, pay special attention to warnings (
WARNING) and error messages (ERROR). -
Check Deckhouse events using the command:
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'Pod events contain key information about problems (e.g., planning errors, image loading errors, etc.). When analyzing events, pay special attention to those with the
Warningtype.Example output:
Type Reason Age From Message ---- ------ ---- ---- ------- Warning Unhealthy 4m44s (x1918 over 154m) kubelet Readiness probe failed: HTTP probe failed with statuscode: 500
DP update is stuck in the Release is suspended status
The status Release is suspended indicates that it has been postponed and is currently unavailable (not recommended) for installation. In this case, it is recommended to remain on the latest available release or on the one currently installed (it will have the status Deployed).
To view the list of releases, use the command:
d8 k get deckhousereleases.deckhouse.io
Example output:
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
IAM
What to do if there are problems applying DexProvider settings?
If you have changed the DexProvider settings in the user-authn module and one of the following problems occurs:
- No changes are visible (settings are not applied).
- When attempting to log in to the platform’s web interface with any type of authorization, a
500 Internal Server Erroroccurs without a detailed description.
Perform the following steps:
-
Check the status of the dex deployment:
d8 k -n d8-user-authn get podExample output:
NAME READY STATUS RESTARTS AGE dex-5ddb779b7d-6pbhs 2/2 Running 0 20h kubeconfig-generator-7c46977b9f-5kdmc 1/1 Running 0 20hIf the module is functioning properly and the correct configuration is specified in DexProvider, all pods will have the status
Running. -
Check the logs for the problematic pod:
d8 k -n d8-user-authn logs dex-<pod-name>Based on the information from the logs, correct the configuration in the DexProvider resource and wait for the dex pods to restart. Within a few minutes, the pods will restart automatically, and the platform’s web interface (located at
console.<CLUSTER_NAME_TEMPLATE>) will become available and will reflect the changes made to the DexProvider resource.
Kubernetes and Scheduling
What to do when the API server is overloaded?
The following signs may indicate problems with API server load and memory consumption:
kubectl (d8)responds slowly or does not respond at all (commands are executed slowly or not at all).- Pods are recreated in the cluster for no apparent reason.
If these signs are present, perform the following actions:
-
Check the resource consumption of API server pods. To do this, use the command:
d8 k -n kube-system top po -l component=kube-apiserverPay attention to
MEMORYconsumption andCPU.Example output:
NAME CPU(cores) MEMORY(bytes) kube-apiserver-sandbox1-master-0 251m 1476Mi -
Check the metrics in Grafana.
To view the metrics, open the dashboard “Home” → “Dashboards” → “Kubernetes Cluster” → “Control Plane Status”. Review the graphs related to the API server (“Kube-apiserver CPU Usage”, “Kube-apiserver Memory Usage”, “Kube-apiserver latency”, etc.).
-
Review the API server audit logs to identify the source of high memory consumption. One common cause of high memory consumption is a large number of requests.
How to check the Kubernetes version in use?
To check the Kubernetes version in use, run the command:
d8 k get nodes
Example output:
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
Network
Is the ingress-nginx module supported? Will it affect passing a PCI DSS audit?
The ingress-nginx module remains supported by Deckhouse Platform for the entire platform support lifecycle and does not depend on the upstream project’s status. The Deckhouse team tracks vulnerabilities in the controller and related components (NGINX, Lua modules, base images), delivers fixes in DP releases, and provides a migration path toward Gateway API.
Flant is the vendor responsible for support. Together with ongoing module maintenance and vulnerability management, this allows passing a PCI DSS audit and meets expectations for vendor accountability for a platform component.
Virtualization
How to use Ansible to provision virtual machines?
Ansible is an automation tool for running tasks on remote servers over SSH. This example shows how to use Ansible with virtual machines (VMs) in the demo-app project.
The example assumes that:
demo-appnamespace contains a VM namedfrontend.- VM has a
clouduser with SSH access. - Private SSH key on the machine where Ansible runs is stored in
/home/user/.ssh/id_rsa.
-
Create an
inventory.yamlfile:--- all: vars: ansible_ssh_common_args: '-o ProxyCommand="d8 v port-forward --stdio=true %h %p"' # Default user for SSH access. ansible_user: cloud # Path to private key. ansible_ssh_private_key_file: /home/user/.ssh/id_rsa hosts: # Host name in the format <VM_NAME>.<NAMESPACE>. frontend.demo-app: -
Check the virtual machine
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
If you do not want to use an inventory file, pass all parameters on the command line:
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
How to automatically generate inventory for Ansible?
The d8 v ansible-inventory command requires d8 v0.27.0 or higher.
The command works only for virtual machines that have the main cluster network (Main) connected.
Instead of manually creating an inventory file, you can use the d8 v ansible-inventory command, which automatically generates an Ansible inventory from virtual machines in the specified namespace. The command is compatible with the ansible inventory script interface.
Only machines in the Running phase that have an assigned IP address get into the inventory. Host names are formatted as <VM_NAME>.<NAMESPACE> (for example, frontend.demo-app).
-
Optionally set host variables via annotations (for example, the SSH user):
d8 k -n demo-app annotate vm frontend vars.ansible.deckhouse.io/ansible_user="cloud" -
Run Ansible with a dynamically generated inventory:
ANSIBLE_INVENTORY_ENABLED=yaml ansible -m shell -a "uptime" all -i <(d8 v ansible-inventory -n demo-app -o yaml)
The <(...) construct is necessary because Ansible expects a file or script as the source of the host list. Simply specifying the command in quotes won’t work, because Ansible tries to execute the string as a script. The <(...) construct passes the command output as a file that Ansible can read.
-
Or save the inventory to a file and run the check:
d8 v ansible-inventory --list -o yaml -n demo-app > inventory.yaml ansible -m shell -a "uptime" -i inventory.yaml all
How to use cloud-init to configure virtual machines?
Cloud-init is used for initial guest OS configuration on first boot. The configuration is written in YAML and starts with the #cloud-config directive.
When using cloud images (for example, official distribution images), you must provide a cloud-init configuration. Without it, some distributions do not configure network connectivity, and the virtual machine becomes unreachable on the network, even if the main network (Main) is attached.
In addition, cloud images do not allow login by default — you must either add SSH keys for the default user or create a new user with SSH access. Otherwise, you will not be able to access the virtual machine.
Updating and installing packages
Example cloud-config for updating the system and installing packages from a list:
#cloud-config
# Update package lists.
package_update: true
# Upgrade installed packages to latest versions.
package_upgrade: true
# List of packages to install.
packages:
- nginx
- curl
- htop
# Commands to run after package installation.
runcmd:
- systemctl enable --now nginx.service
Creating a user
Example cloud-config for creating a local user with a password and SSH key:
#cloud-config
# List of users to create.
users:
# Username.
- name: cloud
# Password hash.
passwd: "<PASSWORD_HASH>"
# Do not lock the account.
lock_passwd: false
# Sudo privileges without a password prompt.
sudo: ALL=(ALL) NOPASSWD:ALL
# Default shell.
shell: /bin/bash
# SSH keys for access.
ssh-authorized-keys:
- <SSH_PUBLIC_KEY>
# Allow password authentication via SSH.
ssh_pwauth: true
To generate a password hash for the passwd field, run:
mkpasswd --method=SHA-512 --rounds=4096
Creating a file with required permissions
Example cloud-config for creating a file with specified access permissions:
#cloud-config
# List of files to create.
write_files:
# File path.
- path: /opt/scripts/start.sh
# File content.
content: |
#!/bin/bash
echo "Starting application"
# File owner, user and group.
owner: cloud:cloud
# Access permissions in octal format.
permissions: '0755'
Configuring disk and filesystem
Example cloud-config for disk partitioning, filesystem creation, and mounting:
#cloud-config
# Disk partitioning setup.
disk_setup:
# Disk device.
/dev/sdb:
# Partition table type, gpt or mbr.
table_type: gpt
# Automatically create partitions.
layout: true
# Do not overwrite existing partitions.
overwrite: false
# Filesystem setup.
fs_setup:
# Filesystem label.
- label: data
# Filesystem type.
filesystem: ext4
# Partition device.
device: /dev/sdb1
# Automatically detect partition.
partition: auto
# Filesystem mounting.
mounts:
# [device, mount_point, fs_type, options, dump, pass]
- ["/dev/sdb1", "/mnt/data", "ext4", "defaults", "0", "2"]
Configuring network interfaces for additional networks
The settings described in this section apply only to additional networks. The main network (Main) is configured automatically via cloud-init and does not require manual configuration.
Additional networks are configured manually via cloud-init. The write_files block creates the configuration files, and the runcmd block applies the settings.
Connecting additional networks to a virtual machine is covered in Additional network interfaces.
The following examples cover common ways to configure networking in the guest OS:
- systemd-networkd
- Netplan (Ubuntu)
- ifcfg (RHEL/CentOS)
- Alpine Linux
Example cloud-config for distributions that use systemd-networkd (Debian, CoreOS, and others):
#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
Example cloud-config for Ubuntu and other systems that use 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
Example cloud-config for RHEL-compatible distributions that use the ifcfg scheme and 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
Example cloud-config for distributions that use the traditional /etc/network/interfaces format (Alpine and similar):
#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
How to increase the DVCR size?
The DVCR volume size is set in the virtualization module ModuleConfig (spec.settings.dvcr.storage.persistentVolumeClaim.size). The new value must be greater than the current one.
-
Check the current DVCR size:
d8 k get mc virtualization -o jsonpath='{.spec.settings.dvcr.storage.persistentVolumeClaim}'Example output:
{"size":"58G","storageClass":"linstor-thick-data-r1"} -
Increase
sizeusingpatch(set the value you need):d8 k patch mc virtualization \ --type merge -p '{"spec": {"settings": {"dvcr": {"storage": {"persistentVolumeClaim": {"size":"59G"}}}}}}'Example output:
moduleconfig.deckhouse.io/virtualization patched -
Verify that ModuleConfig shows the new size:
d8 k get mc virtualization -o jsonpath='{.spec.settings.dvcr.storage.persistentVolumeClaim}'Example output:
{"size":"59G","storageClass":"linstor-thick-data-r1"} -
Check the current DVCR status:
d8 k get pvc dvcr -n d8-virtualizationExample output:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE dvcr Bound pvc-6a6cedb8-1292-4440-b789-5cc9d15bbc6b 57617188Ki RWO linstor-thick-data-r1 7d
How to change the DVCR StorageClass when a PVC already exists?
You can change the DVCR storage StorageClass only by recreating the PVC. All images previously loaded into DVCR are lost, along with data for existing ClusterVirtualImage and VirtualImage resources.
The spec.settings.dvcr.storage.persistentVolumeClaim.storageClassName field in the virtualization module ModuleConfig sets the StorageClass for the virtual machine image storage volume (DVCR). While a PVC for that volume exists in the d8-virtualization namespace, you cannot change the field via the API.
You cannot change storageClassName on an existing PVC in place, and DVCR data is not migrated between storage classes.
To change the DVCR StorageClass, perform the following steps:
-
Stop DVCR:
d8 k -n d8-virtualization scale deployment dvcr --replicas=0 -
List PVCs in the
d8-virtualizationnamespace and find the PVC for the DVCR volume:d8 k get pvc -n d8-virtualization -
Delete the PVC you found. Replace
<PVC_NAME>with the resource name. If the command fails because of insufficient permissions, run it assystem:sudouser:d8 k --as system:sudouser -n d8-virtualization delete pvc/<PVC_NAME> -
Set the new StorageClass in ModuleConfig, substituting the class you need for
<STORAGE_CLASS_NAME>:d8 k patch mc virtualization --type merge -p '{"spec":{"settings":{"dvcr":{"storage":{"persistentVolumeClaim":{"storageClassName":"<STORAGE_CLASS_NAME>"}}}}}}'Example output:
moduleconfig.deckhouse.io/virtualization patched -
Start DVCR:
d8 k -n d8-virtualization scale deployment dvcr --replicas=1 -
Verify the PVC:
d8 k get pvc -n d8-virtualizationExample output:
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
The storage for the chosen StorageClass must be reachable from the nodes where DVCR runs: system nodes, or worker nodes if the cluster has no system nodes.
How to install an operating system in a virtual machine from an ISO image?
Below is a typical Windows guest OS installation scenario from an ISO image. Before you begin, host the ISO on an HTTP endpoint reachable from the cluster.
-
Create an empty VirtualDisk for OS installation:
apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualDisk metadata: name: win-disk namespace: default spec: persistentVolumeClaim: size: 100Gi storageClassName: local-path -
Create ClusterVirtualImage resources for the Windows OS ISO and the VirtIO driver ISO:
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" -
Create a virtual machine (VM):
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 -
Start the virtual machine:
d8 v start win-vm -
Connect to the VM console and complete the OS installation and VirtIO drivers using the graphical installer.
VNC connection:
d8 v vnc -n default win-vm -
After the installation is complete, restart the virtual machine.
-
For further work, connect via VNC again:
d8 v vnc -n default win-vm
How to create a golden image for Linux?
A golden image is a pre-configured virtual machine (VM) image that can be used to quickly create new VMs with pre-installed software and settings.
-
Create a virtual machine, install the required software on it, and perform all necessary configurations.
-
Install and configure qemu-guest-agent (recommended):
-
For RHEL/CentOS:
yum install -y qemu-guest-agent -
For Debian/Ubuntu:
apt-get update apt-get install -y qemu-guest-agent
-
-
Enable and start the service:
systemctl enable qemu-guest-agent systemctl start qemu-guest-agent -
Set the machine run policy to
AlwaysOnUnlessStoppedManually, otherwise you will not be able to shut it down. -
Prepare the image. Clean unused filesystem blocks:
fstrim -v / fstrim -v /boot -
Clean network settings:
-
For 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* -
For Debian/Ubuntu:
rm -f /etc/network/interfaces.d/*
-
-
Clean system identifiers:
echo -n > /etc/machine-id rm -f /var/lib/dbus/machine-id ln -s /etc/machine-id /var/lib/dbus/machine-id -
Remove the SSH host keys:
rm -f /etc/ssh/ssh_host_* -
Clean the systemd journal:
journalctl --vacuum-size=100M --vacuum-time=7d -
Clean package manager cache:
-
For RHEL:
yum clean all -
For Debian/Ubuntu:
apt-get clean
-
-
Clean temporary files:
rm -rf /tmp/* rm -rf /var/tmp/* -
Clean logs:
find /var/log -name "*.log" -type f -exec truncate -s 0 {} \; -
Clean command history:
history -c -
On RHEL, reset and restore the SELinux contexts in one of two ways.
Restore the contexts right away:
restorecon -R /Or schedule a relabel for the next boot:
touch /.autorelabel -
Verify that
/etc/fstabreferences UUID orLABELrather than names like/dev/sdX:blkid cat /etc/fstab -
Reset cloud-init state (logs and seed):
cloud-init clean --logs --seed -
Perform final synchronization and buffer cleanup:
sync echo 3 > /proc/sys/vm/drop_caches -
Shut down the virtual machine:
poweroff -
Create a VirtualImage resource that references the prepared VM’s 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> EOFOr create a ClusterVirtualImage resource so the image is available cluster-wide for all projects:
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> EOFHere,
<IMAGE_NAME>is the name of the image being created,<NAMESPACE>is the namespace of the prepared machine, and<SOURCE_DISK_NAME>is the name of its disk. -
Create a new VirtualDisk from the resulting image:
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> EOFHere,
<VM_DISK_NAME>is the name of the disk of the new machine.
After completing these steps, you will have a golden image that can be used to quickly create new virtual machines with pre-installed software and configurations.
How to restore the cluster if images from registry.deckhouse.io cannot be pulled after a license change?
After a license change on a cluster with containerd v1 and removal of the outdated license, images from registry.deckhouse.io may stop being pulled. Nodes then retain the outdated configuration file /etc/containerd/conf.d/dvcr.toml, which is not removed automatically. Because of it, the registry module does not start, and without it DVCR does not work.
Applying a NodeGroupConfiguration (NGC) manifest removes the file on the nodes. After the registry module starts, delete the manifest, since this is a one-time fix.
-
Save the manifest to a file (for example,
containerd-dvcr-remove-old-config.yaml):apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: containerd-dvcr-remove-old-config.sh spec: weight: 32 # Must be in range 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 -
Apply the saved manifest:
d8 k apply -f containerd-dvcr-remove-old-config.yaml -
Verify that the
registrymodule is running:d8 k -n d8-system -o yaml get secret registry-state | yq -C -P '.data | del .state | map_values(@base64d) | .conditions = (.conditions | from_yaml)'Example output when the
registrymodule has started successfully:conditions: # ... - lastTransitionTime: "..." message: "" reason: "" status: "True" type: Ready -
Delete the one-time NodeGroupConfiguration manifest:
d8 k delete -f containerd-dvcr-remove-old-config.yaml
The migration procedure is covered in Migrating container runtime to containerd v2.
How to redirect traffic to a virtual machine?
A virtual machine runs in a Kubernetes cluster, so traffic reaches it the same way it reaches any other workload. Routing is handled by the standard Kubernetes Service resource, which selects targets by labels.
-
Create a service with the required settings.
For example, consider a virtual machine with the label
vm: frontend-0, an HTTP service exposed on ports 80 and 443, and SSH access on port 22:apiVersion: virtualization.deckhouse.io/v1alpha2 kind: VirtualMachine metadata: name: frontend-0 namespace: dev labels: vm: frontend-0 spec: ... -
To route network traffic to the virtual machine’s ports, create a service:
This service listens on ports 80 and 443 and forwards traffic to the corresponding ports of the target virtual machine. SSH access from outside is provided on port 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
Why is only one connection method available for a virtual machine?
You can connect to a virtual machine (VM) via the serial console (d8 v console) or VNC (d8 v vnc).
These methods use different communication channels with the guest OS and depend on its configuration.
Both methods are covered in Connecting to a virtual machine.
The sections below describe common situations where only one connection method works.
Why does VNC not work when the serial console is available?
VNC displays the guest OS screen and requires virtual terminal support in the kernel. The serial console works independently of the graphics subsystem.
Check in the guest OS whether virtual terminal support is enabled in the kernel configuration:
cat /boot/config-$(uname -r) | grep CONFIG_VT
The output should show CONFIG_VT=y:
CONFIG_VT=y
If the output shows CONFIG_VT is not set, rebuild the kernel with the option enabled or use an OS image with a suitable kernel configuration.
Why does the serial console not work when VNC is available?
The serial console connects to the ttyS0 port in the guest OS.
If the getty service for this port is not running, d8 v console will not show a login prompt even though VNC continues to work.
In the guest OS, enable and start the serial-getty service for ttyS0:
sudo systemctl enable --now serial-getty@ttyS0.service
Then connect to the serial console again.
How to provide a Windows answer file (Sysprep)?
Unattended Windows installation uses an answer file (unattend.xml or autounattend.xml).
The example answer file below:
- Sets the English UI language and keyboard layout.
- Connects the
VirtIOdrivers for the setup stage (the order of devices inblockDeviceRefson the VirtualMachine resource must match the paths in the file). - Creates disk layout for installation with EFI.
- Creates the
cloudadministrator and the regularuseraccount.
<p><b>Example of the contents of the autounattend.xml file…</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>en-US<span class="nt"></UILanguage></span>
<span class="nt"></SetupUILanguage></span>
<span class="nt"><InputLocale></span>0409:00000409<span class="nt"></InputLocale></span>
<span class="nt"><SystemLocale></span>en-US<span class="nt"></SystemLocale></span>
<span class="nt"><UILanguage></span>en-US<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<span class="nt"></InputLocale></span>
<span class="nt"><SystemLocale></span>en-US<span class="nt"></SystemLocale></span>
<span class="nt"><UILanguage></span>en-US<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>Replace <code class="language-plaintext highlighter-rouge"><PRODUCT_KEY></code> with your Windows product key, and <code class="language-plaintext highlighter-rouge"><ADMIN_PASSWORD></code> and <code class="language-plaintext highlighter-rouge"><USER_PASSWORD></code> with the passwords of the accounts being created. Windows reads these passwords from the file in plain text, so don’t leave the finished answer file on a shared resource.</p>
<ol>
<li>
<p>Save the answer file as <code class="language-plaintext highlighter-rouge">autounattend.xml</code> (use the example above or adjust it to your needs).</p>
</li>
<li>
<p>Create a secret with the type <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>Create a virtual machine that will use the answer file during installation. Specify <code class="language-plaintext highlighter-rouge">provisioning</code> with type <code class="language-plaintext highlighter-rouge">SysprepRef</code> in the specification. If necessary, add other Base64-encoded files to the specification required for the answer file scripts to run successfully.</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>Example of the contents of the autounattend.xml file…</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>en-US<span class="nt"></UILanguage></span>
<span class="nt"></SetupUILanguage></span>
<span class="nt"><InputLocale></span>0409:00000409<span class="nt"></InputLocale></span>
<span class="nt"><SystemLocale></span>en-US<span class="nt"></SystemLocale></span>
<span class="nt"><UILanguage></span>en-US<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<span class="nt"></InputLocale></span>
<span class="nt"><SystemLocale></span>en-US<span class="nt"></SystemLocale></span>
<span class="nt"><UILanguage></span>en-US<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>Replace <code class="language-plaintext highlighter-rouge"><PRODUCT_KEY></code> with your Windows product key, and <code class="language-plaintext highlighter-rouge"><ADMIN_PASSWORD></code> and <code class="language-plaintext highlighter-rouge"><USER_PASSWORD></code> with the passwords of the accounts being created. Windows reads these passwords from the file in plain text, so don’t leave the finished answer file on a shared resource.</p>
<ol>
<li>
<p>Save the answer file as <code class="language-plaintext highlighter-rouge">autounattend.xml</code> (use the example above or adjust it to your needs).</p>
</li>
<li>
<p>Create a secret with the type <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>Create a virtual machine that will use the answer file during installation. Specify <code class="language-plaintext highlighter-rouge">provisioning</code> with type <code class="language-plaintext highlighter-rouge">SysprepRef</code> in the specification. If necessary, add other Base64-encoded files to the specification required for the answer file scripts to run successfully.</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>