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

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

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

See the control-plane-manager module FAQ.

Как конвертировать кластер с одним master-узлом в мультикластерный описано в FAQ модуля control-plane-manager.

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

See the control-plane-manager module FAQ.

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

Static nodes

Как конвертировать мультимастерный кластер в кластер с одним master-узлом описано в FAQ модуля control-plane-manager.

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

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

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

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

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

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

  1. Prepare the required resources:

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

  • Allocate a server or virtual machine and ensure that the node has the necessary network connectivity with the cluster.
  1. Подготовьте необходимые ресурсы:
  • If necessary, install additional operating system packages and configure the mount points that will be used on the node.
  • Выделите сервер или виртуальную машину и убедитесь, что узел имеет необходимую сетевую связанность с кластером.
  1. Create a user with sudo` privileges:
  • При необходимости установите дополнительные пакеты ОС и настройте точки монтирования, которые будут использоваться на узле.
  • Add a new user (in this example, caps) with sudo privileges:
  1. Создайте пользователя с правами sudo:

shell useradd -m -s /bin/bash caps usermod -aG sudo caps

  • Добавьте нового пользователя (в данном примере — caps) с правами выполнения команд через sudo:
  • Allow the user to run sudo commands without having to enter a password. For this, add the following line to the sudo configuration on the server (you can either edit the /etc/sudoers file, or run the sudo visudo command, or use some other method):

shell useradd -m -s /bin/bash caps usermod -aG sudo caps

shell caps ALL=(ALL) NOPASSWD: ALL

  • Разрешите пользователю выполнять команды через sudo без ввода пароля. Для этого отредактируйте конфигурацию sudo (отредактировав файл /etc/sudoers, выполнив команду sudo visudo или другим способом):
  1. Set UsePAM to yes in /etc/ssh/sshd_config on server and restart sshd service:

shell caps ALL=(ALL) NOPASSWD: ALL

shell sudo systemctl restart sshd

  1. На сервере откройте файл /etc/ssh/sshd_config и убедитесь, что параметр UsePAM установлен в значение yes. Затем перезапустите службу sshd:
  1. Generate a pair of SSH keys with an empty passphrase on the server:

shell sudo systemctl restart sshd

shell ssh-keygen -t rsa -f caps-id -C “” -N “”

  1. Сгенерируйте на сервере пару SSH-ключей с пустой парольной фразой:

The public and private keys of the caps user will be stored in the caps-id.pub and caps-id files in the current directory on the server.

shell ssh-keygen -t rsa -f caps-id -C “” -N “”

  1. Add the generated public key to the /home/caps/.ssh/authorized_keys file of the caps user by executing the following commands in the keys directory on the server:

Приватный и публичный ключи будут сохранены в файлах caps-id и caps-id.pub соответственно в текущей директории.

shell mkdir -p /home/caps/.ssh cat caps-id.pub » /home/caps/.ssh/authorized_keys chmod 700 /home/caps/.ssh chmod 600 /home/caps/.ssh/authorized_keys chown -R caps:caps /home/caps/

  1. Добавьте полученный публичный ключ в файл /home/caps/.ssh/authorized_keys пользователя caps, выполнив в директории с ключами на сервере следующие команды:
  1. Create the SSHCredentials resource.
  2. Create the StaticInstance resource.
  3. Create the NodeGroup resource with the Static nodeType, specify the desired number of nodes in the group and, if necessary, the filter for StaticInstance.

shell mkdir -p /home/caps/.ssh cat caps-id.pub » /home/caps/.ssh/authorized_keys chmod 700 /home/caps/.ssh chmod 600 /home/caps/.ssh/authorized_keys chown -R caps:caps /home/caps/

An example of adding a static node.

  1. Создайте ресурс SSHCredentials.
  2. Создайте ресурс StaticInstance.
  3. Создайте ресурс NodeGroup с nodeType Static, указав желаемое количество узлов в группе и, при необходимости, фильтр выбора StaticInstance.

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

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

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.

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

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

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

  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:

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

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

  1. Получите один из адресов Kubernetes API-сервера. Обратите внимание, что IP-адрес должен быть доступен с узлов, которые добавляются в кластер:

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

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

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

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

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

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

  1. If the Kubernetes version is smaller than 1.25, get a Kubernetes API token for a special ServiceAccount that Deckhouse manages:

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

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. Если версия Kubernetes меньше 1.25, получите Kubernetes API-токен для специального ServiceAccount’а, которым управляет Deckhouse:
  1. Create Ansible playbook with vars replaced with values from previous steps:

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, которые заменены на полученные на предыдущих шагах значения:

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

  1. Определите дополнительную переменную node_group. Значение переменной должно совпадать с именем NodeGroup, которой будет принадлежать узел. Переменную можно передать различными способами, например с использованием inventory-файла:

[system:vars] node_group=system

text [system] system-0 system-1

[worker] worker-0 worker-1

[system:vars] node_group=system

[worker:vars] node_group=worker

[worker] worker-0 worker-1

  1. Run the playbook with the inventory file.

[worker:vars] node_group=worker

How do I clean up a static node manually?

  1. Запустите выполнение playbook’а с использованием inventory-файла.

This method is valid for both manually configured nodes (using the bootstrap script) and nodes configured using 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

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

Can I delete a StaticInstance?

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

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

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

To delete a StaticInstance in any state other than Pending (Running, Cleaning, Bootstrapping), you need to:

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

  1. Add the label "node.deckhouse.io/allow-bootstrap": "false" to the StaticInstance.
  2. Wait until the StaticInstance status becomes Pending.
  3. Delete the StaticInstance.
  4. Decrease the NodeGroup.spec.staticInstances.count field by 1.

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

How do I change the IP address of a StaticInstance?

Чтобы удалить StaticInstance находящийся в любом состоянии, отличном от Pending (Running, Cleaning, Bootstrapping), выполните следующие шаги:

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.

  1. Добавьте метку "node.deckhouse.io/allow-bootstrap": "false" в StaticInstance.
  2. Дождитесь, пока StaticInstance перейдет в статус Pending.
  3. Удалите StaticInstance.
  4. Уменьшите значение параметра NodeGroup.spec.staticInstances.count на 1.

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

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

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

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

How do I change the NodeGroup of a static node?

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

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.

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

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

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

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

Applying the changes will take some time.

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

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

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

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.

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

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

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

  1. Delete the node from the Kubernetes cluster:

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

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

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

  1. Run cleanup script on the node:

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

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

  1. Удалите узел из кластера Kubernetes:
  1. Run the bootstrap.sh script after reboot of the node.

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

How do I know if something went wrong?

  1. Запустите на узле скрипт очистки:

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.

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

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

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

shell journalctl -fu bashible

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

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

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

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.

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

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

shell journalctl -fu bashible

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:

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.

shell kubectl get instances | grep Pending

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

An example:

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

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

  1. Найдите узел, который находится в стадии бутстрапа:
  1. Get information about connection parameters for viewing logs:

shell kubectl get instances | grep Pending

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

Пример:

An example:

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

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. Получите информацию о параметрах подключения для просмотра логов:
  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.

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

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

Пример:

How do I update kernel on nodes?

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

Debian-based distros

  1. Выполните полученную команду (в примере выше — nc 192.168.199.178 8000), чтобы просмотреть логи cloud-init и определить, на каком этапе остановилась настройка узла.

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

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

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”

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

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 }

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

version_in_use=”$(uname -r)”

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.

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

desired_version=”5.15.0-53-generic”

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

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 }

CentOS-based distros

version_in_use=”$(uname -r)”

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

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

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.

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

desired_version=”3.10.0-1160.42.2.el7.x86_64”

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

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 }

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

version_in_use=”$(uname -r)”

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.

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

desired_version=”3.10.0-1160.42.2.el7.x86_64”

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

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 }

NodeGroup parameters and their result

version_in_use=”$(uname -r)”

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

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

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

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

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.

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

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.

Параметр 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 - - -

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

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

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.

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

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.

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

How do I allocate nodes to specific loads?

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

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 (как в модуле node-manager, так и в любом из облачных провайдеров) виртуальные машины не будут перезаказаны. Пересоздание происходит только после изменения ресурсов InstanceClass или NodeGroup.

There are two ways to solve this problem:

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

  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.

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

Deckhouse tolerates the dedicated by default, so we recommend using the dedicated key with any value for taints on your dedicated nodes.️

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

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.

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

How to allocate nodes to system components?

  1. Установка меток в NodeGroup spec.nodeTemplate.labels для последующего использования их в Pod spec.nodeSelector или spec.affinity.nodeAffinity. Указывает, какие именно узлы будут выбраны планировщиком для запуска целевого приложения.
  2. Установка ограничений в NodeGroup spec.nodeTemplate.taints с дальнейшим снятием их в Pod spec.tolerations. Запрещает исполнение не разрешенных явно приложений на этих узлах.

Frontend

Deckhouse по умолчанию поддерживает использование taint’а с ключом dedicated, поэтому рекомендуется применять этот ключ с любым значением для taints на ваших выделенных узлах.

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

Если требуется использовать другие ключи для taints (например, dedicated.client.com), необходимо добавить соответствующее значение ключа в параметр modules.placement.customTolerationKeys. Это обеспечит разрешение системным компонентам, таким как cni-flannel, использовать эти узлы.

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

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

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

System components

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

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

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

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

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

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

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:

Для компонентов подсистем Deckhouse параметр 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 on nodes that are not handled by Deckhouse (e.g., the filebeat DaemonSet), you can specify the percentage of node resources they can consume via the standbyHolder.overprovisioningRate 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.

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

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

An example:

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

yaml cloudInstances: maxPerZone: 10 minPerZone: 1 standby: 10% standbyHolder: overprovisioningRate: 30%

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

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

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

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

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

Set the mcmEmergencyBrake parameter to true:

Пример:

yaml mcmEmergencyBrake: true

yaml cloudInstances: maxPerZone: 10 minPerZone: 1 standby: 10% standbyHolder: overprovisioningRate: 30%

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

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

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.

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

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

Для того чтобы временно отключить machine-controller-manager (MCM) и предотвратить его автоматические действия, которые могут повлиять на инфраструктуру кластера (например, удаление или пересоздание узлов), установите следующий параметр в конфигурации:

containerd

yaml mcmEmergencyBrake: true

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

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

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

Copy the command’s output and use it for setting the AUTH variable on the corrupted master.

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

Next, you need to pull images of control plane components to the corrupted master:

containerd

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

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

You need to restart kubelet after pulling the images.

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

How to change CRI for NodeGroup?

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

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

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

Set NodeGroup cri.type to Containerd or NotManaged.

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

NodeGroup YAML example:

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

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

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

Also, this operation can be done with patch:

Смена CRI возможна только между Containerd на NotManaged и обратно (параметр cri.type).

  • For Containerd:

Для изменения CRI для NodeGroup, установите параметр cri.type в Containerd или в NotManaged.

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

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

  • For NotManaged:

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

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

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

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

  • Для Containerd:

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.

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

How to change CRI for the whole cluster?

  • Для NotManaged:

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

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

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

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

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

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

  • For Containerd:

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

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"}}”

Смена CRI возможна только между Containerd на NotManaged и обратно (параметр cri.type).

  • For NotManaged:

Для изменения CRI для всего кластера, необходимо с помощью утилиты 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/Containerd/NotManaged/” | base64 -w0)” kubectl -n kube-system patch secret d8-cluster-configuration -p “{"data":{"cluster-configuration.yaml":"$data"}}”

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

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.

  • Для Containerd:

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.

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"}}”

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

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

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"}}”

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

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

  1. Confirm the disruption of the master node that was discovered in the previous step:

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

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

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

  1. Wait for the updated master node to switch to Ready state. Repeat steps for the next master node.
  1. Чтобы определить, какой узел в текущий момент обновляется в master NodeGroup, используйте следующую команду:

How to add node configuration 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

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

  1. Подтвердите остановку (disruption) для master-узла, полученного на предыдущем шаге:

How to automatically put custom labels on the node?

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

  1. On the node, create the directory /var/lib/node_labels.
  1. Дождаитесь перехода обновленного master-узла в Ready. Выполните итерацию для следующего master-узла.
  1. Create a file or files containing the necessary labels in it. The number of files can be any, as well as the number of subdirectories containing them.

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

  1. Add the necessary labels to the files in the key=value format. For example:

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

console example-label=test

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

  1. Save the files.
  1. На узле создайте каталог /var/lib/node_labels.

When adding a node to the cluster, the labels specified in the files will be automatically affixed to the node.

  1. Создайте в нём файл или файлы, содержащие необходимые лейблы. Количество файлов может быть любым, как и вложенность подкаталогов, их содержащих.

Please note that it is not possible to add labels used in DKP in this way. This method will only work with custom labels that do not overlap with those reserved for Deckhouse.

  1. Добавьте в файлы нужные лейблы в формате key=value. Например:

How to use containerd with Nvidia GPU support?

console example-label=test

Create NodeGroup for GPU-nodes.

  1. Сохраните файлы.

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

При добавлении узла в кластер указанные в файлах лейблы будут автоматически проставлены на узел.

Create NodeGroupConfiguration for containerd configuration of NodeGroup gpu:

Обратите внимание, что добавить таким образом лейблы, использующиеся в DKP, невозможно. Работать такой метод будет только с кастомными лейблами, не пересекающимися с зарезервированными для Deckhouse.

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.

Как использовать containerd с поддержкой Nvidia 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: 31

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

Create NodeGroupConfiguration for Nvidia drivers setup on NodeGroup gpu.

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

Ubuntu

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

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.

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.

if [ ! -f “/etc/apt/sources.list.d/nvidia-container-toolkit.list” ]; then 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 fi bb-apt-install nvidia-container-toolkit nvidia-driver-535-server nvidia-ctk config –set nvidia-container-runtime.log-level=error –in-place nodeGroups:

  • gpu weight: 30

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

Centos

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

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.

Ubuntu

if [ ! -f “/etc/yum.repos.d/nvidia-container-toolkit.repo” ]; then 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 fi bb-yum-install nvidia-container-toolkit nvidia-driver nvidia-ctk config –set nvidia-container-runtime.log-level=error –in-place 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.

Bootstrap and reboot node.

if [ ! -f “/etc/apt/sources.list.d/nvidia-container-toolkit.list” ]; then 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 fi bb-apt-install nvidia-container-toolkit nvidia-driver-535-server nvidia-ctk config –set nvidia-container-runtime.log-level=error –in-place nodeGroups:

  • gpu weight: 30

How to check if it was successful?

Centos

Deploy the Job:

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.

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

if [ ! -f “/etc/yum.repos.d/nvidia-container-toolkit.repo” ]; then 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 fi bb-yum-install nvidia-container-toolkit nvidia-driver nvidia-ctk config –set nvidia-container-runtime.log-level=error –in-place nodeGroups:

  • gpu weight: 30

And check the logs:

После того как конфигурации будут применены, необходимо провести бутстрап и перезагрузить узлы, чтобы применить настройки и установить драйвера.

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 | +—————————————————————————–+

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

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

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”

Проверьте логи командой:

And check the logs:

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 | +——————————-+———————-+———————-+

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

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

How to deploy custom containerd configuration?

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

The example of NodeGroupConfiguration uses functions of the script 032_configure_containerd.sh.

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”

Adding custom settings causes a restart of the containerd service.

Проверьте логи командой:

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

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

You can override the values of the parameters that are specified in the file /etc/containerd/deckhouse.toml, but you will have to ensure their functionality on your own. Also, it is better not to change the configuration for the master nodes (nodeGroup master).

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

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: containerd-option-config.sh spec: bundles:

  • ‘*’ content: | Copyright 2024 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 основан на функциях, заложенных в скрипте 032_configure_containerd.sh.

mkdir -p /etc/containerd/conf.d bb-sync-file /etc/containerd/conf.d/additional_option.toml - « EOF oom_score = 500 [metrics] address = “127.0.0.1” grpc_histogram = true EOF nodeGroups:

  • “worker” weight: 31

Добавление кастомных настроек вызывает перезапуск сервиса containerd.

How to add additional registry auth?

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

Deploy NodeGroupConfiguration script:

Вы можете переопределять значения параметров, которые заданы в файле /etc/containerd/deckhouse.toml, но их работу придётся обеспечивать самостоятельно. Также, лучше изменением конфигурации не затрагивать master-узлы (nodeGroup master).

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. REGISTRY_URL=private.registry.example

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: containerd-option-config.sh spec: bundles:

  • ‘*’ content: | Copyright 2024 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.

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.”${REGISTRY_URL}”] endpoint = [“https://${REGISTRY_URL}”] [plugins.”io.containerd.grpc.v1.cri”.registry.configs] [plugins.”io.containerd.grpc.v1.cri”.registry.configs.”${REGISTRY_URL}”.auth] auth = “AAAABBBCCCDDD==” EOF nodeGroups:

  • “*” weight: 31

mkdir -p /etc/containerd/conf.d bb-sync-file /etc/containerd/conf.d/additional_option.toml - « EOF oom_score = 500 [metrics] address = “127.0.0.1” grpc_histogram = true EOF nodeGroups:

  • “worker” weight: 31

How to configure a certificate for an additional registry?

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

In addition to containerd, the certificate can be simultaneously added into the OS.

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

Example of the NodeGroupConfiguration resource for configuring a certificate for an additional 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. REGISTRY_URL=private.registry.example

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: configure-cert-containerd.sh spec: bundles:

  • ‘*’ content: |- Copyright 2024 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.

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.”${REGISTRY_URL}”] endpoint = [“https://${REGISTRY_URL}”] [plugins.”io.containerd.grpc.v1.cri”.registry.configs] [plugins.”io.containerd.grpc.v1.cri”.registry.configs.”${REGISTRY_URL}”.auth] auth = “AAAABBBCCCDDD==” EOF nodeGroups:

  • “*” weight: 31

REGISTRY_URL=private.registry.example CERT_FILE_NAME=${REGISTRY_URL} CERTS_FOLDER=”/var/lib/containerd/certs/” CERT_CONTENT=$(cat «“EOF” —–BEGIN CERTIFICATE—– MIIDSjCCAjKgAwIBAgIRAJ4RR/WDuAym7M11JA8W7D0wDQYJKoZIhvcNAQELBQAw JTEjMCEGA1UEAxMabmV4dXMuNTEuMjUwLjQxLjIuc3NsaXAuaW8wHhcNMjQwODAx MTAzMjA4WhcNMjQxMDMwMTAzMjA4WjAlMSMwIQYDVQQDExpuZXh1cy41MS4yNTAu NDEuMi5zc2xpcC5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL1p WLPr2c4SZX/i4IS59Ly1USPjRE21G4pMYewUjkSXnYv7hUkHvbNL/P9dmGBm2Jsl WFlRZbzCv7+5/J+9mPVL2TdTbWuAcTUyaG5GZ/1w64AmAWxqGMFx4eyD1zo9eSmN G2jis8VofL9dWDfUYhRzJ90qKxgK6k7tfhL0pv7IHDbqf28fCEnkvxsA98lGkq3H fUfvHV6Oi8pcyPZ/c8ayIf4+JOnf7oW/TgWqI7x6R1CkdzwepJ8oU7PGc0ySUWaP G5bH3ofBavL0bNEsyScz4TFCJ9b4aO5GFAOmgjFMMUi9qXDH72sBSrgi08Dxmimg Hfs198SZr3br5GTJoAkCAwEAAaN1MHMwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB /wQCMAAwUwYDVR0RBEwwSoIPbmV4dXMuc3ZjLmxvY2FsghpuZXh1cy41MS4yNTAu NDEuMi5zc2xpcC5pb4IbZG9ja2VyLjUxLjI1MC40MS4yLnNzbGlwLmlvMA0GCSqG SIb3DQEBCwUAA4IBAQBvTjTTXWeWtfaUDrcp1YW1pKgZ7lTb27f3QCxukXpbC+wL dcb4EP/vDf+UqCogKl6rCEA0i23Dtn85KAE9PQZFfI5hLulptdOgUhO3Udluoy36 D4WvUoCfgPgx12FrdanQBBja+oDsT1QeOpKwQJuwjpZcGfB2YZqhO0UcJpC8kxtU by3uoxJoveHPRlbM2+ACPBPlHu/yH7st24sr1CodJHNt6P8ugIBAZxi3/Hq0wj4K aaQzdGXeFckWaxIny7F1M3cIWEXWzhAFnoTgrwlklf7N7VWHPIvlIh1EYASsVYKn iATq8C7qhUOGsknDh3QSpOJeJmpcBwln11/9BGRP —–END CERTIFICATE—– EOF )

Как настроить сертификат для дополнительного registry?

CONFIG_CONTENT=$(cat «EOF [plugins] [plugins.”io.containerd.grpc.v1.cri”.registry.configs.”${REGISTRY_URL}”.tls] ca_file = “${CERTS_FOLDER}/${CERT_FILE_NAME}.crt” EOF )

Помимо containerd, сертификат можно одновременно добавить и в операционной системе.

mkdir -p ${CERTS_FOLDER} mkdir -p /etc/containerd/conf.d

Пример NodeGroupConfiguration для настройки сертификата для дополнительного registry:

bb-tmp-file - Create temp file function. More information: http://www.bashbooster.net/#tmp

yaml apiVersion: deckhouse.io/v1alpha1 kind: NodeGroupConfiguration metadata: name: configure-cert-containerd.sh spec: bundles:

  • ‘*’ content: |- Copyright 2024 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.

CERT_TMP_FILE=”$( bb-tmp-file )” echo -e “${CERT_CONTENT}” > “${CERT_TMP_FILE}”
CONFIG_TMP_FILE=”$( bb-tmp-file )” echo -e “${CONFIG_CONTENT}” > “${CONFIG_TMP_FILE}”

REGISTRY_URL=private.registry.example CERT_FILE_NAME=${REGISTRY_URL} CERTS_FOLDER=”/var/lib/containerd/certs/” CERT_CONTENT=$(cat «“EOF” —–BEGIN CERTIFICATE—– MIIDSjCCAjKgAwIBAgIRAJ4RR/WDuAym7M11JA8W7D0wDQYJKoZIhvcNAQELBQAw JTEjMCEGA1UEAxMabmV4dXMuNTEuMjUwLjQxLjIuc3NsaXAuaW8wHhcNMjQwODAx MTAzMjA4WhcNMjQxMDMwMTAzMjA4WjAlMSMwIQYDVQQDExpuZXh1cy41MS4yNTAu NDEuMi5zc2xpcC5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL1p WLPr2c4SZX/i4IS59Ly1USPjRE21G4pMYewUjkSXnYv7hUkHvbNL/P9dmGBm2Jsl WFlRZbzCv7+5/J+9mPVL2TdTbWuAcTUyaG5GZ/1w64AmAWxqGMFx4eyD1zo9eSmN G2jis8VofL9dWDfUYhRzJ90qKxgK6k7tfhL0pv7IHDbqf28fCEnkvxsA98lGkq3H fUfvHV6Oi8pcyPZ/c8ayIf4+JOnf7oW/TgWqI7x6R1CkdzwepJ8oU7PGc0ySUWaP G5bH3ofBavL0bNEsyScz4TFCJ9b4aO5GFAOmgjFMMUi9qXDH72sBSrgi08Dxmimg Hfs198SZr3br5GTJoAkCAwEAAaN1MHMwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB /wQCMAAwUwYDVR0RBEwwSoIPbmV4dXMuc3ZjLmxvY2FsghpuZXh1cy41MS4yNTAu NDEuMi5zc2xpcC5pb4IbZG9ja2VyLjUxLjI1MC40MS4yLnNzbGlwLmlvMA0GCSqG SIb3DQEBCwUAA4IBAQBvTjTTXWeWtfaUDrcp1YW1pKgZ7lTb27f3QCxukXpbC+wL dcb4EP/vDf+UqCogKl6rCEA0i23Dtn85KAE9PQZFfI5hLulptdOgUhO3Udluoy36 D4WvUoCfgPgx12FrdanQBBja+oDsT1QeOpKwQJuwjpZcGfB2YZqhO0UcJpC8kxtU by3uoxJoveHPRlbM2+ACPBPlHu/yH7st24sr1CodJHNt6P8ugIBAZxi3/Hq0wj4K aaQzdGXeFckWaxIny7F1M3cIWEXWzhAFnoTgrwlklf7N7VWHPIvlIh1EYASsVYKn iATq8C7qhUOGsknDh3QSpOJeJmpcBwln11/9BGRP —–END CERTIFICATE—– EOF )

bb-sync-file - File synchronization function. More information: http://www.bashbooster.net/#sync “${CERTS_FOLDER}/${CERT_FILE_NAME}.crt” - Destination file ${CERT_TMP_FILE} - Source file

CONFIG_CONTENT=$(cat «EOF [plugins] [plugins.”io.containerd.grpc.v1.cri”.registry.configs.”${REGISTRY_URL}”.tls] ca_file = “${CERTS_FOLDER}/${CERT_FILE_NAME}.crt” EOF )

bb-sync-file
“${CERTS_FOLDER}/${CERT_FILE_NAME}.crt”
${CERT_TMP_FILE}

mkdir -p ${CERTS_FOLDER} mkdir -p /etc/containerd/conf.d

bb-sync-file
“/etc/containerd/conf.d/${REGISTRY_URL}.toml”
${CONFIG_TMP_FILE} nodeGroups:

  • ‘*’
    weight: 31

bb-tmp-file - Create temp file function. More information: http://www.bashbooster.net/#tmp

How to use NodeGroup’s priority feature

CERT_TMP_FILE=”$( bb-tmp-file )” echo -e “${CERT_CONTENT}” > “${CERT_TMP_FILE}”
CONFIG_TMP_FILE=”$( bb-tmp-file )” echo -e “${CONFIG_CONTENT}” > “${CONFIG_TMP_FILE}”

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.

bb-sync-file - File synchronization function. More information: http://www.bashbooster.net/#sync “${CERTS_FOLDER}/${CERT_FILE_NAME}.crt” - Destination file ${CERT_TMP_FILE} - Source file

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

bb-sync-file
“${CERTS_FOLDER}/${CERT_FILE_NAME}.crt”
${CERT_TMP_FILE}

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

bb-sync-file
“/etc/containerd/conf.d/${REGISTRY_URL}.toml”
${CONFIG_TMP_FILE} nodeGroups:

  • ‘*’
    weight: 31

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.

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

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

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

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 с использованием узлов типа spot-node:

How to interpret Node Group states?

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

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

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

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

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

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

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

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

Ready — группа узлов содержит минимально необходимое число запланированных узлов с состоянием 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).

Пример 1. Группа узлов в состоянии 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.

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

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

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

  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.

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

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

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

Example. The desired number of nodes is 2:

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

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

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

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

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

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

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

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

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

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:

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

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

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

What is an Instance resource?

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

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.

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

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

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

  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).

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

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).

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

When is a node reboot required?

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

Node reboots may be required after configuration changes. For example, after changing certain sysctl settings, specifically when modifying the kernel.yama.ptrace_scope parameter (e.g., using astra-ptrace-lock enable/disable in the Astra Linux distribution).

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

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

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

 

Когда требуется перезагрузка узлов?

 

Некоторые операции по изменению конфигурации узлов могут потребовать перезагрузки.

 

Перезагрузка узла может потребоваться при изменении некоторых настроек sysctl, например, при изменении параметра kernel.yama.ptrace_scope (изменяется при использовании команды astra-ptrace-lock enable/disable в Astra Linux).