Итак, если вы интересуетесь темой одноплатных ПК вроде RaspberryPi, OrangePi, NanoPI и прочих -- обязательно наступает момент, когда дома их скапливается некоторое количество.
Парочка из них даже в деле -- на одном вы играете в старые игры от Денди, а другой, например, управляет вашим типа "умным домом". Ну ещё один, допустим 3D-принтером. На этом мысль обрывается...
И в голову приходит странная идея, о том, что неплохо бы их использовать хоть с каким-то профитом. Пусть даже не явным.
В моём случае все началось с сети, точнее с подсети из ОПК, а закончилось относительно полноценным решением на основе Kubernetes (K8s).
Зачем?
Первые кластеры (в докубернетовый период) были построены для:
- Майнинга монеты Verium (когда она ещё существовала)
- Машинного доения систем активной рекламы
- Не поверите, для поиска инопланетян (нет, все не настолько плохо, просто был такой проект SETI@home)
А вот это процесс сборки кластера с питанием от ATX БП и управлением этим самым питанием.
А вот уже вариант с кучкой OrangePi One Plus, SSD и платой управления...
Больше информации о процессе можно почитать в моем старом бложике.
Анатомия
Железо
Для простейшего кластера (до K8s мы ещё доберемся и там картина другая):
- Набор Pi-подобных компов, желательно однородный. Памяти не меньше 1ГБ (если не используете Kubernetes -- там адекватная работа будет от 2ГБ и выше)
- Сетевой коммутатор. 100МБ маловато, однако, если не подключаете хранилище по сети - может и хватит.
- Куча патчкордов Ethernet, лучше плоских и мягких (чтобы ваши платы не выворачивало наизнанку).
- Отдельный одноплатник с двумя сетевыми интерфейсами. Он будет изображать шлюз/jumphost в отдельную сеть. Не стоит перегружать роутер выделением адресов. Он же будет управлять питанием остальных узлов.
- Блок питания. Хороший, дорогой, мощный
- Что-то, что позволит управлять питанием. В моем случае -- это плата на основе Arduino с транзисторными ключами, которые могут открываться и закрываться. Всё можно упростить, даже обойтись без неё, но вы реально устанете отключать какой-то один узел в процессе отладки. Вообще, про такие платы я обязательно расскажу отдельно.
- Провода питания, разъемы, кабельные стяжки, винтики-болтики, стойки.
- Конечно же, куча micro SD карт. ОПК надо с чего-то запускать. Спойлер -- это одно из самых слабых мест.
Софт
В качестве основной ОС я использовал Armbian. Он стабилен, он поддерживает кучу одноплатных компьютеров. В его ядре есть все необходимые модули и настройки, а так же поддержка всякой периферии, типа i2c почти "из коробки", чтобы коммутировать ардуины и прочую ересь.
Для создания отдельной подсети -- уже упоминавшийся одноплатник с двумя сетевыми интерфейсами. На нем DHCP сервер и Masquerading через iptables.
SSH-сервер (он доступен сразу в Armbian).
Это необходимый минимум, чтобы соединить это всё в сеть и получить доступ.
Дальше YMMV (your mileage may vary). Можно обойтись Docker swarm + Portainer и гонять на этой конструкции контейнеры Docker.
А можно вообще особо не заморачиваться и запускать какие-то процессы вручную, заходя на россыпь ваших одноплатных ПК.
Однако... В какой-то момент начинаем понимать, что вся конструкция конечно работает, пингуется, даже уже нашла парочку инопланетян в состоянии офигевания от происходящего или намайнила пару монеток Verium (его уже не существует, даже не пытайтесь).
Но за это время выяснилось:
- Ваши microSD дохнут, ибо на них нагрузка резко возросла.
- Ваши одноплатники любят подвиснуть из-за проблем с питанием и их надо постоянно перегружать путем передергивания питания.
- Вы не очень понимаете, что-где работает, как и почему нет, если нет.
Поэтому пора бы уже подумать о том, как россыпь этого хлама превратить в управляемый, самовосстанавливающийся, относительно современный кластер на Kubernetes.
Вперёд в K8s
Тут стоит сказать, что "мотивация" построить полноценный Kubernetes кластер из ОПК имела несколько составляющих:
- Текущий проект на основной работе был связан c K8s, а я был в нём новичком и было немного неудобно спрашивать "а это что, а это как". Поэтому надо было пройти этот путь самому.
- Система "машинного доения САР", упомянутая раньше прям просилась быть масштабируемой без серьезных дополнительных усилий.
- Были планы на дальнейшее использование и развитие идеи.
Увы, нет привычки делать фотографии трудов в больших количествах, так что фотки постараюсь найти в архивах, если они вообще будут. Но постараюсь.
И ещё. Это не учебник и не пособие по "куберостроительству". Скорее заметки о том, как и что было реализовано. Если вы реально заинтересовались и понимаете, зачем вам это -- ваши решения могут быть более разумными и не настолько мучительными. YMMV.
Железо
Вот то, что нам понадобится.
Отдельный ОПК, который:
- Работает в качестве gateway к домашней сети. Значит у него должно быть два сетевых интерфейса. Один из них -- точно гигабитный для обслуживания внутренней сети кластера.
- Обеспечивает подключение платы управления питанием по i2c или по UART.
- Имеет возможность подключать накопители, отличные от microSD для организации хранилища. Самый простой вариант -- USB-NVME коробочка с интерфейсом USB 3.0. Жизненно необходим trim и нужно забыть о механических накопителях, ибо он просто задохнётся от количества обращений.
- Количество памяти не меньше 1ГБ, лучше больше.
- Количество ядер -- не менее 4х, лучше больше.
На эту роль почти идеально подходит такой персонаж, как Nano Pi Neo 4
Тут тебе и гигабитный ethernet, и мощный процессор и разные GPIO. Да и порт USB 3.0 тоже в наличии. А в порт 2.0 можно ткнуть USB-Ethernet для связи с внешним миром.
Несколько ОПК, которые будут изображать узлы кластера:
- Памяти не менее 1гб
- Внятный по мощности процессор
- Гигабитный Ethernet строго
Тут может подойти и Orange Pi PC2 (Allwinner H5), и Orange Pi One Plus (Allwinner H6).
Гигабитный свитч:
- Компактный размер
- Не менее 8 портов
Ну тут даже фотографию публиковать не надо -- этого барахла пока еще полно в магазинах и на маркетплейсах, да и на Avito.
Плата управления питанием:
Устройство, на микроконтроллере, управляющее некоторым количеством линий питания.
Будет отдельная заметка про такие платы. Пока что спойлер в виде фото.
Плата соединяется по UART и/или I2C c одноплатником-гейтвеем и умеет включать/выключать физически узлы кластера.
Компонент не то, чтобы обязательный, можно обойтись просто набором тумблеров. Но не хочется бегать к стенду для передергивания питания каждый раз.
Накопитель:
- Работает по USB3
- NVME с переходником -- вполне годный вариант
- Размер -- от 128Гб, лучше больше
Блок питания:
Я пользовался Meanwall 5в 100 ватт. Можно попроще, подойдет 5в 50ватт от светодиодных лент. Нужно запитать все одноплатники, а если повезет -- еще свитч и охлаждение всего этого. Суммируем ватты и получаем нужное.
Если где-то нужно 12в, или 9 для того же свитча -- вполне нормально использовать повышающие преобразователи, которых тоже завались в продаже.
Провода разные:
- Патчкорды
- Питание
Ну тут особо без комментариев. Провода и провода.
Софт/технологии
Ох, тут будет много всего. Пожалуй, перечислю основные компоненты софтовые, о них более подробно ниже.
Порядок произвольный, никакой логической последовательности нет. Считаем, что это список того, чем нужно будет овладеть.
- Linux вообще, в нашем случае Armbian
- LVM -- организация хранения данных
- ISCSI (как сервер, так и клиент) -- раздача блочных устройств по сети
- LXC -- дополнительная прослойка для операционной системы
- MicroK8s -- вариант Kubernetes, проверенный для работы на Pi-подобных устройствах
- IPtables -- файрволл для организации сети
- DNSMasq -- DHCP и DNS сервер
- Ansible -- автоматизация рутинных операций
- Python -- ну тут достаточно условно, очень пригодится при работе с Ansible и еще для всяких шаманств при работе с платой управления питанием
- Snap -- технология установки пакетов, microk8s работает через snap store и да, придется с этим мириться
- NFS сервер -- опционально, но он нам пригодится для persistent volumes в Kubernetes
- Shell -- Да, желательно уметь писать скрипты на sh/bash
Общая картина
И вот примерные схемы того, что находится на Gateway и на типичном узле кластера.
Давайте начнем с Gateway.
Очевидно, что он организует отдельную подсеть, например 10.0.0.x для bare-metal, 10.0.0.х+50 для контейнеров.
Очевидно, нужен DNSMasq с назначением статических адресов по MAC:
10.0.0.x -- платы
10.0.0.х+50 -- LXC-контейнеры на платах
Так же нужен iptables, чтобы траффик с внутренней сети уходил во внешний мир.
Зачем LVM ? Ну во-первых это удобно. Делаем два раздела. Первый для lxc rootfs, второй для данных, которые будет раздавать например NFS сервер. Они будут использоваться сервисами кластера.
Сложно ? Вовсе нет. В любой момент можно расширить диск или заменить. И все это без прерывания работы системы.
Больше про LVM узнать можно здесь.
Ссылки ведут на англоязычные туториалы. Желающие вкатиться в IT, зумеры, прочие неучи прокачивают для начала английский язык.
И тут это страшное слово iscsi. Зачем? Почему?
ISCSI позволяет передать блочное устройство по сети. То есть к вашему узлу кластера фактически можно прицепить диск произвольного размера. А это значит -- никакого износа драгоценных (на самом деле не очень) microSD карт. Скорость будет точно выше даже очень недешёвой карточки памяти -- ведь под капотом гигабитная сеть и NVME диск (хоть и работающий по USB3). Про возможности резервного копирования я уже даже не упоминаю.
С остальным проще. NFS сервер нам пригодится при работе с кластером, ansible для автоматизации установок, ну а скрипты для платы питания вообще опциональны.
Перейдем к узлу кластера.
На обычный Armbian ставим ISCSI Initiator -- очевидно, чтобы подключить диск по сети с Gateway.
Далее -- ставим LXC контейнер, rootfs которого размещаем либо в LVM на этом сетевом диске, либо сразу напрямую. Зачем LXC??
- Если у вас разные устройства или версии Armbian для них -- вы получите общую одинаковую среду, например Ubuntu Focal, а значит на них единообразно можно будет поставить все остальное с помощью ansible
- Контейнер имеет минимальный оверхед (около 50мб ОЗУ) и его можно пересоздать сколько угодно раз -- не затрагивая основную систему
- Контейнер привилегированный, то есть в нем "можно всё", даже запускать докер внутри и snapы
- Контейнеру можно назначить валидный осмысленный MAC и он автоматом получит нужный IP адрес от Gateway
- В случае проблем его (контейнер) просто и быстро перезапустить
- Его файловая система подключена, считай по сети (на самом деле подключено блочное устройство). Нет износа microSD
Мне лично ОК пожертвовать тактами процессора и 50 Мб памяти и как результат получить гораздо более управляемую систему, а карточку памяти извлекать только по очень серьезной необходимости. И нет, не тормозит.
Строим Gateway
Тут пойдем галопом в формате чек-листа, а особенности будем уже расписывать подробнее.
Качаем и накатываем на microSD подходящий образ Armbian c armbian.com. Выбирать какое-нибудь Ubuntu без GUI. Вариант IoT подходит, но придется доставлять массу пакетов.
Угорающие по хардкору могут сами собрать образ системы, на сайте есть документация и результаты меня лично вполне порадовали.
Грузимся, настраиваем имя пользователя, ключи доступа по SSH (если практикуете), обязательно время по NTP. Оно уже и так будет настроено, но тем не менее лучше перепроверить, что все работает.
Очень важно, если используется NetPlan -- переключиться на NetworkManager. Пример тут. NM уже умеет работать с dnsmasq и назначать адреса.
Напомню, что по схеме:
- Диапазон 10.0.0.x мы отдаем bare metal узлам
- Диапазон 10.0.0.x+50 мы отдаем контейнерам на этих узлах.
Настройте masquerading. Хороший пример тут. Сделайте так, чтобы изменения переживали перезагрузку. Это можно сделать, написав собственный systemd unit или воспользоваться /etc/rc.local (хотя так уже никто не танцует).
Как проверить ?
Возьмите ноутбук или другой одноплатник. Запишите его MAC адрес. В настройках dnsmasq укажите, чтобы этому MAC выделялся адрес, ну пусть 10.0.0.201.
Сохраните настройки. Подключите ноут или одноплатник к вашей внутренней сети кластера. Убедитесь, что выделился именно 10.0.0.201, и с него доступен выход в интернет и в вашу основную сеть.
Дальше -- подключаем диск NVME через USB3 переходник.
Вот тут важный момент. Нужно убедиться, что trim будет работать. Очень хороший пошаговый туториал есть здесь. Конкретно секция 2.3, где речь идет о внешних дисках.
делаем из него LVM, и нарезаем волюмы.
- Один для хранения rootfs контейнеров. Считаем размер так: количество узлов кластера * размер rootfs (лучше 6 или 8 гб) + пара гигабайт до круглого числа
- Второй для хранения данных NFS/кластера. Тут важно отдать не "впритык", чтобы осталось еще немного свободного места - 8-12Гб
Пора устанавливать iscsi target. Для начала ознакомьтесь с тем, как это вообще работает.
Нам нужно столько целей, сколько у нас планируется узлов.
Для каждого target создадим образ диска:
sudo tgtimg --op new --device-type disk --size=8192 --type=disk --thin-provisioning --file=/data/iscsi/node0
Так, мы создаем диск размером 8Гб для узла 0. /data/iscsi -- это то, куда созданный ранее LVM volume для rootfs контейнеров.
Опция thin-provisisoning нам потребуется, чтобы система могла спокойно делать "trim" на ssd диске.
Вот пример настройки таргета с живой системы:
<target iqn.2022-13.me.znoxx-bare11>
<backing-store /data/iscsi/node0>
params thin_provisioning=1
</backing-store>
incominguser bare11 bare11
</target>
Возможно, нужно добавить опцию emulate_tpu=1, но trim у меня заработал именно в текущей конфигурации.
Как проверить ?
Есть два способа. Windows 7 Pro (не к ночи будет сказано) умеет подключаться к iscsi target. Про Win10 не скажу, наверное тоже умеет. Можно где-то ее взять и попробовать. Либо, честно взять второй одноплатник и попытаться подключиться к выбранной iscsi target по любому из туториалов, которых в интернете очень много.
Это была, возможно, самая трудоемкая часть, но она того стоит.
Из важных запчастей нам осталось только поставить Ansible (это делается из пакетов ОС), чтобы пытаться автоматизировать настройки узлов, ну и настроить минимальный NFS сервер. Просто берем и ставим по первой части этого туториала. Мы, кстати, к нему еще вернемся.
Итак, финальный чеклист:
- Работает DHCP сервер, нужные адреса отдаются нужным клиентам, клиенты видят друг друга.
- Работает Masquerading, клиенты могут попасть в основную сеть и интернет.
- Работает ISCSI target сервер, можно подключиться и увидеть диск.
- NFS работает.
- Ansible установлен.
А вот чудом сохраненный вариант моего кластера в процессе сборки. Даже ЛГБТ RGB подсветка есть.
Можно переходить к узлу кластера.
Cтроим узел кластера
Так как у нас несколько узлов, то нужно максимально унифицировать систему. У нас будет работать LXC, и контейнер должен точно так же получать адреса от DHCP сервера, но в другом диапазоне (10.0.0.x+5).
Поэтому тут тоже нужно перейти на Network Manager. После успешного перехода -- нужно создать bridge:
# nmcli con add type bridge ifname br0
# nmcli con add type bridge-slave ifname eth0 master br0
# reboot
Ясное дело, eth0 нужно заменить на физический интерфейс.
Настройте DHCP так, чтобы адрес был статическим. То есть каждый узел всегда должен получать адрес по своему MAC.
В качестве имени хоста используйте что-то понятное, например bare00, bare01 (это bare metal).
Дальнейшие действия лучше обернуть в Ansible playbook, чтобы не повторять их несколько раз для всех хостов.
Необходимые модули ядра для microk8s
В автозагрузку нужно добавить следующие модули ядра для корректной работы:
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
ip_tables
ip6_tables
netlink_diag
nf_nat
overlay
aufs
br_netfilter
Еще, убедитесь, что загружен модуль fuse. Если его нет в списке загруженных -- подключите его.
Подключаем iscsi
Действуем строго по мануалу от iscsi.
Для нас критичны настройки автостарта, чтобы при ребуте хоста диск подключался автоматически.
Чтобы проверить подключение, даем команду после перезагрузки:
iscsiadm -m session -P 3 | grep "Attached scsi disk" | awk '{ print $4 }'
Если в ответ получено что-то вроде "/dev/sda", то все получилось.
Этот диск нужно отформатировать в ext4, ну и подключить в выбранную точку монтирования, например /var/containers
Изменения сохраняем в fstab, проверяем после ребута.
Попробуем дать команду fstrim -Av, и если мы видим успешный трим для подключенного диска, то это ещё больший успех :)
Все готово для установки lxc и создания контейнера.
Ставим lxc и создаем контейнер
LXC ставим из пакетов системы. В некоторых случаях можно подключить ppa-репозитарий, если есть желания использовать "суперпоследнюю" версию.
Но нам потребуется сделать дополнительные настройки в конфигурации LXC.
Поскольку мы хотим, чтобы данные контейнеров попадали на подключенный iscsi диск, то идём в /etc/lxc/lxc.conf и выставляем значение:
lxc.lxcpath=/var/containers
Не забудьте перезагрузить сервис LXC.
Теперь созданные контейнеры вместе с файловой системой будут попадать на подключенный iscsi диск.
Создайте privileged контейнер (просто используйте sudo). В качестве шаблона используйте ubuntu, в качестве версии -- ну не меньше focal. Лучше более позднюю, доступную на текущий момент LTS-версию.
Перед запуском контейнера нужно будет подправить его конфигурацию.
Вот, что должно быть в настройках контейнера:
#Указываем имя контейнера
lxc.uts.name = node00
# Нужно включить nesting, чтобы работал docker
lxc.include = /usr/share/lxc/config/nesting.conf
# необходимые настройки безопасности -- разрешаем почти всё
lxc.apparmor.profile = unconfined
lxc.cgroup.devices.allow = a
lxc.cgroup2.devices.allow = a
lxc.mount.auto=proc:rw sys:rw cgroup-full:rw
lxc.cap.drop=
lxc.net.0.type = veth
lxc.net.0.link = br0 #мы должны получать адреса по DHCP от основного сервера
# нужно для работы snapd
lxc.mount.entry = /dev/kmsg dev/kmsg none bind,create=file,optional
lxc.mount.entry = /dev/fuse dev/fuse none bind,create=file,optional
lxc.mount.entry = /sys/kernel/security sys/kernel/security none bind,optional 0 0
lxc.mount.auto = cgroup:rw
# уникальный mac контейнера. Его можно сгенерить, важно, чтобы он не менялся от старта к старту. нужен для выделения статического ip
lxc.net.0.hwaddr = мак_адрес_вашего_контейнера
Контейнер можно запускать.
Если всё прошло успешно, то:
- Контейнер получит адрес желатемый адрес по DHCP
- Контейнер будет иметь доступ во вненшнюю сеть
Если что-то пошло не так, можно посмотреть логи ошибок. Вполне вероятно, нужно будет перегенерить MAC адрес. Но опять-таки YMMV.
Далее в контейнере -- нужно установить имя хоста, такое, как проставлено в конфигурации (через hostnamectl), поставить ssh-сервер, разрешить логин для root (другие пользователи нам там не понадобятся). Да, это не совсем secure, потом после завершения настройки это всё можно будет донастроить.
Повторите настройку для остальных узлов.
В конечном итоге хосты bare-metal будут иметь имена bare00, bare01, bare02...
Контейнеры node00, node01, node02...
Всё пингуется, всё видит друг друга по крайней мере по IP.
Дальнейшие действия будут выполняться внутри не bare-metal хостов, а контейнеров.
Ставим microk8s
Microk8s -- это реализация Kubernetes от Canonical (Ubuntu)
- Требует не так много ресурсов по сравнению с каноничной реализацией
- Работает везде, где работает Ubuntu
- Проста в установке
- Стабильна и полноценна
Её мы и будем ставить.
Но для начала -- в каждом контейнере обновите /etc/hosts файл.
Дополните его следующими записями:
10.0.0.50 node00
10.0.0.51 node01
10.0.0.52 node02
10.0.0.53 node03
Это нужно, чтобы контейнеры "видели" друг друга. Да, можно конечно заморочиться с донастройкой DNS, но этот вариант вполне работает, тем более, если узлов у нас немного.
Опционально, можно сделать rsyslog менее разговорчивым, чтобы на диск писалось поменьше данных:
Для этого в файл /etc/rsyslog.d/01-blocklist.conf внесите примерно следующее:
if $msg contains "run-containerd-runc-k8s.io" and $msg contains ".mount: Deactivated successfully." then {
stop
}
Дальше всё просто:
Ставим и конфигурируем snapd -- microk8s ставится из Snap Store.
sudo apt-get install snapd squashfuse
Потребуется еще донастроить сервис snapd
C помощью механизма кастомизаций сервисов systemctl добавьте вот такой override для Snapd service:
[Service]
ExecStartPre=/bin/sh -c '/usr/sbin/apparmor_parser -r /var/lib/snapd/apparmor/profiles/*'
Перегрузите сервис
systemctl daemon-reload
Ну и наконец
snap install microk8s --classic
В принципе, этого достаточно. Дальше можно обратиться к официальной документации на microk8s и выполнить какие-то формальные проверки.
Однако, мне лично пришлось сделать еще пару фиксов -- сделать лог менее "разговорчивым" и ещё пару мелочей.
Оставлю тут кусочек ansible task, который это выполняет. Немножко поломано форматирование yaml, но в целом понятно.
---
- name: Decrease verbosity of containerd -- remove logging
lineinfile:
path: /var/snap/microk8s/current/args/containerd
state: absent
regexp: '^--log-level'
become: true
- name: Decrease verbosity of containerd -- set fatal level
lineinfile:
path: /var/snap/microk8s/current/args/containerd
line: '--log-level=fatal'
insertafter: EOF
become: true
- name: Fix kube-apiserver bind -- clean
lineinfile:
path: /var/snap/microk8s/current/args/kube-apiserver
state: absent
regexp: '^--bind-address'
become: true
- name: Fix kube-apiserver bind --apply
lineinfile:
path: /var/snap/microk8s/current/args/kube-apiserver
line: '--bind-address=0.0.0.0'
insertafter: EOF
become: true
- name: Stop microk8s
shell: "microk8s stop"
become: true
- name: Start microk8s
shell: "microk8s start"
become: true
Объявляем, кто тут главный
На данный момент у нас установлен microk8s на нескольких узлах. В дефолтной конфигурации
Для определенности пусть они называются так:
- node00
- node01
- node02
- node03
Это еще не кластер. Это просто набор хостов с установленным microk8s snap.
Пора придать ему форму.
Для начала нужно переключить dns сервис kubernetes на наш локальный DNS, работающий через dnsmasq на узле gateway.
В контейнере node00:
microk8s disable dns
Ждем, пока отключится сервис dns
Дальше
microk8s enable dns:10.100.100.1 (тут ставим адрес нашего DNS)
Кстати, тут можно даже поставить адрес вашего роутера, чтобы видеть домашнюю сеть. Дело в том, что по-умолчанию активно используется DNS 8.8.8.8. Мой провайдер блокирует любые другие DNS, кроме своего. Так что этот шаг вполне себе нужный. Я ставлю адрес гейтвея, ибо он знает и про интернет, и про хосты домашней сети и про хосты внутренней сети кластера.
Следующий важный момент.
Сохраните ключ от кластера. Он понадобится и для kubectl, и для helm и прочих утилит.
Для этого на узле node00 (это важно) выполните команду и сохраните вывод
microk8s config > kubekey
Ок, время собирать кластер.
Узел node00 мы объявляем главным!
На нем выполняем:
microk8s add-node|grep -E "^microk8s\s.*--worker"
Теперь на узле node01 выполняем ту команду, которая у нас появилась на экране!
Опять даем команду add-node, а потом переходим на node02 и добавляем узел. И так для всех узлов.
Вот так это можно обернуть в скрипт:
nodes='01 02 03'
for i in $nodes
do
command=$(ssh root@node00 microk8s add-node|grep -E "^microk8s\s.*--worker")
ssh root@node$i $command
done
В принципе все готово. Идем на гейтвей узел и ставим туда утилиты:
- helm
- kubectl
Если вы дочитали до этого места, то вполне в силах их найти.
Подкладываем ключ от кластера в файл ~/.kube/config, чтобы утилиты работали с нашим кластером.
Момент истины:
kubectl get nodes -- выполняем на gateway.
Вы должны увидеть сообщение о том, что в вашем кластере нужное количество узлов и они готовы к работе.
Оригинал руководства, если что, есть здесь.
Настраиваем возможность Persistent Volumes через NFS
Тут подробностей особо и не нужно.
Если вы настроили NFS, как описано ранее, то воспользуйтесь вот этим туториалом.
Простенький механизм PV/PVC позволит сэкономить большое количество времени в будущем.
Ставим утилиту k9s
Чтобы не возиться с командной строкой, можно воспользоваться как-бы интерфейсом к kubernetes.
Если справляетесь с редактором vi/vim -- точно справитесь и с этим.
Делаем первый deploy
Да, можно делать первый деплой.
На узле gateway, куда мы поставили kubectl:
kubectl create deployment nginx --image=nginx
Через некоторое время в вашем кластере начнет работать nginx. За прогрессом можно наблюдать через k9s.
В случае проблем -- внимательно читаем сообщения об ошибках и исправляем их.
Примеров много, точно справитесь.
Кстати, лучше взять за практику следующее:
- На узле master (node00) работают только служебные сервисы
- Никакая полезная нагрузка на нем не выполняется
- Вся нагрузка должна работать на узлах slave
Для облегчения -- лучше поставить метки на узлы:
kubectl label nodes node00 kubernetes.io/role=master
kubectl label nodes node01 kubernetes.io/role=slave
kubectl label nodes node02 kubernetes.io/role=slave
kubectl label nodes node03 kubernetes.io/role=slave
Lessons Leared
Ну что сказать. Работа проведена, кластер работает. Теперь можно погрузиться в технологию и радостно прокачивать скиллы.
В моем экземпляре я заменил узлы кластера на немножко раздербаненные приставки Vontar X3 (там 4 Гб памяти и быстрый процессор и они умеют в Armbian, хоть и не официально). Об этом обязательно расскажу.
Вот он на фото, издеваюсь над ним:
"Нулевой" узел я тоже заменил на довольно дешёвую плату Banana Pi M3. С 2ГБ ОЗУ (это ее единственное достоинство).
Почему не приставка ? Тут все просто. Нулевой узел выполняет административную работу. Если зависание рабочего узла можно пережить и задача переедет на другой, то лучше снизить риски.
Стоила ли вся возня со сборкой и настройкой того ? Думаю да:
- Настоящий Kubernetes, который потребляет суммарно меньшей электрической лампочки накаливания
- Возможность учиться
- Реальное применение железок
- Даже какой-то прямой финансовый выхлоп, если говорить о проектах
И вообще.
Спасибо, что дочитали и, надеюсь, было интересно.