Далее описан процесс добавления узлов из Deckhouse Virtualization Platform (DVP) в существующий статический кластер DKP.

Для интеграции с DVP используется модуль cloud-provider-dvp. Он обеспечивает взаимодействие DKP с API кластера DVP, создание виртуальных машин, подключение созданных ВМ к существующему Kubernetes-кластеру и управление жизненным циклом узлов через механизмы Cluster API.

В разделе описаны два способа добавления узлов:

  • Автоматическое создание узлов в DVP. DKP создаёт виртуальные машины через API DVP. Параметры ВМ задаются ресурсом DVPInstanceClass, а требуемое количество узлов и зоны размещения — ресурсом NodeGroup с типом CloudEphemeral.
  • Подключение вручную созданных узлов через bootstrap-скрипт. Виртуальная машина создаётся пользователем заранее и подключается к кластеру с помощью bootstrap-скрипта DKP. Для такого сценария используется NodeGroup с типом CloudStatic.

Предварительные требования

Перед началом убедитесь, что выполнены следующие условия:

  • Кластер создан с параметром clusterType: Static.
  • Между сетью статических узлов кластера DKP и сетью виртуальных машин в DVP настроена сетевая связность. Создаваемые в DVP узлы имеют доступ к Kubernetes API подключаемого DKP-кластера, DNS и необходимым адресам согласно разделам Сетевое взаимодействие и «Настройка сетевых политик». При использовании Cilium с туннелированием трафика подов выбран режим tunnelMode, соответствующий сетевой связности между площадками. Из кластера DKP доступен Kubernetes API кластера DVP.
  • Выполнены требования из раздела «Подготовка окружения»:
    • создан ServiceAccount для доступа к API DVP;
    • сгенерирован kubeconfig для подключения к API DVP;
    • подготовлен неймспейс, в котором будут создаваться виртуальные машины и диски.
  • В DVP доступен образ ОС Linux с поддержкой cloud-init, например ubuntu-24-04-lts.
  • В DVP доступен подходящий VirtualMachineClass, например amd-epyc-gen-3.
  • В DVP доступен StorageClass для корневых дисков виртуальных машин, например replicated.
  • Если используется шаблон виртуальной машины, убедитесь, что он содержит только один диск.

В параметрах DVPInstanceClass используются ресурсы кластера DVP: VirtualMachineClass, ClusterVirtualImage, VirtualImage, VirtualDisk и StorageClass из DVP, а не из подключаемого DKP-кластера.

Убедитесь, что в статическом DKP-кластере отсутствуют StorageClass с именами, совпадающими с именами StorageClass в кластере DVP.

При включении модуля cloud-provider-dvp соответствующие StorageClass автоматически синхронизируются из DVP в DKP-кластер. Если StorageClass с таким именем уже существует в статическом кластере, может возникнуть конфликт ресурсов, из-за которого установка или обновление модуля завершится с ошибкой.

Добавление автоматически создаваемых узлов

  1. На машине администратора, где настроен доступ к кластеру DVP, подготовьте kubeconfig для доступа модуля cloud-provider-dvp к API DVP.

    Выполните шаги из раздела «Подготовка окружения» и закодируйте полученный kubeconfig в Base64:

    export DVP_PROVIDER_KUBECONFIG="./kubeconfig"
    export DVP_KUBECONFIG_B64="$(base64 -w0 ${DVP_PROVIDER_KUBECONFIG})"
    
  2. Задайте неймспейс DVP, в котором будут создаваться виртуальные машины и диски:

    export DVP_NAMESPACE="<DVP_NAMESPACE>"
    
  3. Укажите зону DVP, в которой будут создаваться узлы.

    На данный момент зонирование в DVP находится в разработке, поэтому для параметров zones в ModuleConfig и NodeGroup используйте значение default:

    export DVP_ZONE="default"
    

    При необходимости можно проверить топологические метки узлов в кластере DVP:

    d8 k get nodes -L topology.kubernetes.io/region,topology.kubernetes.io/zone
    

    Значение зоны в ModuleConfig и NodeGroup должно совпадать. Пока в DVP доступно только значение default.

  4. Создайте файл, например cloud-provider-dvp-mc.yaml, с конфигурацией модуля cloud-provider-dvp:

    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}
    EOF
    

    В манифесте используются значения переменных окружения, заданных на предыдущих шагах: DVP_KUBECONFIG_B64, DVP_NAMESPACE и DVP_ZONE.

  5. Примените ModuleConfig:

    d8 k apply -f cloud-provider-dvp-mc.yaml
    
  6. Дождитесь включения модуля cloud-provider-dvp:

    d8 k get module cloud-provider-dvp -o wide
    

    Модуль должен перейти в состояние Ready, а поды в неймспейсе d8-cloud-provider-dvp — в состояние Running.

  7. Убедитесь, что модуль node-manager находится в состоянии Ready:

    d8 k get module node-manager -o wide
    

    Если модуль находится в состоянии Error, проверьте, что в ModuleConfig и NodeGroup указаны доступные зоны DVP.

  8. Убедитесь, что в кластере появился ресурс DVPInstanceClass:

    d8 k get crd dvpinstanceclasses.deckhouse.io
    
  9. На машине администратора, где настроен доступ к кластеру DVP, проверьте доступные классы виртуальных машин, образы и StorageClass:

    d8 k --kubeconfig ${DVP_PROVIDER_KUBECONFIG} get virtualmachineclasses
    d8 k --kubeconfig ${DVP_PROVIDER_KUBECONFIG} get clustervirtualimages
    d8 k --kubeconfig ${DVP_PROVIDER_KUBECONFIG} get storageclasses
    

    Используйте полученные значения при создании DVPInstanceClass.

  10. Создайте файл, например dvp-instanceclass-nodegroup.yaml, с ресурсами DVPInstanceClass и NodeGroup:

    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:
          - <ZONE_NAME>
    

    Где:

    • virtualMachineClassName — имя VirtualMachineClass в DVP, например amd-epyc-gen-3;
    • rootDisk.storageClass — имя StorageClass в DVP, например replicated;
    • rootDisk.image.kind — тип источника образа. Для кластерного образа используйте ClusterVirtualImage;
    • rootDisk.image.name — имя образа ОС в DVP, например ubuntu-24-04-lts;
    • cloudInstances.zones — зона DVP, в которой будет создан узел. Значение должно входить в список zones из ModuleConfig.
  11. Примените манифест:

    d8 k apply -f dvp-instanceclass-nodegroup.yaml
    

    После применения DKP начнёт создавать виртуальную машину в DVP и подключать её к кластеру как узел.

  12. Проверьте состояние NodeGroup:

    d8 k get nodegroup dvp-worker -o wide
    d8 k describe nodegroup dvp-worker
    
  13. Проверьте появление нового узла в DKP-кластере:

    d8 k get nodes -o wide
    

    Пример ожидаемого результата:

    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
    

Добавление вручную созданных узлов через bootstrap-скрипт

Перед началом убедитесь, что выполнены следующие условия:

  • Модуль cloud-provider-dvp включён:

    d8 k get module cloud-provider-dvp -o wide
    
  • Компоненты модуля cloud-provider-dvp находятся в состоянии Running:

    d8 k -n d8-cloud-provider-dvp get pods -o wide
    
  • В DVP создана виртуальная машина, которая будет подключена к кластеру.
  • Виртуальная машина подключена к сети DVP, используемой для гибридной интеграции с кластером.
  • IP-адрес виртуальной машины входит в диапазон, указанный в internalNetworkCIDRs.
  • Имя виртуальной машины в DVP совпадает с hostname внутри операционной системы.
  • На виртуальной машине есть SSH-доступ для копирования и запуска bootstrap-скрипта.
  • Пользователь для подключения по SSH может выполнять команды через sudo без ввода пароля.
  • На виртуальной машине установлен один из пакетных менеджеров (apt/apt-get, yum или rpm) для поддерживаемой ОС. В РЕД ОС по умолчанию могут отсутствовать yum и which, поэтому их необходимо заранее установить.
  1. Создайте файл, например cloud-static-nodegroup.yaml, с ресурсом NodeGroup и типом узлов CloudStatic:

    apiVersion: deckhouse.io/v1
    kind: NodeGroup
    metadata:
      name: cloud-static
    spec:
      nodeType: CloudStatic
    
  2. Примените манифест:

    d8 k apply -f cloud-static-nodegroup.yaml
    
  3. Убедитесь, что NodeGroup создана и синхронизирована:

    d8 k get nodegroup cloud-static
    

    Пример ожидаемого результата:

    NAME           TYPE          READY   NODES   UPTODATE   INSTANCES   DESIRED   MIN   MAX   STANDBY   STATUS   AGE   SYNCED
    cloud-static   CloudStatic   0       0       0                                                               1m    True
    
  4. Получите bootstrap-скрипт для созданной NodeGroup:

    NODE_GROUP=cloud-static
    
    d8 k -n d8-cloud-instance-manager get secret manual-bootstrap-for-${NODE_GROUP} \
      -o jsonpath='{.data.bootstrap\.sh}' > bootstrap.b64
    
  5. Скопируйте bootstrap-скрипт на подключаемую виртуальную машину:

    scp bootstrap.b64 <USER>@<NODE_IP>:/tmp/bootstrap.b64
    
  6. Подключитесь к виртуальной машине по SSH:

    ssh <USER>@<NODE_IP>
    
  7. На виртуальной машине декодируйте bootstrap-скрипт, назначьте права и запустите его:

    base64 -d /tmp/bootstrap.b64 > /tmp/bootstrap.sh
    chmod +x /tmp/bootstrap.sh
    
    sudo bash /tmp/bootstrap.sh
    

    После запуска bootstrap-скрипт установит необходимые компоненты, настроит container runtime, kubelet и подключит узел к кластеру.

  8. На master-узле проверьте появление нового узла:

    d8 k get nodes -o wide
    

    Пример ожидаемого результата:

    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
    
  9. При сбоях подключения проверьте состояние NodeGroup, события и логи bootstrap на подключаемой виртуальной машине:

    d8 k get nodegroup cloud-static
    d8 k describe nodegroup cloud-static
    d8 k get events -A --sort-by=.lastTimestamp | tail -n 100
    

    На подключаемой виртуальной машине:

    sudo tail -n 120 /var/log/d8/bashible/bootstrap.log
    

    Если в логах есть ошибка Failed to discover node_ip that matches internalNetworkCIDRs, проверьте, что IP-адрес виртуальной машины входит в internalNetworkCIDRs.

Дополнительные ресурсы