ALT Container OS подветка K8S. Создание HA кластера: различия между версиями

Материал из ALT Linux Wiki
Строка 51: Строка 51:


Для работы высоко-доступного (Highly Available) kubernetes-кластера необходимо на всех трех узлах поднять балансировщик, распределяющий входящие запросы между мастер-узлами кластера.
Для работы высоко-доступного (Highly Available) kubernetes-кластера необходимо на всех трех узлах поднять балансировщик, распределяющий входящие запросы между мастер-узлами кластера.
Для поддержки отказоустойчивости самого балансировщика создают несколько HOST-систем на которых запускают балансировщики  
Для поддержки отказоустойчивости самого балансировщика на  HOST-системах  запускаются балансировщики.
разделяющий один общий виртуальный адрес.  
Одному их балансировщику присваивается виртуальный  адрес ''10.150.0.160''. 
При выходе из строя или потери доступности основного балансировщика виртуальный адрес присваивается
другому доступному балансировщику.  


Для создания балансировщика установите пакеты:
Для создания балансировщика установите пакеты:
Строка 114: Строка 116:
В секции ''balance roundrobin'' укажите список имен, IP-адресов и портов 6443 API-интерфейсов мастер-узлов.
В секции ''balance roundrobin'' укажите список имен, IP-адресов и портов 6443 API-интерфейсов мастер-узлов.


HAPROXY будет принимать входящие соединения на порту ''8443'' и передавать их на один из перечисленных master-серверов на порт ''6443''.
''haproxy'' будет принимать входящие соединения на порту ''8443'' и передавать их на один из  
перечисленных ''master-серверов'' на порт ''6443''.


==== Конфигурирование keepalived ====
==== Конфигурирование keepalived ====
Строка 153: Строка 156:
На остальных параметр ''state'' в значение ''BACKUP'' и параметр ''priority'' в значение ''100''.
На остальных параметр ''state'' в значение ''BACKUP'' и параметр ''priority'' в значение ''100''.


Скрипт ''/etc/keepalived/check_apiserver.sh'' проверят доступность балансировщика 'haproxy':
Скрипт ''/etc/keepalived/check_apiserver.sh'' проверяет доступность балансировщика ''haproxy'':
  #!/bin/sh
  #!/bin/sh
   
   
Строка 177: Строка 180:
  chmod a+x /etc/keepalived/check_apiserver.sh
  chmod a+x /etc/keepalived/check_apiserver.sh


При работающем балансировщики скрипт должен завершаться с кодом ''0''.
При работающем балансировщике и хотя бы одному доступному порту ''6443'' на ''master-узлах'' скрипт
должен завершаться с кодом ''0''.


==== Запуск сервисов ====
==== Запуск сервисов ====
Строка 185: Строка 189:
  systemctl enable keepalived --now
  systemctl enable keepalived --now


Так как master-узлы k8s еще не подняты ''haproxy'' выведет на консоль сообщение
Так как ''master-узлы'' ''k8s'' еще не подняты ''haproxy'' выведет на консоль сообщение
  haproxy[nnnn]: backend apiserver has no server available!
  haproxy[nnnn]: backend apiserver has no server available!
<!--
<!--

Версия от 19:39, 17 декабря 2021


K8s cluster.png

Настройка узлов

Создание ethernet-моста (bridge)

Для выделения IP-адресов узлов кластера в рамках IP-адресов локальной сети необходимо в интерфейсе создания сетевых интерфейсов создать в HOST-системе создать мост (например br0) и связать с ним основной ethernet-интерфейс локальной сети. Ifaceconfig.png

В нашем примере примем IP-адрес HOST-системы - 10.150.0.4/24 в подсети 10.150.0.0/24.

В дальнейшем при создании виртуальных машин в пункте конфигурирования сетевого интерфейса укажите:

  • Создать на базе: Устройство моста
  • Название устройства: br0
  • Состояние связи: активно

Vmnetconfig.png

При развертывания виртуальных машин им будут присваиваться статические адреса из подсети 10.150.0.0/24.

Конфигурирование параметров ядра

Проверьте в sysctl настройку переменных ядра :

# sysctl -a | grep net.bridge.bridge-nf-call
net.bridge.bridge-nf-call-arptables = 0
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0

Перечисленные переменные должны иметь нулевое значение, иначе связь между виртуальными может фильтроваться правилами iptables, arptables.

Если вывод команду пустой, подключите модуль br_netfilter:

modprobe br_netfilter

и обеспечьте загрузку этого модуля после перезагрузки.

Если часть переменных имеет ненулевые значения, сформируйте файл /etc/sysctl.d/99-sysctl.conf:

#
# Configure kernel parameters at boot.
# See sysctl.d(5) for more details.
#
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0

и запустите команду:

sysctl -f /etc/sysctl.d/99-sysctl.conf

Конфигурирование балансировшика

Для работы высоко-доступного (Highly Available) kubernetes-кластера необходимо на всех трех узлах поднять балансировщик, распределяющий входящие запросы между мастер-узлами кластера. Для поддержки отказоустойчивости самого балансировщика на HOST-системах запускаются балансировщики. Одному их балансировщику присваивается виртуальный адрес 10.150.0.160. При выходе из строя или потери доступности основного балансировщика виртуальный адрес присваивается другому доступному балансировщику.

Для создания балансировщика установите пакеты:

apt-get install haproxy keepalived

Конфигурирование haproxy

Создайте файл конфигурации haproxy /etc/haproxy/haproxy.cfg:

# /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    log /dev/log local0
    log /dev/log local1 notice
    daemon

#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 1
    timeout http-request    10s
    timeout queue           20s
    timeout connect         5s
    timeout client          20s
    timeout server          20s
    timeout http-keep-alive 10s
    timeout check           10s

#---------------------------------------------------------------------
# apiserver frontend which proxys to the control plane nodes
#---------------------------------------------------------------------
frontend apiserver
    bind *:8443
    mode tcp
    option tcplog
    default_backend apiserver
    
#---------------------------------------------------------------------
# round robin balancing for apiserver
#---------------------------------------------------------------------
backend apiserver
    option httpchk GET /healthz
    http-check expect status 200
    mode tcp
    option ssl-hello-chk
    balance     roundrobin
        server master01 10.150.0.161:6443 check
        server master02 10.150.0.162:6443 check
        server master03 10.150.0.163:6443 check

В секции balance roundrobin укажите список имен, IP-адресов и портов 6443 API-интерфейсов мастер-узлов.

haproxy будет принимать входящие соединения на порту 8443 и передавать их на один из перечисленных master-серверов на порт 6443.

Конфигурирование keepalived

Создайте файл конфигурации 'keepalived' /etc/keepalived/keepalived.conf:

! /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
    router_id LVS_K8S
}
vrrp_script check_apiserver {
  script "/etc/keepalived/check_apiserver.sh"
  interval 3
  weight -2
  fall 10
  rise 2
}

vrrp_instance VI_1 {
    state MASTER
    interface br0
    virtual_router_id  51
    priority 101
    authentication {
        auth_type PASS
        auth_pass 42
    }
    virtual_ipaddress {
        10.150.0.160 
    }
    track_script {
        check_apiserver
    }
}

На одном из узлов установите параметр state в значение MASTER и параметр priority в значение 101. На остальных параметр state в значение BACKUP и параметр priority в значение 100.

Скрипт /etc/keepalived/check_apiserver.sh проверяет доступность балансировщика haproxy:

#!/bin/sh

errorExit() {
    echo "*** $*" 1>&2
    exit 1
}

APISERVER_DEST_PORT=8443
APISERVER_VIP=10.150.0.160
curl --silent --max-time 2 --insecure https://localhost:${APISERVER_DEST_PORT}/ -o /dev/null || errorExit "Error GET https://localhost:${APISERVER_DEST_PORT}/"
if ip addr | grep -q ${APISERVER_VIP}; then
    curl --silent --max-time 2 --insecure https://${APISERVER_VIP}:${APISERVER_DEST_PORT}/ -o /dev/null || errorExit "Error GET https://${APISERVER_VIP}:${APISERVER_DEST_PORT}/"
fi

Параметр APISERVER_DEST_PORT задает порт балансировщиков haproxy, параметр APISERVER_VIP виртуальный адрес, через который будут взаимодействовать master (control plane) узлы кластера k8s.

Скрипт проверяет работоспособность haproxy на локальной машине. А если в настоящее время виртуальный адрес принадлежит текущему узлу, то и работоспособность haproxy через виртуальный адрес.

Добавьте флаг на выполнение скрипта:

chmod a+x /etc/keepalived/check_apiserver.sh

При работающем балансировщике и хотя бы одному доступному порту 6443 на master-узлах скрипт должен завершаться с кодом 0.

Запуск сервисов

Для запуска сервисов наберите команды:

systemctl enable haproxy --now
systemctl enable keepalived --now

Так как master-узлы k8s еще не подняты haproxy выведет на консоль сообщение

haproxy[nnnn]: backend apiserver has no server available!

Конфигурирование и запуск кластера

Описание базовых butane YML-файлов

На основе базовых butane YML-файлов программой butane создаются ignition-файлы, используемые для создания конечных 'master_NN.ign', 'worker_NN.jgn' ignition-файлов для разворачивания master и worker узлов кластера.

Файл users.yml описания пользователя altcos

yml описания пользователя altcos имеет следующую структуру:

variant: fcos
version: 1.3.0
passwd:
  users:
    - name: altcos
      groups:
        - wheel
        - docker
      password_hash: ...
      ssh_authorized_keys:
        - ssh-rsa ... 
        - ssh-rsa ... 
storage:
  files:
    - path: /etc/sudoers.d/altcos
      contents:
        inline: |
          altcos ALL=NOPASSWD: ALL

В поле password_hash помещается хеш-пароля, сгенерированный командой

mkpasswd --method=yescrypt

В поле ssh_authorized_keys массив открытых ключей пользователей для которых необходим беспарольный доступ к пользователю altcos виртуалной машины.

В файл /etc/sudoers.d/altcos записывается строка, обеспечивающая беспарольный доступ пользователя altcos к sudo.

Файл hosts.yml описания имен и IP-адресов узлов

Файл hosts.yml содержит строки привязки имен и IP-адресов виртуальных машин в файле /etc/hosts:

variant: fcos
version: 1.3.0

storage:
  files:
    - path: /etc/hosts
      append:
        - inline: |
            10.150.0.161 master01
            10.150.0.162 master02
            10.150.0.163 master03
            10.150.0.171 worker01
            10.150.0.172 worker02
            10.150.0.173 worker03
Файл btrfs.yml инициализации btrfs тома
variant: fcos
version: 1.3.0
storage:
  disks:
    - device: /dev/sdb # создадим на диске /dev/sdb партицию /dev/sdb1
      wipe_table: true
      partitions:
        - number: 1
          label: docker
  filesystems:
    - device: /dev/sdb1 # создадим в партиции /dev/sdb1 файловую систему BTRFS
      format: btrfs
      wipe_filesystem: true
      label: docker
      with_mount_unit: false
  directories:
    - path: /var/mnt/docker # создадим каталог монтирования тома
      overwrite: true
  files:
    - path: /etc/fstab # добавим строку монтирования btrfs-тома на каталог /var/mnt/docker
      append:
        - inline: |
            LABEL=docker /var/mnt/docker btrfs defaults 0 2
    # заменим в конфигурации dockerd-демона:
    # тип storage-driver с overlay2 на btrfs
    # изменим каталог размещения данных docker-демона  с /var/lib/docker на /var/mnt/docker/docker/
    - path: /etc/docker/daemon.json
      overwrite: true
      contents:
        inline: |
          {
          "init-path": "/usr/bin/tini",
          "userland-proxy-path": "/usr/bin/docker-proxy",
          "default-runtime": "docker-runc",
          "live-restore": false,
          "log-driver": "journald",
          "runtimes": {
            "docker-runc": {
              "path": "/usr/bin/runc"
            }
          },
          "default-ulimits": {
            "nofile": {
            "Name": "nofile",
            "Hard": 64000,
            "Soft": 64000
            }
          },
          "data-root": "/var/mnt/docker/docker/",
          "storage-driver": "btrfs"
          }
    # заменим в конфигурации CRI-O, podman:
    # тип driver с overlay2 на btrfs
    # изменим каталог размещения данных docker-демона  с /var/lib/containers/storage на /var/mnt/docker/containers/storage
    - path: /etc/containers/storage.conf
      overwrite: true
      contents:
        inline: |
          [storage]
          driver = "btrfs"
          runroot = "/var/run/containers/storage"
          graphroot = "/var/mnt/docker/containers/storage"

          [storage.options]
          additionalimagestores = [
          ]
          [storage.options.overlay]
          mountopt = "nodev,metacopy=on"
Файл initk8s.yml описания сервиса инициализации кластера k8s

Файл описывает сервис initk8s инициализации кластера и может быть включен только в YML-файл 1-го master-узла кластера master01.

variant: fcos
version: 1.3.0
systemd:
  units:
    - name: initk8s.service
      enabled: false
      contents: |
        [Unit]
        Description=Start up kubernetes in master mode
        After=crio.service kube-proxy.service kubelet.service systemd-networkd.service systemd-resolved.service
        [Service]
        Type=oneshot
        RemainAfterExit=yes
        Environment="KUBECONFIG=/etc/kubernetes/admin.conf"
        ExecStartPre=loadDockerArchiveImages.sh
        ExecStart=kubeadm init --cri-socket=/var/run/crio/crio.sock \
                          --pod-network-cidr=10.244.0.0/16 \
                          --ignore-preflight-errors=SystemVerification \
                          --kubernetes-version=v1.20.12 \
                          --control-plane-endpoint 10.150.0.160:8443 \
                          --upload-certs
        [Install]
        WantedBy=multi-user.target

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

  • оставить вызов скрипта loadDockerArchiveImages.sh разворачивания архивов docker-образов, хранящихся в ostree-образе;
  • указать версию 'kubernetes' в параметре kubernetes-version (версию можно узнать вызвав команду rpm -qa --dbpath /lib/rpm/ | grep kubernetes или kubectl version);

Если Вы планируете загрузить docker-образы из Интернет, то ExecStartPre и --kubernetes-version= можно удалить.

В отличие от варианта разворачивания кластера с одним master-узлом в команду kubeadm init добалены параметры:

  • control-plane-endpoint в котором указан URL основного haproxy-сервера, работающего на виртуальном адресе 10.150.0.160 и предоставляющий доступ на порту 8443.
  • upload-certs, обеспечивающий загрузку сгенерированных сертификатов и раздачу их другим master-узлам.
Файл k8senv.yml создание profile инициализации kubernetes-среды
variant: fcos
version: 1.3.0
storage:
  files:
    - path: /etc/profile.d/kube.sh
      mode: 0755
      contents:
        inline: |
          # Set  kube environment
          if [ `id -u ` = 0 ]
          then
            export KUBECONFIG=/etc/kubernetes/admin.conf
          else
            if [ -f /etc/kubernetes/admin.conf ]
            then
              if [ ! -d ~/.kube ]
              then
                mkdir -p ~/.kube
                sudo cp -i /etc/kubernetes/admin.conf ~/.kube/config
                sudo chown $(id -u):$(id -g) ~/.kube/config
                kubectl completion bash >> ~/.bashrc
              fi
            fi
          fi

Файл обеспечивает создание профайла /etc/profile.d/kube.sh. Для привелигированного пользователя (sudo -i bash) в среду добавляется переменная KUBECONFIG. Для непривилигиванного формирование каталога .kube.

Файл mastersUsers.yml описания открытых ключей мастер-узлов кластера

Данный файл обеспечивает под пользователем altcos беспарольный доступ с master-узлов на 'worker'-узлы. Структура файла следующая:

variant: fcos
version: 1.3.0
passwd:
  users:
    - name: altcos
      ssh_authorized_keys:
        - ssh-rsa ... altcos@master01 
        - ssh-rsa ... altcos@master02
        - ssh-rsa ... altcos@master03  

В него помещаются открытые ключи пользователей altcos master-узлов.

Конфигурирование и запуск мастер-узлов

Создание butane-YML файлов описания конфигурации master-узлов

YML-файл для первого узла master01:

variant: fcos
version: 1.3.0
ignition:
  config:
    merge:
      - local: users.ign
      - local: hosts.ign
      - local: btrfs.ign
      - local: k8senv.ign  
      - local: initk8s.ign
storage:
  files:
    - path: /etc/hostname
      overwrite: true
      contents:
        inline:
          master01
    - path: /etc/systemd/network/20-wired.network
      overwrite: true
      contents:
        inline: |
          [Match]
          Name=eth0
          [Network]
          DHCP=no
          Address=10.150.0.161/24
          Gateway=10.150.0.1
          DNS=10.150.0.1

В элементе ignition.config.merge описываются ignition-файлы сгенерированные командой butane из вышеперечисленных YML_файлов.

В файле /etc/hostname указывается имя узла master01. В файле /etc/systemd/network/20-wired.network описываются адрес Address узла, шлюз Gateway и DNS для узла.

Остальные YML-файлы конфигурации master-узлов master_02.yml, master_03.yml описываются схожим образом за исключением:

  • файл описания сервиса local: initk8s.ign можно не подключать, так как инициализация кластера производится с узла master01;
  • в файле /etc/hostname указываются имена узлов master01 и master02 соответственно;
  • в файле '/etc/systemd/network/20-wired.network в поле Address указываются IP-адреса master-узлов 10.150.0.162 и 10.150.0.163 соответственно.

Скрипт createNode.sh запуска master и worker узлов

Исходный код скрипта:

#!/bin/sh
case $1 in 
  master | worker) type=$1;;
  *) echo "Тип нод может быть только master или worker"; exit 1;
esac
N=`printf "%02d" $2 2>/dev/null` 
if [ $N = '00' ]
then
  echo "Номер ноды должен быть числовым и больше нуля"; exit 1;
fi
if [ ! -f $3 ]
then
  echo "Образ $3 не существует";exit 1;
fi
IMAGE=$3
prefix=${type}_${N}
diskSize=30G
sdaDisk=${prefix}_sda.qcow2
sdbDisk=${prefix}_sdb.qcow2
ignFile=$PWD/${prefix}.ign
ylmfiles="users k8senv btrfs hosts initmaster $prefix mastersUsers"
for ymlfile in $ylmfiles 
do
  if ! butane -d . -p $ymlfile.yml > $ymlfile.ign
  then
    exit 1;
  fi
done
cp $IMAGE $sdaDisk
qemu-img create -f qcow2 $sdbDisk $diskSize
virt-install --name $prefix \
  --vcpus 2 \
  --ram 2048 \
  --os-variant altlinux1.0 \
  --import \
  --disk $sdaDisk \
  --disk $sdbDisk \
  --vnc \
  --qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=$ignFile"

Скрипт принимает три параметра:

  1. Тип узла - master или worker.
  2. Номер узла (1, 2, 3, ...).
  3. Тропа до файла 'qcow2'-образа.

Скрипт на основе типа виртуальной машины и ее номера формирует prefix ${type}_${N} который используется для определения:

  • имен основных yml и ignitio файлов;
  • имен основного (/dev/sda) и дополнительного btrfs (/dev/sdb) имен qcow2-файлов дисков;
  • имен виртуальных машин.

Далее производятся следующие действия:

  • Указанный 3-м параметром файл-образ копируется в файл загрузочного qcow2-образа.
  • Команда qemu-img create ... создает образ btrfs-диска указанного размера.
  • Команда virt-install --name $prefix ... создает виртуальную машину, передавая ignition файл конфигурации ${prefix}.ign.

Запуск виртуальных машин master-узлов

В HOST-системах NODE3 10.140.0.3, NODE4 10.140.0.4, NODE5 10.140.0.5 запустите виртуальные машины командами:

  • NODE3:
createNode.sh master 1 images/k8s.20211125.0.0.qcow2
  • NODE4:
createNode.sh master 2 images/k8s.20211125.0.0.qcow2
  • NODE5:
createNode.sh master 3 images/k8s.20211125.0.0.qcow2

Генерация ssh-ключей и их использование

Дождитесь запуска виртуальных машин (несколько минут) и зайдите под пользователем altcos на них:

  • NODE3:
ssh altcos@10.150.0.161
  • NODE4:
ssh altcos@10.150.0.162
  • NODE5:
ssh altcos@10.150.0.163

Сгенерируйте ssh-ключи командой:

ssh-keygen

Передайте открытые ключи на остальные master-узлы:

  • master01 (10.150.0.161):
ssh-copy-id master02
ssh-copy-id master03
  • master02 (10.150.0.162):
ssh-copy-id master01
ssh-copy-id master03
  • master03 (10.150.0.163):
ssh-copy-id master01
ssh-copy-id master02

Добавьте открытый ключи из файла ~altcos/.ssh/id_rsa.pub в файл mastersUsers.yml описания открытых ключей мастер-узлов кластера.

Иниализация кластера на первом узле master01

На узле master01 (10.150.0.161) запустите сервис initk8s:

sudo systemctl start initk8s

Инициализация кластера производится несколько минут.

Подключение остальных master-узлов

На узле master01 (10.150.0.161) запустите сервис initk8s:

journalctl -u initk8s

Найдите в логах строки:

kubeadm join 10.150.0.160:8443 --token ... \
  --discovery-token-ca-cert-hash sha256:... \
  --control-plane --certificate-key ...

добавьте к ним параметр --cri-socket=/var/run/crio/crio.sock и запишите полученную команду в переменную

joinmaster='kubeadm join ...'

Загрузите необходимые docker-образы на узлах master02, master03:

ssh master02 sudo loadDockerArchiveImages.sh
ssh master03 sudo loadDockerArchiveImages.sh

Подключите дополнительные master-узлы командами:

ssh master02 sudo $joinmaster
ssh master03 sudo $joinmaster

Подключение master'ов происходит за пару минут.

После подключения проверьте список узлов кластера:

 kubectl get nodes
NAME       STATUS   ROLES                  AGE    VERSION
master01   Ready    control-plane,master   3h9m   v1.20.8
master02   Ready    control-plane,master   179m   v1.20.8
master03   Ready    control-plane,master   178m   v1.20.8

Конфигурирование и запуск рабочих (worker) узлов

Создание butane-YML файлов описания конфигурации worker-узлов

YML-файл для первого узла worker01:

variant: fcos
version: 1.3.0

ignition:
  config:
    merge:
      - local: users.ign
      - local: btrfs.ign
      - local: hosts.ign
      - local: mastersUsers.ign  
storage:
  files:
    - path: /etc/hostname
      overwrite: true
      contents:
        inline:
          worker01
    - path: /etc/systemd/network/20-wired.network
      overwrite: true
      contents:
        inline: |
          [Match]
          Name=eth0
          [Network]
          DHCP=no
          Address=10.150.0.171/24
          Gateway=10.150.0.1
          DNS=10.150.0.1

Отличие он конфигурации master-файлов: - отсутствует подключение ignition-файлов k8senv.ign, initk8s.ign; - подключается файл mastersUsers.ign описания открытых ключей мастер-узлов кластера.

Аналогичным образом конфигурируются файлы для worker02, worker03.

Запуск виртуальных машин worker-узлов

В HOST-системах NODE3 10.140.0.3, NODE4 10.140.0.4, NODE5 10.140.0.5 запустите виртуальные worker-машины командами:

  • NODE3:
createNode.sh worker 1 images/k8s.20211125.0.0.qcow2
  • NODE4:
createNode.sh worker 2 images/k8s.20211125.0.0.qcow2
  • NODE5:
createNode.sh worker 3 images/k8s.20211125.0.0.qcow2

Подключение worker-узлов

На узле master01 (10.150.0.161) запустите сервис initk8s:

journalctl -u initk8s

Найдите в логах строки:

kubeadm join 10.150.0.160:8443 --token ... \
    --discovery-token-ca-cert-hash sha256:...

добавьте к ним параметр --cri-socket=/var/run/crio/crio.sock и запишите полученную команду в переменную

joinworker='kubeadm join ...'

Загрузите необходимые docker-образы на узлах master02, master03:

ssh worker01 sudo loadDockerArchiveImages.sh
ssh worker02 sudo loadDockerArchiveImages.sh
ssh worker03 sudo loadDockerArchiveImages.sh

Подключите дополнительные worker-узлы командами:

ssh worker01 sudo $joinworker
ssh worker02 sudo $joinworker
ssh worker03 sudo $joinworker

Подключение worker'ов происходит менее минуты.

После подключения проверьте список узлов кластера:

 kubectl get nodes
NAME       STATUS   ROLES                  AGE    VERSION
master01   Ready    control-plane,master   3h9m   v1.20.8
master02   Ready    control-plane,master   179m   v1.20.8
master03   Ready    control-plane,master   178m   v1.20.8
worker01   Ready    <none>                 180m   v1.20.8
worker02   Ready    <none>                 185m   v1.20.8
worker03   Ready    <none>                 189m   v1.20.8

Ссылки