This section describes how to add nodes from Deckhouse Virtualization Platform (DVP) to an existing static DKP cluster.
Integration with DVP uses the cloud-provider-dvp module. It enables DKP to interact with the DVP cluster API, create virtual machines, connect the created VMs to an existing Kubernetes cluster, and manage the lifecycle of nodes through Cluster API mechanisms.
This section describes two ways to add nodes:
- Automatically creating nodes in DVP. DKP creates virtual machines through the DVP API. VM parameters are specified using the DVPInstanceClass resource, while the required number of nodes and placement zones are specified using the NodeGroup resource with the
CloudEphemeraltype. - Connecting manually created nodes using a bootstrap script. A virtual machine is created in advance by the user and connected to the cluster using a DKP bootstrap script. This scenario uses a NodeGroup with the
CloudStatictype.
Prerequisites
Before you begin, make sure that the following requirements are met:
- The cluster is created with the
clusterType: Staticparameter. - Network connectivity is configured between the network of the static DKP cluster nodes and the network of virtual machines in DVP. For details, see Network requirements. Nodes created in DVP have access to the Kubernetes API of the target DKP cluster, DNS, and the required addresses according to the Network interaction and Configuring network policies sections. If Cilium is used with pod traffic tunneling, the
tunnelModemode is selected according to the network connectivity between sites. The Kubernetes API of the DVP cluster is accessible from the DKP cluster. - The requirements from the Preparing the environment section are met:
- a ServiceAccount has been created to access the DVP API;
- a kubeconfig has been generated to connect to the DVP API;
- a namespace has been prepared where virtual machines and disks will be created.
- A Linux OS image with
cloud-initsupport is available in DVP, for exampleubuntu-24-04-lts. - A suitable VirtualMachineClass is available in DVP, for example
amd-epyc-gen-3. - A StorageClass for root disks of virtual machines is available in DVP, for example
replicated. - If a virtual machine template is used, make sure that it contains only one disk.
DVPInstanceClass parameters use resources from the DVP cluster: VirtualMachineClass, ClusterVirtualImage, VirtualImage, VirtualDisk, and StorageClass from DVP, not from the target DKP cluster.
Make sure there are no StorageClass resources in the static DKP cluster whose names match the names of StorageClass resources in the DVP cluster.
When the cloud-provider-dvp module is enabled, the corresponding StorageClass resources are automatically synchronized from DVP to the DKP cluster. If a StorageClass with the same name already exists in the static cluster, a resource conflict may occur, causing the module installation or upgrade to fail.
Adding automatically created nodes
-
On the administrator’s machine where access to the DVP cluster is configured, prepare a kubeconfig for the
cloud-provider-dvpmodule to access the DVP API.Follow the steps in the “Preparing the environment” section and encode the generated kubeconfig in Base64:
export DVP_PROVIDER_KUBECONFIG="./kubeconfig" export DVP_KUBECONFIG_B64="$(base64 -w0 ${DVP_PROVIDER_KUBECONFIG})" -
Specify the DVP namespace where virtual machines and disks will be created:
export DVP_NAMESPACE="<DVP_NAMESPACE>" -
Specify the DVP zone where nodes will be created.
Currently, zoning in DVP is under development, so use the
defaultvalue for thezonesparameters in ModuleConfig and NodeGroup:export DVP_ZONE="default"If necessary, you can check the topology labels of nodes in the DVP cluster:
d8 k get nodes -L topology.kubernetes.io/region,topology.kubernetes.io/zoneThe zone value in ModuleConfig and NodeGroup must match. Currently, only the
defaultvalue is available in DVP. -
Create a file with the
cloud-provider-dvpmodule configuration. For example,cloud-provider-dvp-mc.yaml:cat > cloud-provider-dvp-mc.yaml <<EOF apiVersion: deckhouse.io/v1alpha1 kind: ModuleConfig metadata: name: cloud-provider-dvp spec: enabled: true version: 1 settings: provider: kubeconfigDataBase64: ${DVP_KUBECONFIG_B64} namespace: ${DVP_NAMESPACE} zones: - ${DVP_ZONE} EOFThe manifest automatically uses the values of the environment variables set in the previous steps:
DVP_KUBECONFIG_B64,DVP_NAMESPACE, andDVP_ZONE. -
Apply ModuleConfig:
d8 k apply -f cloud-provider-dvp-mc.yaml -
Wait until the
cloud-provider-dvpmodule is enabled:d8 k get module cloud-provider-dvp -o wideThe module must switch to the
Readystate, and the pods in thed8-cloud-provider-dvpnamespace must be in theRunningstate. -
Make sure that the
node-managermodule is in theReadystate:d8 k get module node-manager -o wideIf the module is in the
Errorstate, check that available DVP zones are specified in ModuleConfig and NodeGroup. -
Make sure that the DVPInstanceClass resource is available in the cluster:
d8 k get crd dvpinstanceclasses.deckhouse.io -
On the administrator’s machine where access to the DVP cluster is configured, check the available virtual machine classes, images, and StorageClasses:
d8 k --kubeconfig ${DVP_PROVIDER_KUBECONFIG} get virtualmachineclasses d8 k --kubeconfig ${DVP_PROVIDER_KUBECONFIG} get clustervirtualimages d8 k --kubeconfig ${DVP_PROVIDER_KUBECONFIG} get storageclassesUse the obtained values when creating DVPInstanceClass.
-
Create a file with DVPInstanceClass and NodeGroup resources. For example,
dvp-instanceclass-nodegroup.yaml:apiVersion: deckhouse.io/v1alpha1 kind: DVPInstanceClass metadata: name: dvp-worker spec: virtualMachine: cpu: cores: 3 coreFraction: 20% memory: size: 6Gi virtualMachineClassName: <VIRTUAL_MACHINE_CLASS_NAME> bootloader: EFI rootDisk: size: 15Gi storageClass: <STORAGE_CLASS_NAME> image: kind: ClusterVirtualImage name: <CLUSTER_VIRTUAL_IMAGE_NAME> --- apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: dvp-worker spec: nodeType: CloudEphemeral cloudInstances: classReference: kind: DVPInstanceClass name: dvp-worker minPerZone: 1 maxPerZone: 1 zones: - defaultWhere:
virtualMachineClassName— name of the VirtualMachineClass in DVP, for exampleamd-epyc-gen-3;rootDisk.storageClass— name of the StorageClass in DVP, for examplereplicated;rootDisk.image.kind— image source type. For a cluster image, useClusterVirtualImage;rootDisk.image.name— name of the OS image in DVP, for exampleubuntu-24-04-lts;cloudInstances.zones— DVP zone where the node will be created. The value must match thezonesvalue in ModuleConfig.
-
Apply the manifest:
d8 k apply -f dvp-instanceclass-nodegroup.yamlAfter the manifest is applied, DKP will start creating a virtual machine in DVP and connect it to the cluster as a node.
-
Check the NodeGroup status:
d8 k get nodegroup dvp-worker -o wide d8 k describe nodegroup dvp-worker -
Check that a new node appears in the DKP cluster:
d8 k get nodes -o wideExample expected output:
NAME STATUS ROLES AGE VERSION INTERNAL-IP dvp-hybrid-master-0 Ready control-plane,master 1h v1.33.10 10.12.0.69 dvp-worker-c75a75c1-twqp4-bjpvl Ready dvp-worker 10m v1.33.10 10.12.3.15
Adding manually created nodes using a bootstrap script
Before you begin, make sure that the following requirements are met:
-
The
cloud-provider-dvpmodule is enabled:d8 k get module cloud-provider-dvp -o wide -
The
cloud-provider-dvpmodule components are in theRunningstate:d8 k -n d8-cloud-provider-dvp get pods -o wide - A virtual machine that will be connected to the cluster has been created in DVP.
- The virtual machine is connected to the DVP network used for hybrid integration with the cluster.
- The virtual machine IP address belongs to the range specified in
internalNetworkCIDRs. - The virtual machine name in DVP matches the hostname inside the operating system.
- SSH access is available on the virtual machine for copying and running the bootstrap script.
- The SSH user can run commands using
sudowithout entering a password. - One of the package managers (
apt/apt-get,yum, orrpm) for a supported OS is installed on the virtual machine.
-
Create a NodeGroup with the
CloudStaticnode type. In this example and the following steps, thecloud-staticname is used:d8 k apply -f - <<EOF apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: cloud-static spec: nodeType: CloudStatic EOF -
Make sure that NodeGroup has been created and synchronized:
d8 k get nodegroup cloud-staticExample expected output:
NAME TYPE READY NODES UPTODATE INSTANCES DESIRED MIN MAX STANDBY STATUS AGE SYNCED cloud-static CloudStatic 0 0 0 1m True -
Get the bootstrap script for the created NodeGroup:
NODE_GROUP=cloud-static d8 k -n d8-cloud-instance-manager get secret manual-bootstrap-for-${NODE_GROUP} \ -o jsonpath='{.data.bootstrap\.sh}' > ${NODE_GROUP}-bootstrap.b64 -
On the master node, verify that the file contains valid Base64 data of the bootstrap script:
base64 -d ${NODE_GROUP}-bootstrap.b64 > /dev/nullCheck the beginning of the decoded content:
base64 -d ${NODE_GROUP}-bootstrap.b64 | head -n 5The decoded content must start with a bash script:
#!/bin/bash ... -
Copy the bootstrap script to the virtual machine being connected:
scp ${NODE_GROUP}-bootstrap.b64 <USER>@<NODE_IP>:/tmp/bootstrap.b64 -
Connect to the virtual machine over SSH:
ssh <USER>@<NODE_IP> -
On the virtual machine, decode the bootstrap script, set permissions, and run it:
base64 -d /tmp/bootstrap.b64 > /tmp/bootstrap.sh chmod +x /tmp/bootstrap.sh sudo bash /tmp/bootstrap.shAfter the bootstrap script starts, it will install the required components, configure the container runtime and kubelet, and connect the node to the cluster.
-
On the master node, check that a new node appears:
d8 k get nodes -o wideExample expected output:
NAME STATUS ROLES AGE VERSION INTERNAL-IP dvp-hybrid-master-0 Ready control-plane,master 1h v1.33.12 10.12.0.69 cloud-static-worker-0 Ready cloud-static 5m v1.33.12 10.12.3.88 -
If connection fails, check the NodeGroup status, events, and bootstrap logs on the virtual machine being connected:
d8 k get nodegroup cloud-static d8 k describe nodegroup cloud-static d8 k get events -A --sort-by=.lastTimestamp | tail -n 100On the virtual machine being connected:
sudo tail -n 120 /var/log/d8/bashible/bootstrap.logIf the logs contain the
Failed to discover node_ip that matches internalNetworkCIDRserror, check that the virtual machine IP address belongs tointernalNetworkCIDRs.