Compare languages | Управление узлами: FAQ

Как добавить master-узлы в облачном кластере (single-master в multi-master)?

How do I add a master nodes to a cloud cluster (single-master to a multi-master)?

Инструкция в FAQ модуля control-plane-manager…

See the control-plane-manager module FAQ…

Как уменьшить число master-узлов в облачном кластере (multi-master в single-master)?

How do I reduce the number of master nodes in a cloud cluster (multi-master to single-master)?

Инструкция в FAQ модуля control-plane-manager…

See the control-plane-manager module FAQ…

Статические узлы

Static nodes

Добавить статический узел в кластер можно вручную (пример) или с помощью Cluster API Provider Static.

You can add a static node to the cluster manually (an example) or by using Cluster API Provider Static.

Как добавить статический узел в кластер (Cluster API Provider Static)?

How do I add a static node to a cluster (Cluster API Provider Static)?

Чтобы добавить статический узел в кластер (сервер bare metal или виртуальную машину), выполните следующие шаги:

To add a static node to a cluster (bare metal server or virtual machine), follow these steps:

  1. Подготовьте необходимые ресурсы — серверы/виртуальные машины, установите специфические пакеты ОС, добавьте точки монтирования, настройте сетевую связанность и т.п.
  2. Создайте ресурс SSHCredentials.
  3. Создайте ресурс StaticInstance.
  4. Создайте ресурс NodeGroup с nodeType Static, указав желаемое количество узлов в группе и, при необходимости, фильтр выбора StaticInstance.
  1. Prepare the required resources — servers/virtual machines, install specific OS packages, add mount points, configure the network, etc.
  2. Create the SSHCredentials resource.
  3. Create the StaticInstance resource.
  4. Create the NodeGroup resource with the Static nodeType, specify the desired number of nodes in the group and, if necessary, the filter for StaticInstance.

Пример добавления статического узла.

An example of adding a static node.

Как добавить несколько статических узлов в кластер вручную?

How do I add a batch of static nodes to a cluster manually?

Используйте существующий или создайте новый custom resource NodeGroup (пример NodeGroup с именем worker).

Use an existing one or create a new NodeGroup custom resource (example of the NodeGroup called worker). The nodeType parameter for static nodes in the NodeGroup must be Static or CloudStatic.

Автоматизировать процесс добавления узлов можно с помощью любой платформы автоматизации. Далее приведен пример для Ansible.

You can automate the bootstrap process with any automation platform you prefer. The following is an example for Ansible.

  1. Получите один из адресов Kubernetes API-сервера. Обратите внимание, что IP-адрес должен быть доступен с узлов, которые добавляются в кластер:
  1. Pick up one of Kubernetes API Server endpoints. Note that this IP must be accessible from nodes that are being added to the cluster:

shell kubectl -n default get ep kubernetes -o json | jq ‘.subsets[0].addresses[0].ip + “:” + (.subsets[0].ports[0].port | tostring)’ -r

shell kubectl -n default get ep kubernetes -o json | jq ‘.subsets[0].addresses[0].ip + “:” + (.subsets[0].ports[0].port | tostring)’ -r

Проверьте версию K8s. Если версия >= 1.25, создайте токен node-group:

Check the K8s version. If the version >= 1.25, create node-group token:

shell kubectl create token node-group –namespace d8-cloud-instance-manager –duration 1h

shell kubectl create token node-group –namespace d8-cloud-instance-manager –duration 1h

Сохраните полученный токен, и добавьте в поле token: playbook’а Ansible на дальнейших шагах.

Save the token you got and add it to the token: field of the Ansible playbook in the next steps.

  1. Если версия Kubernetes меньше 1.25, получите Kubernetes API-токен для специального ServiceAccount’а, которым управляет Deckhouse:
  1. If the Kubernetes version is smaller than 1.25, get a Kubernetes API token for a special ServiceAccount that Deckhouse manages:

shell kubectl -n d8-cloud-instance-manager get $(kubectl -n d8-cloud-instance-manager get secret -o name | grep node-group-token)
-o json | jq ‘.data.token’ -r | base64 -d && echo “”

shell kubectl -n d8-cloud-instance-manager get $(kubectl -n d8-cloud-instance-manager get secret -o name | grep node-group-token)
-o json | jq ‘.data.token’ -r | base64 -d && echo “”

  1. Создайте Ansible playbook с vars, которые заменены на полученные на предыдущих шагах значения:
  1. Create Ansible playbook with vars replaced with values from previous steps:

yaml

  • hosts: all become: yes gather_facts: no vars: kube_apiserver: token: tasks:
  • name: Check if node is already bootsrapped stat: path: /var/lib/bashible register: bootstrapped
  • name: Get bootstrap secret uri: url: “https://{{ kube_apiserver }}/api/v1/namespaces/d8-cloud-instance-manager/secrets/manual-bootstrap-for-{{ node_group }}” return_content: yes method: GET status_code: 200 body_format: json headers: Authorization: “Bearer {{ token }}” validate_certs: no register: bootstrap_secret when: bootstrapped.stat.exists == False
  • name: Run bootstrap.sh shell: “{{ bootstrap_secret.json.data[‘bootstrap.sh’] | b64decode }}” args: executable: /bin/bash ignore_errors: yes when: bootstrapped.stat.exists == False
  • name: wait wait_for_connection: delay: 30 when: bootstrapped.stat.exists == False

yaml

  • hosts: all become: yes gather_facts: no vars: kube_apiserver: token: tasks:
  • name: Check if node is already bootsrapped stat: path: /var/lib/bashible register: bootstrapped
  • name: Get bootstrap secret uri: url: “https://{{ kube_apiserver }}/api/v1/namespaces/d8-cloud-instance-manager/secrets/manual-bootstrap-for-{{ node_group }}” return_content: yes method: GET status_code: 200 body_format: json headers: Authorization: “Bearer {{ token }}” validate_certs: no register: bootstrap_secret when: bootstrapped.stat.exists == False
  • name: Run bootstrap.sh shell: “{{ bootstrap_secret.json.data[‘bootstrap.sh’] | b64decode }}” args: executable: /bin/bash ignore_errors: yes when: bootstrapped.stat.exists == False
  • name: wait wait_for_connection: delay: 30 when: bootstrapped.stat.exists == False
  1. Определите дополнительную переменную node_group. Значение переменной должно совпадать с именем NodeGroup, которой будет принадлежать узел. Переменную можно передать различными способами, например с использованием inventory-файла:
  1. Specify one more node_group variable. This variable must be the same as the name of NodeGroup to which node will belong. Variable can be passed in different ways, for example, by using an inventory file.:

text [system] system-0 system-1

text [system] system-0 system-1

[system:vars] node_group=system

[system:vars] node_group=system

[worker] worker-0 worker-1

[worker] worker-0 worker-1

[worker:vars] node_group=worker

[worker:vars] node_group=worker

  1. Выполните playbook с использованием inventory-файла.
  1. Run the playbook with the inventory file.

Как вручную очистить статический узел?

How do I clean up a static node manually?

This method is valid for both manually configured nodes (using the bootstrap script) and nodes configured using CAPS.

Инструкция справедлива как для узла, настроенного вручную (с помощью bootstrap-скрипта), так и для узла, настроенного с помощью CAPS.

To decommission a node from the cluster and clean up the server (VM), run the following command on the node:

Чтобы вывести из кластера узел и очистить сервер (ВМ), выполните следующую команду на узле:

shell bash /var/lib/bashible/cleanup_static_node.sh –yes-i-am-sane-and-i-understand-what-i-am-doing

shell bash /var/lib/bashible/cleanup_static_node.sh –yes-i-am-sane-and-i-understand-what-i-am-doing

Can I delete a StaticInstance?

Можно ли удалить StaticInstance?

A StaticInstance that is in the Pending state can be deleted with no adverse effects.

StaticInstance, находящийся в состоянии Pending можно удалять без каких-либо проблем.

To delete a StaticInstance in any state other than Pending (Runnig, Cleaning, Bootstraping), you need to delete the corresponding Instance resource, and then the StaticInstance will be deleted automatically.

Чтобы удалить StaticInstance находящийся в любом состоянии отличном от Pending (Runnig, Cleaning, Bootstraping), нужно удалить соответствующий ресурс Instance, после чего StaticInstance удалится автоматически.

How do I change the IP address of a StaticInstance?

Как изменить IP-адрес StaticInstance?

You cannot change the IP address in the StaticInstance resource. If an incorrect address is specified in StaticInstance, you have to delete the StaticInstance and create a new one.

Изменить IP-адрес в ресурсе StaticInstance нельзя. Если в StaticInstance указан ошибочный адрес, то нужно удалить StaticInstance и создать новый.

How do I migrate a manually configured static node under CAPS control?

Как мигрировать статический узел настроенный вручную под управление CAPS?

You need to clean up the node, then hand over the node under CAPS control.

Необходимо выполнить очистку узла, затем добавить узел под управление CAPS.

How do I change the NodeGroup of a static node?

Как изменить NodeGroup у статического узла?

Note that if a node is under CAPS control, you cannot change the NodeGroup membership of such a node. The only alternative is to delete StaticInstance and create a new one.

To switch an existing manually created static node to another NodeGroup, you need to change its group label:

Если узел находится под управлением CAPS, то изменить принадлежность к NodeGroup у такого узла нельзя. Единственный вариант — удалить StaticInstance и создать новый.

shell kubectl label node –overwrite node.deckhouse.io/group= kubectl label node node-role.kubernetes.io/-

Чтобы перенести существующий статический узел созданный вручную из одной NodeGroup в другую, необходимо изменить у узла лейбл группы:

Applying the changes will take some time.

shell kubectl label node –overwrite node.deckhouse.io/group= kubectl label node node-role.kubernetes.io/-

How to clean up a node for adding to the cluster?

Применение изменений потребует некоторого времени.

This is only needed if you have to move a static node from one cluster to another. Be aware these operations remove local storage data. If you just need to change a NodeGroup, follow this instruction.

Как зачистить узел для последующего ввода в кластер?

Note! Evict resources from the node and remove the node from LINSTOR using the instruction if the node you are cleaning up has LINSTOR storage pools.

Это необходимо только в том случае, если нужно переместить статический узел из одного кластера в другой. Имейте в виду, что эти операции удаляют данные локального хранилища. Если необходимо просто изменить NodeGroup, следуйте этой инструкции.

  1. Delete the node from the Kubernetes cluster:

Внимание! Если на зачищаемом узле есть пулы хранения LINSTOR, то предварительно выгоните ресурсы с узла и удалите узел из LINSTOR, следуя инструкции.

shell kubectl drain --ignore-daemonsets --delete-local-data kubectl delete node

  1. Удалите узел из кластера Kubernetes:
  1. Run cleanup script on the node:

shell kubectl drain --ignore-daemonsets --delete-local-data kubectl delete node

shell bash /var/lib/bashible/cleanup_static_node.sh –yes-i-am-sane-and-i-understand-what-i-am-doing

  1. Запустите на узле скрипт очистки:
  1. Run the bootstrap.sh script after reboot of the node.

shell bash /var/lib/bashible/cleanup_static_node.sh –yes-i-am-sane-and-i-understand-what-i-am-doing

How do I know if something went wrong?

  1. После перезагрузки узла запустите скрипт bootstrap.sh.

If a node in a nodeGroup is not updated (the value of UPTODATE when executing the kubectl get nodegroup command is less than the value of NODES) or you assume some other problems that may be related to the node-manager module, then you need to look at the logs of the bashible service. The bashible service runs on each node managed by the node-manager module.

Как понять, что что-то пошло не так?

To view the logs of the bashible service on a specific node, run the following command:

Если узел в NodeGroup не обновляется (значение UPTODATE при выполнении команды kubectl get nodegroup меньше значения NODES) или вы предполагаете какие-то другие проблемы, которые могут быть связаны с модулем node-manager, нужно посмотреть логи сервиса bashible. Сервис bashible запускается на каждом узле, управляемом модулем node-manager.

shell journalctl -fu bashible

Чтобы посмотреть логи сервиса bashible, выполните на узле следующую команду:

Example of output when the bashible service has performed all necessary actions:

shell journalctl -fu bashible

console May 25 04:39:16 kube-master-0 systemd[1]: Started Bashible service. May 25 04:39:16 kube-master-0 bashible.sh[1976339]: Configuration is in sync, nothing to do. May 25 04:39:16 kube-master-0 systemd[1]: bashible.service: Succeeded.

Пример вывода, когда все необходимые действия выполнены:

How do I know what is running on a node while it is being created?

console May 25 04:39:16 kube-master-0 systemd[1]: Started Bashible service. May 25 04:39:16 kube-master-0 bashible.sh[1976339]: Configuration is in sync, nothing to do. May 25 04:39:16 kube-master-0 systemd[1]: bashible.service: Succeeded.

You can analyze cloud-init to find out what’s happening on a node during the bootstrapping process:

Как посмотреть, что в данный момент выполняется на узле при его создании?

  1. Find the node that is currently bootstrapping:

Если необходимо узнать, что происходит на узле (к примеру, он долго создается), можно посмотреть логи cloud-init. Для этого выполните следующие шаги:

  1. Найдите узел, который сейчас бутстрапится:

shell kubectl get instances | grep Pending

shell kubectl get instances | grep Pending

An example:

Пример:

shell $ kubectl get instances | grep Pending dev-worker-2a6158ff-6764d-nrtbj Pending 46s

shell $ kubectl get instances | grep Pending dev-worker-2a6158ff-6764d-nrtbj Pending 46s

  1. Get information about connection parameters for viewing logs:
  1. Получите информацию о параметрах подключения для просмотра логов:

shell kubectl get instances dev-worker-2a6158ff-6764d-nrtbj -o yaml | grep ‘bootstrapStatus’ -B0 -A2

shell kubectl get instances dev-worker-2a6158ff-6764d-nrtbj -o yaml | grep ‘bootstrapStatus’ -B0 -A2

An example:

Пример:

shell $ kubectl get instances dev-worker-2a6158ff-6764d-nrtbj -o yaml | grep ‘bootstrapStatus’ -B0 -A2 bootstrapStatus: description: Use ‘nc 192.168.199.178 8000’ to get bootstrap logs. logsEndpoint: 192.168.199.178:8000

shell $ kubectl get instances dev-worker-2a6158ff-6764d-nrtbj -o yaml | grep ‘bootstrapStatus’ -B0 -A2 bootstrapStatus: description: Use ‘nc 192.168.199.178 8000’ to get bootstrap logs. logsEndpoint: 192.168.199.178:8000

  1. Run the command you got (nc 192.168.199.115 8000 according to the example above) to see cloud-init logs and determine the cause of the problem on the node.
  1. Выполните полученную команду (в примере выше — nc 192.168.199.178 8000), чтобы увидеть логи cloud-init и на чем зависла настройка узла.

The logs of the initial node configuration are located at /var/log/cloud-init-output.log.

Логи первоначальной настройки узла находятся в /var/log/cloud-init-output.log.

How do I update kernel on nodes?

Как обновить ядро на узлах?

Debian-based distros

Для дистрибутивов, основанных на Debian

Create a Node Group Configuration resource by specifying the desired kernel version in the desired_version variable of the shell script (the resource’s spec.content parameter):

Создайте ресурс NodeGroupConfiguration, указав в переменной desired_version shell-скрипта (параметр spec.content ресурса) желаемую версию ядра:

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: install-kernel.sh spec: bundles:

  • ‘*’ nodeGroups:
  • ‘*’ weight: 32 content: | Copyright 2022 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.

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: install-kernel.sh spec: bundles:

  • ‘*’ nodeGroups:
  • ‘*’ weight: 32 content: | Copyright 2022 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.

desired_version=”5.15.0-53-generic”

desired_version=”5.15.0-53-generic”

bb-event-on ‘bb-package-installed’ ‘post-install’ post-install() { bb-log-info “Setting reboot flag due to kernel was updated” bb-flag-set reboot }

bb-event-on ‘bb-package-installed’ ‘post-install’ post-install() { bb-log-info “Setting reboot flag due to kernel was updated” bb-flag-set reboot }

version_in_use=”$(uname -r)”

version_in_use=”$(uname -r)”

if [[ “$version_in_use” == “$desired_version” ]]; then exit 0 fi

if [[ “$version_in_use” == “$desired_version” ]]; then exit 0 fi

bb-deckhouse-get-disruptive-update-approval bb-apt-install “linux-image-${desired_version}”

bb-deckhouse-get-disruptive-update-approval bb-apt-install “linux-image-${desired_version}”

CentOS-based distros

Для дистрибутивов, основанных на CentOS

Create a Node Group Configuration resource by specifying the desired kernel version in the desired_version variable of the shell script (the resource’s spec.content parameter):

Создайте ресурс NodeGroupConfiguration, указав в переменной desired_version shell-скрипта (параметр spec.content ресурса) желаемую версию ядра:

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: install-kernel.sh spec: bundles:

  • ‘*’ nodeGroups:
  • ‘*’ weight: 32 content: | Copyright 2022 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.

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: install-kernel.sh spec: bundles:

  • ‘*’ nodeGroups:
  • ‘*’ weight: 32 content: | Copyright 2022 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.

desired_version=”3.10.0-1160.42.2.el7.x86_64”

desired_version=”3.10.0-1160.42.2.el7.x86_64”

bb-event-on ‘bb-package-installed’ ‘post-install’ post-install() { bb-log-info “Setting reboot flag due to kernel was updated” bb-flag-set reboot }

bb-event-on ‘bb-package-installed’ ‘post-install’ post-install() { bb-log-info “Setting reboot flag due to kernel was updated” bb-flag-set reboot }

version_in_use=”$(uname -r)”

version_in_use=”$(uname -r)”

if [[ “$version_in_use” == “$desired_version” ]]; then exit 0 fi

if [[ “$version_in_use” == “$desired_version” ]]; then exit 0 fi

bb-deckhouse-get-disruptive-update-approval bb-yum-install “kernel-${desired_version}”

bb-deckhouse-get-disruptive-update-approval bb-yum-install “kernel-${desired_version}”

NodeGroup parameters and their result

Какие параметры NodeGroup к чему приводят?

The NodeGroup parameter Disruption update Node provisioning Kubelet restart
chaos - - -
cloudInstances.classReference - + -
cloudInstances.maxSurgePerZone - - -
cri.containerd.maxConcurrentDownloads - - +
cri.type - (NotManaged) / + (other) - -
disruptions - - -
kubelet.maxPods - - +
kubelet.rootDir - - +
kubernetesVersion - - +
nodeTemplate - - -
static - - +
update.maxConcurrent - - -
Параметр NG Disruption update Перезаказ узлов Рестарт kubelet
chaos - - -
cloudInstances.classReference - + -
cloudInstances.maxSurgePerZone - - -
cri.containerd.maxConcurrentDownloads - - +
cri.type - (NotManaged) / + (other) - -
disruptions - - -
kubelet.maxPods - - +
kubelet.rootDir - - +
kubernetesVersion - - +
nodeTemplate - - -
static - - +
update.maxConcurrent - - -

Refer to the description of the NodeGroup custom resource for more information about the parameters.

Подробно о всех параметрах можно прочитать в описании custom resource NodeGroup.

Changing the InstanceClass or instancePrefix parameter in the Deckhouse configuration won’t result in a RollingUpdate. Deckhouse will create new MachineDeployments and delete the old ones. The number of machinedeployments ordered at the same time is determined by the cloud Instances.maxSurgePerZone parameter.

В случае изменения параметров InstanceClass или instancePrefix в конфигурации Deckhouse не будет происходить RollingUpdate. Deckhouse создаст новые MachineDeployment, а старые удалит. Количество заказываемых одновременно MachineDeployment определяется параметром cloudInstances.maxSurgePerZone.

During the disruption update, an evict of the pods from the node is performed. If any pod failes to evict, the evict is repeated every 20 seconds until a global timeout of 5 minutes is reached. After that, the pods that failed to evict are removed.

При disruption update выполняется evict подов с узла. Если какие-либо поды не удалось evict’нуть, evict повторяется каждые 20 секунд до достижения глобального таймаута в 5 минут. После этого поды, которые не удалось evict’нуть, удаляются.

How do I redeploy ephemeral machines in the cloud with a new configuration?

Как пересоздать эфемерные машины в облаке с новой конфигурацией?

If the Deckhouse configuration is changed (both in the node-manager module and in any of the cloud providers), the VMs will not be redeployed. The redeployment is performed only in response to changing InstanceClass or NodeGroup objects.

При изменении конфигурации Deckhouse (как в модуле node-manager, так и в любом из облачных провайдеров) виртуальные машины не будут перезаказаны. Пересоздание происходит только после изменения ресурсов InstanceClass или NodeGroup.

To force the redeployment of all Machines, you need to add/modify the manual-rollout-id annotation to the NodeGroup: kubectl annotate NodeGroup name_ng "manual-rollout-id=$(uuidgen)" --overwrite.

Чтобы принудительно пересоздать все узлы, связанные с ресурсом Machines, следует добавить/изменить аннотацию manual-rollout-id в NodeGroup: kubectl annotate NodeGroup имя_ng "manual-rollout-id=$(uuidgen)" --overwrite.

How do I allocate nodes to specific loads?

Как выделить узлы под специфические нагрузки?

Note! You cannot use the deckhouse.io domain in labels and taints keys of the NodeGroup. It is reserved for Deckhouse components. Please, use the dedicated or dedicated.client.com keys.

Внимание! Запрещено использование домена deckhouse.io в ключах labels и taints у NodeGroup. Он зарезервирован для компонентов Deckhouse. Следует отдавать предпочтение в пользу ключей dedicated или dedicated.client.com.

There are two ways to solve this problem:

Для решений данной задачи существуют два механизма:

  1. You can set labels to NodeGroup’s spec.nodeTemplate.labels, to use them in the Pod’s spec.nodeSelector or spec.affinity.nodeAffinity parameters. In this case, you select nodes that the scheduler will use for running the target application.
  2. You cat set taints to NodeGroup’s spec.nodeTemplate.taints and then remove them via the Pod’s spec.tolerations parameter. In this case, you disallow running applications on these nodes unless those applications are explicitly allowed.
  1. Установка меток в NodeGroup spec.nodeTemplate.labels для последующего использования их в Pod spec.nodeSelector или spec.affinity.nodeAffinity. Указывает, какие именно узлы будут выбраны планировщиком для запуска целевого приложения.
  2. Установка ограничений в NodeGroup spec.nodeTemplate.taints с дальнейшим снятием их в Pod spec.tolerations. Запрещает исполнение не разрешенных явно приложений на этих узлах.

Deckhouse tolerates the dedicated by default, so we recommend using the dedicated key with any value for taints on your dedicated nodes.️ To use custom keys for taints (e.g., dedicated.client.com), you must add the key’s value to the modules.placement.customTolerationKeys parameters. This way, deckhouse can deploy system components (e.g., cni-flannel) to these dedicated nodes.

Deckhouse по умолчанию tolerate’ит ключ dedicated, поэтому рекомендуется использовать ключ dedicated с любым value для taint’ов на ваших выделенных узлах.️ Если необходимо использовать произвольные ключи для taints (например, dedicated.client.com), значение ключа нужно добавить в параметр modules.placement.customTolerationKeys. Таким образом мы разрешим системным компонентам (например, cni-flannel) выезжать на эти выделенные узлы.

How to allocate nodes to system components?

Подробности в статье на Habr.

Frontend

Как выделить узлы под системные компоненты?

For Ingress controllers, use the NodeGroup with the following configuration:

Фронтенд

yaml nodeTemplate: labels: node-role.deckhouse.io/frontend: “” taints:

  • effect: NoExecute key: dedicated.deckhouse.io value: frontend

Для Ingress-контроллеров используйте NodeGroup со следующей конфигурацией:

System components

yaml nodeTemplate: labels: node-role.deckhouse.io/frontend: “” taints:

  • effect: NoExecute key: dedicated.deckhouse.io value: frontend

NodeGroup for components of Deckhouse subsystems will look as follows:

Системные

yaml nodeTemplate: labels: node-role.deckhouse.io/system: “” taints:

  • effect: NoExecute key: dedicated.deckhouse.io value: system

NodeGroup для компонентов подсистем Deckhouse будут с такими параметрами:

How do I speed up node provisioning on the cloud when scaling applications horizontally?

yaml nodeTemplate: labels: node-role.deckhouse.io/system: “” taints:

  • effect: NoExecute key: dedicated.deckhouse.io value: system

The most efficient way is to have some extra nodes “ready”. In this case, you can run new application replicas on them almost instantaneously. The obvious disadvantage of this approach is the additional maintenance costs related to these nodes.

Как ускорить заказ узлов в облаке при горизонтальном масштабировании приложений?

Here is how you should configure the target NodeGroup:

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

  1. Specify the number of “ready” nodes (or a percentage of the maximum number of nodes in the group) using the cloudInstances.standby paramter.
  2. If there are additional service components (not maintained by Deckhouse, such as filebeat DaemonSet) for these nodes, you need to specify their combined resource consumption via the standbyHolder.notHeldResources parameter.
  3. This feature requires that at least one group node is already running in the cluster. In other words, there must be either a single replica of the application, or the cloudInstances.minPerZone parameter must be set to 1.

Необходимые настройки целевой NodeGroup будут следующие:

An example:

  1. Указать абсолютное количество подогретых узлов (или процент от максимального количества узлов в этой группе) в параметре cloudInstances.standby.
  2. При наличии дополнительных служебных компонентов (не обслуживаемых Deckhouse, например DaemonSet filebeat) для этих узлов — задать их суммарное потребление ресурсов в параметре standbyHolder.notHeldResources.
  3. Для работы этой функции требуется, чтобы как минимум один узел из группы уже был запущен в кластере. Иными словами, либо должна быть доступна одна реплика приложения, либо количество узлов для этой группы cloudInstances.minPerZone должно быть 1.

yaml cloudInstances: maxPerZone: 10 minPerZone: 1 standby: 10% standbyHolder: notHeldResources: cpu: 300m memory: 2Gi

Пример:

How do I disable machine-controller-manager in the case of potentially cluster-damaging changes?

yaml cloudInstances: maxPerZone: 10 minPerZone: 1 standby: 10% standbyHolder: notHeldResources: cpu: 300m memory: 2Gi

Note! Use this switch only if you know what you are doing and clearly understand the consequences.

Как выключить machine-controller-manager в случае выполнения потенциально деструктивных изменений в кластере?

Set the mcmEmergencyBrake parameter to true:

Внимание! Использовать эту настройку допустимо только тогда, когда вы четко понимаете, зачем это необходимо.

yaml mcmEmergencyBrake: true

Установить параметр:

How do I restore the master node if kubelet cannot load the control plane components?

yaml mcmEmergencyBrake: true

Such a situation may occur if images of the control plane components on the master were deleted in a cluster that has a single master node (e.g., the directory /var/lib/containerd was deleted). In this case, kubelet cannot pull images of the control plane components when restarted since the master node lacks authorization parameters required for accessing registry.deckhouse.io.

Как восстановить master-узел, если kubelet не может загрузить компоненты control plane?

Below is an instruction on how you can restore the master node.

Подобная ситуация может возникнуть, если в кластере с одним master-узлом на нем были удалены образы компонентов control plane (например, удалена директория /var/lib/containerd). В этом случае kubelet при рестарте не сможет скачать образы компонентов control plane, поскольку на master-узле нет параметров авторизации в registry.deckhouse.io.

containerd

Ниже инструкция по восстановлению master-узла.

Execute the following command to restore the master node in any cluster running under Deckhouse:

containerd

shell kubectl -n d8-system get secrets deckhouse-registry -o json | jq -r ‘.data.”.dockerconfigjson”’ | base64 -d | jq -r ‘.auths.”registry.deckhouse.io”.auth’

Для восстановления работоспособности master-узла нужно в любом рабочем кластере под управлением Deckhouse выполнить команду:

Copy the command’s output and use it for setting the AUTH variable on the corrupted master. Next, you need to pull images of control plane components to the corrupted master:

shell kubectl -n d8-system get secrets deckhouse-registry -o json | jq -r ‘.data.”.dockerconfigjson”’ | base64 -d | jq -r ‘.auths.”registry.deckhouse.io”.auth’

shell for image in $(grep “image:” /etc/kubernetes/manifests/* | awk ‘{print $3}’); do crictl pull –auth $AUTH $image done

Вывод команды нужно скопировать и присвоить переменной AUTH на поврежденном master-узле. Далее на поврежденном master-узле нужно загрузить образы компонентов control-plane:

You need to restart kubelet after pulling the images.

shell for image in $(grep “image:” /etc/kubernetes/manifests/* | awk ‘{print $3}’); do crictl pull –auth $AUTH $image done

How to change CRI for NodeGroup?

После загрузки образов необходимо перезапустить kubelet.

Note! CRI can only be switched from Containerd to NotManaged and back (the cri.type parameter).

Как изменить CRI для NodeGroup?

Set NodeGroup cri.type to Containerd or NotManaged.

Внимание! Возможен переход только с Containerd на NotManaged и обратно (параметр cri.type).

NodeGroup YAML example:

Установить параметр cri.type в Containerd или в NotManaged.

yaml apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: worker spec: nodeType: Static cri: type: Containerd

Пример YAML-манифеста NodeGroup:

Also, this operation can be done with patch:

yaml apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: worker spec: nodeType: Static cri: type: Containerd

  • For Containerd:

Также эту операцию можно выполнить с помощью патча:

shell kubectl patch nodegroup --type merge -p '{"spec":{"cri":{"type":"Containerd"}}}'

  • Для Containerd:
  • For NotManaged:

shell kubectl patch nodegroup <имя NodeGroup=""> --type merge -p '{"spec":{"cri":{"type":"Containerd"}}}'

shell kubectl patch nodegroup --type merge -p '{"spec":{"cri":{"type":"NotManaged"}}}'

  • Для NotManaged:

Note! While changing cri.type for NodeGroups, created using dhctl, you must change it in dhctl config edit provider-cluster-configuration and in NodeGroup object.

shell kubectl patch nodegroup <имя NodeGroup=""> --type merge -p '{"spec":{"cri":{"type":"NotManaged"}}}'

After setting up a new CRI for NodeGroup, the node-manager module drains nodes one by one and installs a new CRI on them. Node update is accompanied by downtime (disruption). Depending on the disruption setting for NodeGroup, the node-manager module either automatically allows node updates or requires manual confirmation.

Внимание! При смене cri.type для NodeGroup, созданных с помощью dhctl, нужно менять ее в dhctl config edit provider-cluster-configuration и настройках объекта NodeGroup.

How to change CRI for the whole cluster?

После настройки нового CRI для NodeGroup модуль node-manager по одному drain’ит узлы и устанавливает на них новый CRI. Обновление узла сопровождается простоем (disruption). В зависимости от настройки disruption для NodeGroup модуль node-manager либо автоматически разрешает обновление узлов, либо требует ручного подтверждения.

Note! CRI can only be switched from Containerd to NotManaged and back (the cri.type parameter).

Как изменить CRI для всего кластера?

It is necessary to use the dhctl utility to edit the defaultCRI parameter in the cluster-configuration config.

Внимание! Возможен переход только с Containerd на NotManaged и обратно (параметр cri.type).

Also, this operation can be done with the following patch:

  • For Containerd:

Необходимо с помощью утилиты dhctl отредактировать параметр defaultCRI в конфиге cluster-configuration.

shell data=”$(kubectl -n kube-system get secret d8-cluster-configuration -o json | jq -r ‘.data.”cluster-configuration.yaml”’ | base64 -d | sed “s/NotManaged/Containerd/” | base64 -w0)” kubectl -n kube-system patch secret d8-cluster-configuration -p “{"data":{"cluster-configuration.yaml":"$data"}}”

Также возможно выполнить эту операцию с помощью kubectl patch. Пример:

  • Для Containerd:
  • For NotManaged:

shell data=”$(kubectl -n kube-system get secret d8-cluster-configuration -o json | jq -r ‘.data.”cluster-configuration.yaml”’ | base64 -d | sed “s/NotManaged/Containerd/” | base64 -w0)” kubectl -n kube-system patch secret d8-cluster-configuration -p “{"data":{"cluster-configuration.yaml":"$data"}}”

shell data=”$(kubectl -n kube-system get secret d8-cluster-configuration -o json | jq -r ‘.data.”cluster-configuration.yaml”’ | base64 -d | sed “s/Containerd/NotManaged/” | base64 -w0)” kubectl -n kube-system patch secret d8-cluster-configuration -p “{"data":{"cluster-configuration.yaml":"$data"}}”

  • Для NotManaged:

If it is necessary to leave some NodeGroup on another CRI, then before changing the defaultCRI it is necessary to set CRI for this NodeGroup, as described here.

shell data=”$(kubectl -n kube-system get secret d8-cluster-configuration -o json | jq -r ‘.data.”cluster-configuration.yaml”’ | base64 -d | sed “s/Containerd/NotManaged/” | base64 -w0)” kubectl -n kube-system patch secret d8-cluster-configuration -p “{"data":{"cluster-configuration.yaml":"$data"}}”

Note! Changing defaultCRI entails changing CRI on all nodes, including master nodes. If there is only one master node, this operation is dangerous and can lead to a complete failure of the cluster! The preferred option is to make a multi-master and change the CRI type!

Если необходимо какую-то NodeGroup оставить на другом CRI, перед изменением defaultCRI необходимо установить CRI для этой NodeGroup, как описано здесь.

When changing the CRI in the cluster, additional steps are required for the master nodes:

Внимание! Изменение defaultCRI влечет за собой изменение CRI на всех узлах, включая master-узлы. Если master-узел один, данная операция является опасной и может привести к полной неработоспособности кластера! Предпочтительный вариант — сделать multimaster и поменять тип CRI!

  1. Deckhouse updates nodes in master NodeGroup one by one, so you need to discover which node is updating right now:

При изменении CRI в кластере для master-узлов необходимо выполнить дополнительные шаги:

shell kubectl get nodes -l node-role.kubernetes.io/control-plane=”” -o json | jq ‘.items[] | select(.metadata.annotations.”update.node.deckhouse.io/approved”==””) | .metadata.name’ -r

  1. Deckhouse обновляет узлы в master NodeGroup по одному, поэтому необходимо определить, какой узел на данный момент обновляется:
  1. Confirm the disruption of the master node that was discovered in the previous step:

shell kubectl get nodes -l node-role.kubernetes.io/control-plane=”” -o json | jq ‘.items[] | select(.metadata.annotations.”update.node.deckhouse.io/approved”==””) | .metadata.name’ -r

shell kubectl annotate node update.node.deckhouse.io/disruption-approved=

  1. Подтвердить disruption для master-узла, полученного на предыдущем шаге:
  1. Wait for the updated master node to switch to Ready state. Repeat steps for the next master node.

shell kubectl annotate node <имя master-узла=""> update.node.deckhouse.io/disruption-approved=

How to add node configuration step?

  1. Дождаться перехода обновленного master-узла в Ready. Выполнить итерацию для следующего master’а.

Additional node configuration steps are set via the NodeGroupConfiguration custom resource.

Как добавить шаг для конфигурации узлов?

How to use containerd with Nvidia GPU support?

Дополнительные шаги для конфигурации узлов задаются с помощью custom resource NodeGroupConfiguration.

Create NodeGroup for GPU-nodes.

Как использовать containerd с поддержкой Nvidia GPU?

yaml apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: gpu spec: chaos: mode: Disabled disruptions: approvalMode: Automatic nodeType: CloudStatic

Необходимо создать отдельную NodeGroup для GPU-нод.

Create NodeGroupConfiguration for containerd configuration of NodeGroup gpu:

yaml apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: gpu spec: chaos: mode: Disabled disruptions: approvalMode: Automatic nodeType: CloudStatic

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: containerd-additional-config.sh spec: 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.

Далее необходимо создать NodeGroupConfiguration для NodeGroup gpu для конфигурации containerd:

mkdir -p /etc/containerd/conf.d bb-sync-file /etc/containerd/conf.d/nvidia_gpu.toml - « “EOF” [plugins] [plugins.”io.containerd.grpc.v1.cri”] [plugins.”io.containerd.grpc.v1.cri”.containerd] default_runtime_name = “nvidia” [plugins.”io.containerd.grpc.v1.cri”.containerd.runtimes] [plugins.”io.containerd.grpc.v1.cri”.containerd.runtimes.runc] [plugins.”io.containerd.grpc.v1.cri”.containerd.runtimes.nvidia] privileged_without_host_devices = false runtime_engine = “” runtime_root = “” runtime_type = “io.containerd.runc.v1” [plugins.”io.containerd.grpc.v1.cri”.containerd.runtimes.nvidia.options] BinaryName = “/usr/bin/nvidia-container-runtime” SystemdCgroup = false EOF nodeGroups:

  • gpu weight: 49

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: containerd-additional-config.sh spec: 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.

Create NodeGroupConfiguration for Nvidia drivers setup on NodeGroup gpu.

mkdir -p /etc/containerd/conf.d bb-sync-file /etc/containerd/conf.d/nvidia_gpu.toml - « “EOF” [plugins] [plugins.”io.containerd.grpc.v1.cri”] [plugins.”io.containerd.grpc.v1.cri”.containerd] default_runtime_name = “nvidia” [plugins.”io.containerd.grpc.v1.cri”.containerd.runtimes] [plugins.”io.containerd.grpc.v1.cri”.containerd.runtimes.runc] [plugins.”io.containerd.grpc.v1.cri”.containerd.runtimes.nvidia] privileged_without_host_devices = false runtime_engine = “” runtime_root = “” runtime_type = “io.containerd.runc.v1” [plugins.”io.containerd.grpc.v1.cri”.containerd.runtimes.nvidia.options] BinaryName = “/usr/bin/nvidia-container-runtime” SystemdCgroup = false EOF nodeGroups:

  • gpu weight: 49

Ubuntu

Далее необходимо добавить NodeGroupConfiguration для установки драйверов Nvidia для NodeGroup gpu.

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: install-cuda.sh spec: bundles:

  • ubuntu-lts 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.

Ubuntu

distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/libnvidia-container/gpgkey | sudo apt-key add - curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list apt-get update apt-get install -y nvidia-container-toolkit nvidia-driver-525-server nodeGroups:

  • gpu weight: 30

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: install-cuda.sh spec: bundles:

  • ubuntu-lts 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.

Centos

distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/libnvidia-container/gpgkey | sudo apt-key add - curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list apt-get update apt-get install -y nvidia-container-toolkit nvidia-driver-525-server nodeGroups:

  • gpu weight: 30

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: install-cuda.sh spec: bundles:

  • centos 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.

Centos

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.repo | sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo yum install -y nvidia-container-toolkit nvidia-driver nodeGroups:

  • gpu weight: 30

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: install-cuda.sh spec: bundles:

  • centos 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.

Bootstrap and reboot node.

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.repo | sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo yum install -y nvidia-container-toolkit nvidia-driver nodeGroups:

  • gpu weight: 30

How to check if it was successful?

После этого выполните бутстрап и ребут узла.

Deploy the Job:

Как проверить, что все прошло успешно?

yaml apiVersion: batch/v1 kind: Job metadata: name: nvidia-cuda-test namespace: default spec: completions: 1 template: spec: restartPolicy: Never nodeSelector: node.deckhouse.io/group: gpu containers:

  • name: nvidia-cuda-test image: nvidia/cuda:11.6.2-base-ubuntu20.04 imagePullPolicy: “IfNotPresent” command:
  • nvidia-smi

Создайте в кластере Job:

And check the logs:

yaml apiVersion: batch/v1 kind: Job metadata: name: nvidia-cuda-test namespace: default spec: completions: 1 template: spec: restartPolicy: Never nodeSelector: node.deckhouse.io/group: gpu containers:

  • name: nvidia-cuda-test image: nvidia/cuda:11.6.2-base-ubuntu20.04 imagePullPolicy: “IfNotPresent” command:
  • nvidia-smi

shell $ kubectl logs job/nvidia-cuda-test Tue Jan 24 11:36:18 2023 +—————————————————————————–+ | NVIDIA-SMI 525.60.13 Driver Version: 525.60.13 CUDA Version: 12.0 | |——————————-+———————-+———————-+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 Tesla T4 Off | 00000000:8B:00.0 Off | 0 | | N/A 45C P0 25W / 70W | 0MiB / 15360MiB | 0% Default | | | | N/A | +——————————-+———————-+———————-+

И посмотрите логи:

+—————————————————————————–+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +—————————————————————————–+

shell $ kubectl logs job/nvidia-cuda-test Tue Jan 24 11:36:18 2023 +—————————————————————————–+ | NVIDIA-SMI 525.60.13 Driver Version: 525.60.13 CUDA Version: 12.0 | |——————————-+———————-+———————-+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 Tesla T4 Off | 00000000:8B:00.0 Off | 0 | | N/A 45C P0 25W / 70W | 0MiB / 15360MiB | 0% Default | | | | N/A | +——————————-+———————-+———————-+

Deploy the Job:

+—————————————————————————–+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +—————————————————————————–+

yaml apiVersion: batch/v1 kind: Job metadata: name: gpu-operator-test namespace: default spec: completions: 1 template: spec: restartPolicy: Never nodeSelector: node.deckhouse.io/group: gpu containers:

  • name: gpu-operator-test image: nvidia/samples:vectoradd-cuda10.2 imagePullPolicy: “IfNotPresent”

Создайте в кластере Job:

And check the logs:

yaml apiVersion: batch/v1 kind: Job metadata: name: gpu-operator-test namespace: default spec: completions: 1 template: spec: restartPolicy: Never nodeSelector: node.deckhouse.io/group: gpu containers:

  • name: gpu-operator-test image: nvidia/samples:vectoradd-cuda10.2 imagePullPolicy: “IfNotPresent”

shell $ kubectl logs job/gpu-operator-test [Vector addition of 50000 elements] Copy input data from the host memory to the CUDA device CUDA kernel launch with 196 blocks of 256 threads Copy output data from the CUDA device to the host memory Test PASSED Done

И посмотрите логи:

How to deploy custom containerd configuration?

shell $ kubectl logs job/gpu-operator-test [Vector addition of 50000 elements] Copy input data from the host memory to the CUDA device CUDA kernel launch with 196 blocks of 256 threads Copy output data from the CUDA device to the host memory Test PASSED Done

Bashible on nodes merges main deckhouse containerd config with configs from /etc/containerd/conf.d/*.toml.

Как развернуть кастомный конфиг containerd?

How to add additional registry auth?

Bashible на узлах мержит основной конфиг containerd для Deckhouse с конфигами из /etc/containerd/conf.d/*.toml.

Deploy NodeGroupConfiguration script:

Как добавить авторизацию в дополнительный registry?

yaml

apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: containerd-additional-config.sh spec: 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.

Разверните скрипт NodeGroupConfiguration:

mkdir -p /etc/containerd/conf.d bb-sync-file /etc/containerd/conf.d/additional_registry.toml - « “EOF” [plugins] [plugins.”io.containerd.grpc.v1.cri”] [plugins.”io.containerd.grpc.v1.cri”.registry] [plugins.”io.containerd.grpc.v1.cri”.registry.mirrors] [plugins.”io.containerd.grpc.v1.cri”.registry.mirrors.”docker.io”] endpoint = [“https://registry-1.docker.io”] [plugins.”io.containerd.grpc.v1.cri”.registry.mirrors.”artifactory.proxy”] endpoint = [“https://artifactory.proxy”] [plugins.”io.containerd.grpc.v1.cri”.registry.configs] [plugins.”io.containerd.grpc.v1.cri”.registry.configs.”artifactory.proxy”.auth] auth = “AAAABBBCCCDDD==” EOF nodeGroups:

  • “*” weight: 49

yaml

apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: containerd-additional-config.sh spec: 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.

How to use NodeGroup’s priority feature

mkdir -p /etc/containerd/conf.d bb-sync-file /etc/containerd/conf.d/additional_registry.toml - « “EOF” [plugins] [plugins.”io.containerd.grpc.v1.cri”] [plugins.”io.containerd.grpc.v1.cri”.registry] [plugins.”io.containerd.grpc.v1.cri”.registry.mirrors] [plugins.”io.containerd.grpc.v1.cri”.registry.mirrors.”docker.io”] endpoint = [“https://registry-1.docker.io”] [plugins.”io.containerd.grpc.v1.cri”.registry.mirrors.”artifactory.proxy”] endpoint = [“https://artifactory.proxy”] [plugins.”io.containerd.grpc.v1.cri”.registry.configs] [plugins.”io.containerd.grpc.v1.cri”.registry.configs.”artifactory.proxy”.auth] auth = “AAAABBBCCCDDD==” EOF nodeGroups:

  • “*” weight: 49

The priority field of the NodeGroup CustomResource allows you to define the order in which nodes will be provisioned in the cluster. For example, cluster-autoscaler can first provision spot-nodes and switch to regular ones when they run out. Or it can provision larger nodes when there are plenty of resources in the cluster and then switch to smaller nodes once cluster resources run out.

Как использовать NodeGroup с приоритетом?

Here is an example of creating two NodeGroups using spot-node nodes:

С помощью параметра priority custom resource’а NodeGroup можно задавать порядок заказа узлов в кластере. Например, можно сделать так, чтобы сначала заказывались узлы типа spot-node, а если они закончились — обычные узлы. Или чтобы при наличии ресурсов в облаке заказывались узлы большего размера, а при их исчерпании — узлы меньшего размера.

yaml

apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: worker-spot spec: cloudInstances: classReference: kind: AWSInstanceClass name: worker-spot maxPerZone: 5 minPerZone: 0 priority: 50 nodeType: CloudEphemeral — apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: worker spec: cloudInstances: classReference: kind: AWSInstanceClass name: worker maxPerZone: 5 minPerZone: 0 priority: 30 nodeType: CloudEphemeral

Пример создания двух NodeGroup с использованием узлов типа spot-node:

In the above example, cluster-autoscaler will first try to provision a spot-node. If it fails to add such a node to the cluster within 15 minutes, the worker-spot NodeGroup will be paused (for 20 minutes), and cluster-autoscaler will start provisioning nodes from the worker NodeGroup. If, after 30 minutes, another node needs to be deployed in the cluster, cluster-autoscaler will first attempt to provision a node from the worker-spot NodeGroup before provisioning one from the worker NodeGroup.

yaml

apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: worker-spot spec: cloudInstances: classReference: kind: AWSInstanceClass name: worker-spot maxPerZone: 5 minPerZone: 0 priority: 50 nodeType: CloudEphemeral — apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: worker spec: cloudInstances: classReference: kind: AWSInstanceClass name: worker maxPerZone: 5 minPerZone: 0 priority: 30 nodeType: CloudEphemeral

Once the worker-spot NodeGroup reaches its maximum (5 nodes in the example above), the nodes will be provisioned from the worker NodeGroup.

В приведенном выше примере cluster-autoscaler сначала попытается заказать узел типа spot-node. Если в течение 15 минут его не получится добавить в кластер, NodeGroup worker-spot будет поставлена на паузу (на 20 минут) и cluster-autoscaler начнет заказывать узлы из NodeGroup worker. Если через 30 минут в кластере возникнет необходимость развернуть еще один узел, cluster-autoscaler сначала попытается заказать узел из NodeGroup worker-spot и только потом — из NodeGroup worker.

Note that node templates (labels/taints) for worker and worker-spot NodeGroups must be the same (or at least suitable for the load that triggers the cluster scaling process).

После того как NodeGroup worker-spot достигнет своего максимума (5 узлов в примере выше), узлы будут заказываться из NodeGroup worker.

How to interpret Node Group states?

Шаблоны узлов (labels/taints) для NodeGroup worker и worker-spot должны быть одинаковыми или как минимум подходить для той нагрузки, которая запускает процесс увеличения кластера.

Ready — the node group contains the minimum required number of scheduled nodes with the status Ready for all zones.

Как интерпретировать состояние группы узлов?

Example 1. A group of nodes in the Ready state:

Ready — группа узлов содержит минимально необходимое число запланированных узлов с состоянием Ready для всех зон.

yaml apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: ng1 spec: nodeType: CloudEphemeral cloudInstances: maxPerZone: 5 minPerZone: 1 status: conditions:

  • status: “True” type: Ready — apiVersion: v1 kind: Node metadata: name: node1 labels: node.deckhouse.io/group: ng1 status: conditions:
  • status: “True” type: Ready

Пример 1. Группа узлов в состоянии Ready:

Example 2. A group of nodes in the Not Ready state:

yaml apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: ng1 spec: nodeType: CloudEphemeral cloudInstances: maxPerZone: 5 minPerZone: 1 status: conditions:

  • status: “True” type: Ready — apiVersion: v1 kind: Node metadata: name: node1 labels: node.deckhouse.io/group: ng1 status: conditions:
  • status: “True” type: Ready

yaml apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: ng1 spec: nodeType: CloudEphemeral cloudInstances: maxPerZone: 5 minPerZone: 2 status: conditions:

  • status: “False” type: Ready — apiVersion: v1 kind: Node metadata: name: node1 labels: node.deckhouse.io/group: ng1 status: conditions:
  • status: “True” type: Ready

Пример 2. Группа узлов в состоянии Not Ready:

Updating — a node group contains at least one node in which there is an annotation with the prefix update.node.deckhouse.io (for example, update.node.deckhouse.io/waiting-for-approval).

yaml apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: ng1 spec: nodeType: CloudEphemeral cloudInstances: maxPerZone: 5 minPerZone: 2 status: conditions:

  • status: “False” type: Ready — apiVersion: v1 kind: Node metadata: name: node1 labels: node.deckhouse.io/group: ng1 status: conditions:
  • status: “True” type: Ready

WaitingForDisruptiveApproval - a node group contains at least one node that has an annotation update.node.deckhouse.io/disruption-required and there is no annotation update.node.deckhouse.io/disruption-approved.

Updating — группа узлов содержит как минимум один узел, в котором присутствует аннотация с префиксом update.node.deckhouse.io (например, update.node.deckhouse.io/waiting-for-approval).

Scaling — calculated only for node groups with the type CloudEphemeral. The state True can be in two cases:

WaitingForDisruptiveApproval — группа узлов содержит как минимум один узел, в котором присутствует аннотация update.node.deckhouse.io/disruption-required и отсутствует аннотация update.node.deckhouse.io/disruption-approved.

  1. When the number of nodes is less than the desired number of nodes in the group, i.e. when it is necessary to increase the number of nodes in the group.
  2. When a node is marked for deletion or the number of nodes is greater than the desired number of nodes, i.e. when it is necessary to reduce the number of nodes in the group.

Scaling — рассчитывается только для групп узлов с типом CloudEphemeral. Состояние True может быть в двух случаях:

The desired number of nodes is the sum of all replicas in the node group.

  1. Когда число узлов меньше желаемого числа узлов в группе, то есть когда нужно увеличить число узлов в группе.
  2. Когда какой-то узел помечается к удалению или число узлов больше желаемого числа узлов, то есть когда нужно уменьшить число узлов в группе.

Example. The desired number of nodes is 2:

Желаемое число узлов — это сумма всех реплик, входящих в группу узлов.

yaml apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: ng1 spec: nodeType: CloudEphemeral cloudInstances: maxPerZone: 5 minPerZone: 2 status: … desired: 2 …

Пример. Желаемое число узлов равно 2:

Error — contains the last error that occurred when creating a node in a node group.

yaml apiVersion: deckhouse.io/v1 kind: NodeGroup metadata: name: ng1 spec: nodeType: CloudEphemeral cloudInstances: maxPerZone: 5 minPerZone: 2 status: … desired: 2 …

How do I make werf ignore the Ready conditions in a node group?

Error — содержит последнюю ошибку, возникшую при создании узла в группе узлов.

werf checks the Ready status of resources and, if available, waits for the value to become True.

Как заставить werf игнорировать состояние Ready в группе узлов?

Creating (updating) a nodeGroup resource in a cluster can take a significant amount of time to create the required number of nodes. When deploying such a resource in a cluster using werf (e.g., as part of a CI/CD process), deployment may terminate when resource readiness timeout is exceeded. To make werf ignore the nodeGroup status, the following nodeGroup annotations must be added:

werf проверяет состояние Ready у ресурсов и в случае его наличия дожидается, пока значение станет True.

yaml metadata: annotations: werf.io/fail-mode: IgnoreAndContinueDeployProcess werf.io/track-termination-mode: NonBlocking

Создание (обновление) ресурса nodeGroup в кластере может потребовать значительного времени на развертывание необходимого количества узлов. При развертывании такого ресурса в кластере с помощью werf (например, в рамках процесса CI/CD) развертывание может завершиться по превышении времени ожидания готовности ресурса. Чтобы заставить werf игнорировать состояние nodeGroup, необходимо добавить к nodeGroup следующие аннотации:

What is an Instance resource?

yaml metadata: annotations: werf.io/fail-mode: IgnoreAndContinueDeployProcess werf.io/track-termination-mode: NonBlocking

An Instance resource contains a description of an implementation-independent ephemeral machine resource. For example, machines created by MachineControllerManager or Cluster API Provider Static will have a corresponding Instance resource.

Что такое ресурс Instance?

The object does not contain a specification. The status contains:

  1. A link to the InstanceClass if it exists for this implementation;
  2. A link to the Kubernetes Node object;
  3. Current machine status;
  4. Information on how to view machine creation logs (at the machine creation stage).

Ресурс Instance содержит описание объекта эфемерной машины, без учета ее конкретной реализации. Например, машины созданные MachineControllerManager или Cluster API Provider Static будут иметь соответcтвующий ресурс Instance.

When a machine is created/deleted, the Instance object is created/deleted accordingly. You cannot create an Instance resource yourself, but you can delete it. In this case, the machine will be removed from the cluster (the removal process depends on implementation details.

Объект не содержит спецификации. Статус содержит:

  1. Ссылку на InstanceClass, если он существует для данной реализации.
  2. Ссылку на объект Node Kubernetes.
  3. Текущий статус машины.
  4. Информацию о том, как посмотреть логи создания машины (появляется на этапе создания машины).

При создании/удалении машины создается/удаляется соответствующий объект Instance. Самостоятельно ресурс Instance создать нельзя, но можно удалить. В таком случае машина будет удалена из кластера (процесс удаления зависит от деталей реализации).