2024-11-17 01:08:44 +03:00
# Kubernetes на Orange Pi 5 Plus под управлением Ubuntu 20.04 (на других Orange Pi, Raspberry Pi и других SBC тоже должно работать)
## Подготовка
2024-12-17 21:53:54 +03:00
### Установим DBus и Avahi (не обязательно)
2024-11-17 01:08:44 +03:00
2024-11-20 18:10:37 +03:00
DBus — система межпроцессного взаимодействия, которая позволяет различным приложениям и службам в системе общаться
друг с другом. DBus часто используется для управления службами, взаимодействия с системными демонами и упрощения
интеграции приложений.
2024-11-17 01:08:44 +03:00
2024-11-27 00:53:45 +03:00
Avahi — это демон и утилиты для работы с mDNS/DNS-SD (Bonjour) и реализация протокола Zeroconf. Avahi тесно
интегрирован с D-Bus и используется для обнаружения устройств и сервисов в локальной сети и предоставляет
автоматическое обнаружение устройств и сервисов в локальной сети. Например, Avahi используется для обнаружения сетевых
принтеров, файловых серверов и других ресурсов без необходимости ручной настройки. Нам avahi понадобится для
обнаружения хостов кластера в локальной сети.
2024-11-17 01:08:44 +03:00
```shell
sudo apt update
2024-11-27 00:53:45 +03:00
sudo apt install dbus avahi-daemon avahi-utils
2024-11-17 01:08:44 +03:00
```
Запускаем эти сервисы:
2024-11-17 01:10:33 +03:00
```bash
2024-11-17 01:08:44 +03:00
sudo systemctl start dbus
sudo systemctl start avahi-daemon
```
А также включаем автозапуск при загрузке:
```shell
sudo systemctl enable dbus
sudo systemctl enable avahi-daemon
```
#### Возможные проблемы с DBus
При проверке статуса dbus `sudo systemctl status dbus` , случается, выскакивают предупреждения, типа:
```text
Xxx xx xx:xx:xx _xxx-hostname-xxx_ dbus-daemon[909]: Unknown username "whoopsie" in message bus configuration file
```
Это связано с тем, что в конфигурационном файле DBus указаны несуществующий пользователь _whoopsie_ . Это системный
пользователь, используемый сервисом Whoopsie, отвечающий за отправку отчётов о б ошибках на серверы разработчиков
(Canonical) в системах Ubuntu. Если whoopsie или е г о конфигурация установлены, но пользователь отсутствует, возникают такие предупреждения.
Я не возражаю против отправки отчётов о б ошибках, тем более, что сервис whoopsie у меня не запущен. :) Так что просто
добавлю пользователя _whoopsie_ в систему:
```shell
sudo adduser --system --no-create-home --disabled-login whoopsie
```
Н о если внутренний параноик вам шепчет, что это не безопасно, то нужно найти в каких конфигурационных файлах DBus встречается _whoopsie_ `grep -r "whoopsie" /etc/dbus-1/` и закомментировать или удалить соответствующие строки.
Также, порадовать своего внутреннего параноика, можно отключить отправку отчётов о б ошибках в Ubuntu:
```shell
sudo systemctl stop whoopsie
sudo apt-get remove --purge whoopsie
```
После всех упражнений (добавления пользователя _whoopsie_ или, наоборот истребления е г о , и отключения сервиса
whoopsie) перезагрузим D-Bus:
```shell
sudo systemctl restart dbus
```
Теперь проверкак статуса dbus:
```shell
sudo systemctl status dbus
```
Н е должна выдавать предупреждений:
```text
dbus.service - D-Bus System Message Bus
Loaded: loaded (/lib/systemd/system/dbus.service; static)
Active: active (running) since Sat XXXX-XX-XX XX:XX:XX MSK; 1min ago
TriggeredBy: ● dbus.socket
Docs: man:dbus-daemon(1)
Main PID: 8437 (dbus-daemon)
Tasks: 1 (limit: 18675)
Memory: 616.0K
CPU: 112ms
CGroup: /system.slice/dbus.service
└─8437 @dbus -daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
XXX XX XX:XX:XX _xxx-hostname-xxx_ systemd[1]: Started D-Bus System Message Bus.
```
#### Возможные проблемы с Avahi
При проверке статуса avahi `sudo systemctl status avahi-daemon` , случается, выскакивают предупреждения, типа:
```text
Xxx xx xx:xx:xx _xxx-hostname-xxx_ avahi-daemon[2079]: Failed to parse address 'fe80::1%xxxxxxxx', ignoring.
```
2024-12-25 09:46:45 +03:00
Я не понял как это исправить и почему локальная петля (loopback) для iv6 `fe80::1` — проблема. Отключение
2024-11-20 18:10:37 +03:00
обслуживания IPv6 для avahi в конфиге `/etc/avahi/avahi-daemon.conf` не помогло. Ставил в нем `use-ipv6=no` ,
но предупреждения продолжались. Н о , вроде, это не критично, но...
2024-11-17 01:08:44 +03:00
2024-11-20 18:32:38 +03:00
| |
|:----------------------------------------------|
| **СООБЩАЙТЕ, ЕСЛИ З Н А Е Т Е К А К ЭТО ИСПРАВИТЬ!** |
| |
2024-11-17 01:08:44 +03:00
2024-11-20 18:10:37 +03:00
Пока я нашел следующее решение (по карйне мере у меня сработало, и сработало только если е г о проделать после всех
2024-11-20 18:32:38 +03:00
предыдущих пунктов по установке `avahi-daemon` вручную). Порядок действий напоминает шаманство:
2024-11-20 18:10:37 +03:00
Запускаем конфигуратор Orange Pi:
```shell
sudo orangepi-config
```
Панель orangepi-config на Orange Pi 5 выглядит так:
2024-11-20 18:12:29 +03:00
2024-11-20 18:10:37 +03:00

Выбираем пункт ** 'System: System and security settings'** и заходим в панель ** 'System Settings'**. Выбираем в ней пункт
'**Avahi: Announce system in the network**':
2024-11-20 18:12:29 +03:00
2024-11-20 18:10:37 +03:00

Сервис устанавливается.
2024-11-20 18:12:29 +03:00
2024-11-20 18:10:37 +03:00

Возможно, на панели 'System Setting' вместо пункта 'Avahi: Announce system in the network' будет пункт 'Avahi: Disable
system announcement in the network':
2024-11-20 18:12:29 +03:00
2024-11-20 18:10:37 +03:00

2024-11-20 18:12:29 +03:00
2024-11-20 18:32:38 +03:00
Всё равно выбираем е г о : сначала отключаем avahi-демон; после возвращаемся в '**System Settings**'; повторно выбираем пункт
'**Avahi: Announce system in the network**' и устанавливаем avahi-демон заново через '**Avahi: Announce system in the
2024-12-25 09:46:45 +03:00
network**'... Всё как у настоящих системщиков — надо "выйти и зайти".
2024-11-20 18:10:37 +03:00
2024-11-20 18:32:38 +03:00
Покидаем orangepi-config (Back и затем Exit) и перезагружаем Orange Pi:
2024-11-20 18:10:37 +03:00
```shell
2024-11-20 18:32:38 +03:00
sudo reboot
2024-11-20 18:10:37 +03:00
```
2024-11-20 18:32:38 +03:00
После перезагрузки предупреждения о проблемах loopback для iv6 (`fe80::1`) в avahi должны исчезнуть.
2024-11-20 18:10:37 +03:00
```shell
sudo service avahi-daemon status
2024-11-20 18:24:44 +03:00
```
2024-11-20 18:10:37 +03:00
2024-11-27 00:53:45 +03:00
В с е чисто. Магия!
2024-11-20 18:10:37 +03:00
------
2024-11-27 00:53:45 +03:00
## Настройка сети
2024-11-20 18:10:37 +03:00
2024-12-17 01:16:43 +03:00
#### hostname
2024-11-20 18:10:37 +03:00
2024-12-17 01:16:43 +03:00
Настроить имя хоста (hostname) можно командой `hostnamectl` . Например, для узла `opi5plus-1` :
```shell
sudo hostnamectl set-hostname opi5plus-1
```
2024-12-17 21:53:54 +03:00
Или просто отредактировать файл `/etc/hostname` :
```shell
2024-12-17 01:16:43 +03:00
sudo nano /etc/hostname
```
И внесем в него имя узла (на самом деле заменим, т.к. в файле уже прописано имя хоста). Например, `opi5plus-1` ,
`opi5plus-2` и так далее. Сохраняем и закрываем файл.
2024-12-17 21:53:54 +03:00
Изменения вступят в силу после перезагрузки узла. Н о чтобы не перезагружать узел, можно применить изменения в `/etc/hostname` сразу:
```shell
sudo service systemd-hostnamed restart
```
Кстати, чтобы временно изменить hostname, можно использовать команду `hostname` . Например для узла `opi5plus-1` :
```shell
sudo hostname opi5plus-1
```
Что бы узнать текущее имя хоста, можно использовать команду `hostname` :
```shell
hostname
```
2024-12-17 01:16:43 +03:00
#### ip
Можно настроить статический IP-адрес для каждого узла кластера (о б этом будет отдельная заметка). Н о можно
и оставить и автоматическое получение IP-адреса от DHCP-сервера. Для этого надо на зарезервировать IP-адреса для
каждого узла кластера в DHCP-сервере. Резервирование IP-адресов в DHCP-сервере обычно делается по MAC-адресу устройства.
Чтобы узнать MAC- и IP-адреса Orange Pi. Н а Ubuntu это можно сделать, например, с помощью команды `ifconfig` .
2024-11-27 00:53:45 +03:00
Увидим что-то вроде этого:
```text
...
...
enP4p65s0: flags=4163< UP , BROADCAST , RUNNING , MULTICAST > mtu 1500
inet 192.168.1.110 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 fe80::1e2f:65ff:fe49:3ab0 prefixlen 64 scopeid 0x20< link >
ether 1c:2f:65:49:3a:b0 txqueuelen 1000 (Ethernet)
RX packets 656166 bytes 157816045 (157.8 MB)
RX errors 0 dropped 12472 overruns 0 frame 0
TX packets 44578 bytes 4805687 (4.8 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
...
```
2024-11-27 00:54:33 +03:00
* MAC-адрес: `ether 1c:2f:65:49:3a:b0`
* IP-адрес: `inet 192.168.1.110`
2024-11-27 00:53:45 +03:00
2024-12-17 01:16:43 +03:00
И кстати, на Orange Pi 5 Plus есть два сетевых интерфейса: `enP4p65s0` и `enP3p49s0` (и, если установлен
WiFi-адаптер PCIe, ещё и третий). Так что стоит зарезервировать в DHCP адреса для всех интерфейсов.
#### DNS
Н а всякий случай, установим утилиты для работы с DNS (они обычно уже установлены в Ubuntu, но на всякий случай):
```shell
sudo apt install dnsutils
```
В случае с DHCP настройки DNS получены автоматически, при каждой перезагрузке узла конфигурационный файл
`/etc/resolv.conf` будет перезаписываться. Н о если у нас статический IP-адрес, то нам надо настроить `/etc/resolv.conf`
вручную. В нем указывается DNS-сервер, к которому обращается узел для преобразования доменных имен в IP-адреса,
а так же указывается домен, к которому принадлежит узел и который будет использоваться по умолчанию для преобразования
коротких доменных имен в полные.
```shell
sudo nano /etc/resolv.conf
```
В файле, обычно уже прописаны DNS-сервера. Нам остается только добавить доменное имя. Получим что-то типа вот такого:
```text
# Generated by NetworkManager
nameserver 192.168.1.1
nameserver fe80::1%enP4p65s0
search local
```
2024-12-25 09:46:45 +03:00
Как видим мы добавили строку `search local` , где `local` — это доменное имя которое будет добавляться к коротким,
2024-12-17 01:16:43 +03:00
и таким образом hostname в нашем случае `opi5plus-1` будет преобразовываться в `opi5plus-1.local` . Сохраняем и
закрываем файл.
#### hosts
Что бы узлы кластера могли общаться между собой по именам, нам надо добавить их в файл `/etc/hosts` . Откроем е г о :
```shell
sudo nano /etc/hosts
```
2024-12-17 21:53:54 +03:00
И добавим в него строки вида для каждого узла кластера. Например, для узлов `opi5plus-1` :
2024-12-17 01:16:43 +03:00
```text
127.0.0.1 localhost
127.0.1.1 opi5plus-1.local opi5plus-1
::1 localhost ip6-localhost ip6-loopback opi5plus-1.local opi5plus-1
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# УЗЛЫ КЛАСТЕРА (не забудьте заменить ip-адреса и имена узлов)
192.168.1.XX1 opi5 opi5.local
192.168.1.XX2 opi5plus-1 opi5plus-1.local
192.168.1.XX3 opi5plus-2 opi5plus-2.local
192.168.1.XX4 opi5plus-3 opi5plus-3.local
192.168.1.XX5 rpi3b rpi3b.local
```
2024-12-17 21:53:54 +03:00
Перезагружаем сетевые настройки:
```shell
sudo service networking restart
```
Теперь узлы кластера могут общаться между собой по именам. Можно проверить, например, пингом:
```shell
ping opi5plus-3
```
2024-12-20 23:56:29 +03:00
#### SSH-авторизация по ключам
Для общения между узлами кластера по SSH без ввода пароля, нам надо настроить авторизацию по ключам. Выпустим по паре
ключей (публичный и приватный) на каждом узле кластера. Н а каждом узле выполним команду:
```shell
ssh-keygen -t rsa
```
В процессе генерации ключей нам предложат указать место для сохранения ключей. По умолчанию они сохраняются в папке
`~/.ssh/` (папка `.ssh` в домашнем каталоге пользователя). Можно оставить по умолчанию, нажав _Enter_ . Так же предложат
указать пароль для ключа. Нужно оставить пустым, нажав _Enter_ . После генерации ключей, в папке `~/.ssh/` появятся два
файла: `id_rsa` (приватный ключ) и `id_rsa.pub` (публичный ключ).
Теперь надо обменяться публичными ключами между узлами кластера. Для этого на каждом узле кластера выполним команды,
например для узла `opi5plus-1.local` (не забываем заменить `[user]` на имя пользователя):
```shell
ssh-copy-id [user]@opi5plus-2.local
ssh-copy-id [user]@opi5plus-3.local
```
Таким образом, хост `opi5plus-1.local` отправит свой публичный ключ на хосты `opi5plus-2.local` и `opi5plus-3.local` .
С другими узлами кластера поступим аналогично.
При обмене ключами сначала попросят ввести `yes` для подтверждения подключения к хосту, и предотвращения MITM-атаки
2024-12-25 09:46:45 +03:00
(Man-In-The-Middle — человек посередине). После этого попросят ввести пароль пользователя на удаленном хосте. После
2024-12-20 23:56:29 +03:00
успешного ввода пароля, публичный ключ будет добавлен в файл `~/.ssh/authorized_keys` на удаленном хосте. Теперь можно
подключаться к удаленному хосту без ввода пароля.
Проверим, что авторизация по ключам работает. Подключимся к удаленному хосту (например к `opi5plus-2.local` ):
```shell
ssh [user]@opi5plus-2.local
```
Для отключения с удаленного хоста наберем команду `logout` .
-----
2024-12-17 21:53:54 +03:00
## Еще немного подготовительных действий
2024-12-17 23:20:39 +03:00
#### Настойка времени
2024-12-25 09:46:45 +03:00
Для самого Kubernates не так важно, чтобы время на всех узлах было синхронизировано, но для баз данных, кэшей и
других сервисов, работающих на узлах кластера, это может оказаться критичным. Поэтому настроим синхронизацию времени.
2024-12-17 23:20:39 +03:00
Посмотреть текущий часовой пояс можно командой:
```shell
timedatectl
```
2024-12-25 09:46:45 +03:00
Установим на всех узлах один и тот же часовой пояс. Например, для Москвы:
2024-12-17 23:20:39 +03:00
```shell
sudo timedatectl set-timezone Europe/Moscow
```
2024-12-25 09:46:45 +03:00
Н а Orange Pi 5 настройку часового пояса можно сделать и через `sudo orangepi-config` (пункт ** 'System: Timezone'**).
2024-12-17 23:20:39 +03:00
Также установим NTP (Network Time Protocol) для синхронизации времени. Описание установки и настройки есть
[в другой заметке ](../misc/deploying-django-site-to-dvs-hosting.md#3-настраиваем-службу-времени-необязательно ).
2024-12-25 09:46:45 +03:00
Следует отметить, что т.к. у Orange Pi 5 Plus есть встроенные часы реального времени (RTC), а NTP-клиент имеет
более высокие накладные расходы, по сравнению с SNTP (Simple Network Time Protocol). Для микрокомпьютеров можно
немного поднастроить NTP. В частности убрать дефолтный список серверов времени и добавить только ближайшие к нам.
2024-12-17 23:20:39 +03:00
Список NTP-серверов можно посмотреть на сайте [ntppool.org ](https://www.ntppool.org/ ). Например, для России список
2024-12-20 23:56:29 +03:00
пула в `/etc/ntp.conf` будет такой (и добавим еще [московский сервер ](https://kb.msk-ix.ru/public/ntp-server/ )...
и не забудьте убрать дефолтные):
2024-12-17 23:20:39 +03:00
```text
pool 0.ru.pool.ntp.org minpoll 9 maxpoll 14
pool 1.ru.pool.ntp.org minpoll 9 maxpoll 14
pool 2.ru.pool.ntp.org minpoll 9 maxpoll 14
pool 3.ru.pool.ntp.org minpoll 9 maxpoll 14
server ntp.msk-ix.ru minpoll 8 maxpoll 12 prefer
```
Здесь:
2024-12-25 09:46:45 +03:00
* `pool` — Указывает пул серверов времени. Клиент автоматически выбирает серверы из указанного пула и может
переключаться между ними для повышения надежности и отказоустойчивости. `server` — указывает конкретный сервер
2024-12-17 23:20:39 +03:00
времени для синхронизации. Если сервер недоступен, NTP-клиент будет пытаться подключиться к нему снова
через некоторое время.
2024-12-25 09:46:45 +03:00
* `minpoll` и `maxpoll` — это минимальный и максимальный интервалы обращения к серверу. Значения — это степени
2024-12-19 22:32:30 +03:00
двойки. По умолчанию значения равны 6 (64 секунды) и 10 (~17 минут). Н о для микрокомпьютеров можно установить
побольше. У нас 9 (~8.5 минуты) и 14 (~4.5 часа). Н а самом деле обращения к серверам времени будут происходить
в случайные интервалы времени (jitter), но в пределах указанных значений.
2024-12-17 23:20:39 +03:00
* `prefer` -- это приоритетный сервер. Если у нас несколько серверов, то NTP-клиент будет обращаться к приоритетному.
Это позволит уменьшить нагрузку от NTP-клиента и снизить трафик.
2024-12-25 09:46:45 +03:00
2024-12-17 23:20:39 +03:00
#### Установка необходимых пакетов
2024-12-17 21:53:54 +03:00
В системе уже должны быть установлены пакеты `apt-transport-https` (для работы с HTTPS-репозиториями) и `curl` (для
передачи и получения данных с использованием различных протоколов), `wget` (для загрузки файлов из интернета), `gnupg`
(для работы с GPG-ключами), `sudo` (для выполнения команд от имени суперпользователя), `iptables` (для настройки
фильтрации пакетов), `tmux` (для работы с несколькими терминалами в одном окне). Проверим их наличие:
```shell
sudo apt install apt-transport-https curl wget gnupg sudo iptables tmux
```
Также установим `keepalived` (для обеспечения высокой доступности, балансировки нагрузки, мониторинга состояния
серверов и автоматического переключения на резервные серверы в случае сбоя) и `haproxy` (балансировщик нагрузки и
прокси-сервер для TCP и HTTP приложений, для распределения трафика между серверами и обеспечения высокой доступности).
```shell
sudo apt install keepalived haproxy
```
2024-12-19 22:32:30 +03:00
#### Модули и параметры ядра
В каждом узле, создадим конфигурационный файл для загрузки необходимых Kubernetes модулей ядра (`overlay` и
`br_netfilter` ). Для этого создадим конфиг в папке `/etc/modules-load.d/` . Файл может иметь любое имя с расширением
`.conf` , для удобства назовем е г о `k8s.conf` :
```shell
sudo nano /etc/modules-load.d/k8s.conf
```
В файле пропишем модули:
```yaml
# Load overlay module (драйвер для работы с файловой системой overlayfs, для объединения
# нескольких файловых систем в одну)
overlay
# Load br_netfilter module (Драйвер для работы с сетевыми мостами и фильтрацией пакетов)
br_netfilter
```
Сохраняем и закрываем файл и теперь, благодаря конфигу, эти модули ядра будут автоматически загружаться при каждой
перезагрузке узла. Н о чтобы загрузить сразу и сейчас выполним команды:
```shell
sudo modprobe overlay
sudo modprobe br_netfilter
```
2024-12-20 23:56:29 +03:00
Проверим, что модуль `overlay` загружен:
```shell
lsmod | grep overlay
```
Увидим что-то вроде:
```text
overlay 126976 0
```
2024-12-25 09:46:45 +03:00
Цифры `126976` — это размер модуля в байтах и `0` — количество других модулей, которые используют этот модуль.
Проверим для модуля `br_netfilter` :
2024-12-20 23:56:29 +03:00
```shell
2024-12-25 09:46:45 +03:00
`lsmod | grep br_netfilter`
2024-12-20 23:56:29 +03:00
```
Увидим типа такого:
```text
br_netfilter 28672 0
bridge 266240 1 br_netfilter
```
2024-12-25 09:46:45 +03:00
Как видим, модуль `br_netfilter` загружен, и он используется модулем `bridge` .
2024-12-19 22:32:30 +03:00
Затем создадим конфигурационный файл для ядра Linux в папке `/etc/sysctl.d/` . В эту папку помещаются файлы с
для настройки параметров ядра Linux. Создадим файл `k8s.conf` :
```shell
sudo nano /etc/sysctl.d/k8s.conf
```
В файле пропишем параметры:
```toml
# Enable IPv6 traffic through iptables on bridges (Разрешаем обработку IPv6-трафика через iptables на сетевых мостах)
net.bridge.bridge-nf-call-ip6tables = 1
# Enable IPv4 traffic through iptables on bridges (Разрешаем обработку IPv4-трафика через iptables на сетевых мостах)
net.bridge.bridge-nf-call-iptables = 1
# Enable IP forwarding (Разрешаем пересылку IP-пакетов для маршрутизации трафика между контейнерами)
net.ipv4.ip_forward = 1
```
В принципе, первые два параметра уже установлены по умолчанию (посмотреть текущие параметры ядра можно командой
`sysctl -a` ), но на всякий случай все равно укажем их в файле. Сохраняем и закрываем файл. Теперь при перезагрузке
узла эти параметры будут загружаться автоматически. Н о чтобы загрузить их сразу исопльзуем команду:
```shell
sudo sysctl -f /etc/sysctl.d/k8s.conf
```
2024-12-20 23:56:29 +03:00
Проверим, что параметры загружены:
```shell
sudo sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
```
Увидим, что параметры установлены:
```text
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
```
2024-12-19 23:18:33 +03:00
#### Отключение swap
2024-12-19 22:32:30 +03:00
2024-12-19 23:18:33 +03:00
Для обеспечения стабильной и предсказуемой работы контейнеров, Kubernetes требует отключения файла подкачки (swap).
Это может замедлить работу системы (по этому лучше использовать Orange Pi c большим объемом памяти), но когда включен
swap, ядро может перемещать неактивные страницы памяти на диск, что может привести к задержкам и непредсказуемому
поведению контейнеров. Отключение swap позволяет Kubernetes более точно управлять ресурсами и гарантировать, что
контейнерам будет выделено достаточно памяти.
Проверим, включен ли swap:
```shell
sudo swapon --show
```
Если увидим, что swap включен, например вот так:
```text
NAME TYPE SIZE USED PRIO
/dev/zram0 partition 7.8G 0B 5
```
Как видим, у нас есть swap-раздел `/dev/zram0` . Это "электронный диск" в памяти, который используется для
кэширования данных. Отключим е г о :
```shell
sudo swapoff /dev/zram0
```
Сначала узнать как на самом деле называется служба `zram` в вашей системе можно командой:
```shell
systemctl list-units --type=service | grep zram
```
Затем отключим эту службу чтобы электронный диск не создавался при каждой загрузке:
```shell
sudo systemctl disable orangepi-zram-config.service
```
И остановим службу:
```shell
sudo service orangepi-zram-config stop
```
И наконец, удалим соответствующие записи из файла `/etc/fstab` , чтобы предотвратить их автоматическое монтирование при
загрузке системы. Для этого удалим из файла `/etc/fstab` строку, содержащую `/dev/zram0` :
```shell
sudo sed -i '/zram0/d' /etc/fstab
```
2024-12-19 22:32:30 +03:00
2024-12-20 23:56:29 +03:00
Теперь проверим, что swap отключен:
```shell
sudo swapon --show
```
2024-12-25 09:46:45 +03:00
Если ничего не выводится, значит swap отключен. Н о возможно, даже если swap отключен и е г о нет в `/etc/fstab` , он может
был создан и включен с помощью `dphys-swapfile` . Чтобы исключить swap сперва отключим е г о :
```shell
sudo swapoff -a
```
Отключим службу `dphys-swapfil` :
```shell
sudo service dphys-swapfile stop
sudo systemctl disable dphys-swapfile
```
И удалим файл подкачки, если он есть:
```shell
sudo rm /var/swap
```
2024-12-20 23:56:29 +03:00
-----
## Установим Docker и Kubernetes
2024-12-19 22:32:30 +03:00
2024-12-20 23:56:29 +03:00
#### Ключи и репозитории
Для начала на каждом узле нашего будущего кластера надо установить GPG-ключи репозитория Docker и Kubernetes.
Установка GPG-ключей для Docker подробна описана в [отдельной инструкции ](../docker/docker-trusted-gpg.md ). Для
Kubernetes ключи устанавливаются похожим образом. Скачиваем GPG-ключ в папку `/etc/apt/trusted.gpg.d/` :
```shell
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/kubernetes-apt-keyring.gpg
```
2024-12-19 22:32:30 +03:00
2024-12-25 09:46:45 +03:00
Добавляем репозиторий Kubernetes (с указанием этого GPG-ключа и ARM-платформы, ведь у нас Orange Pi 5 Plus на ARM64):
2024-12-20 23:56:29 +03:00
```shell
echo 'deb [arch=arm64 signed-by=/etc/apt/trusted.gpg.d/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
```
2024-11-18 01:15:17 +03:00
2024-12-25 09:46:45 +03:00
А для старенького Raspberry Pi 3 Model B+ на ARMv7:
```shell
echo 'deb [arch=armhf signed-by=/etc/apt/trusted.gpg.d/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
```
2024-12-20 23:56:29 +03:00
Готово. Теперь обновим список пакетов:
```shell
sudo apt update
2024-12-25 09:46:45 +03:00
```
#### Установка Docker и Kubernetes
Наконец, установим Docker и Kubernetes:
```shell
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin kubelet kubeadm kubectl
```
Где:
* `docker-ce` — это Docker Community Edition (Docker CE) — это бесплатная версия Docker, которая включает в себя
Docker Engine, Docker CLI и Docker Compose.
* `containerd.io` — это контейнерный менеджер, который управляет жизненным циклом контейнеров.
* `docker-compose-plugin` — это плагин для Docker, который позволяет использовать Docker Compose с Kubernetes.
* `kubelet` — это агент, который работает на каждом узле кластера и отвечает за запуск контейнеров.
* `kubeadm` — это утилита для управления кластером Kubernetes.
* `kubectl` — это утилита командной строки для управления кластером Kubernetes.
Так же нам надо **на каждый узел** установить `cri-dockerd` -- демон, который позволяет Kubernetes использовать
Docker в качестве контейнерного рантайма. Начиная с версии 1.20, Kubernetes прекратил прямую поддержку Docker
и для взаимодействия появился `cri-dockerd` -- интерфейс Container Runtime Interface (CRI) для Docker,
выступающий в роли моста между Kubernetes и Docker. Он позволяет Kubernetes управлять контейнерами.
Найти самый свежий релиз `cri-dockerd` можно на [странице релизов ](https://github.com/Mirantis/cri-dockerd/releases ).
Перед загрузкой рекомендуется проверить актуальную архитектуру с помощью команды: `uname -m` . Например, для Orange Pi 5
покажет архитектуру `aarch64` (вариант ARM64). Скачаем соответствующий релиз:
```shell
sudo wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.16/cri-dockerd-0.3.16.arm64.tgz
```
Распакуем архив, переместим исполняемый файл в папку `/usr/local/bin/` и удалим архив:
```shell
sudo tar xvf cri-dockerd-0.3.16.arm64.tgz
sudo mv cri-dockerd/cri-dockerd /usr/local/bin/
sudo rm -rf cri-dockerd-0.3.16.arm64.tgz
```
Сделаем службу `cri-dockerd` для systemd. Для этого в папке `/etc/systemd/system/` создадим файл `cri-docker.service` .
Он описывает службу `cri-dockerd` и определяет, как и когда она должна быть запущена. Создадим файл:
```shell
sudo nano /etc/systemd/system/cri-docker.service
```
Содержимое файла ([см. тут](https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.service)):
```toml
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket
[Service]
Type=notify
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd://
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
```
Где:
* [Unit] -- Описывает службу.
* `Description` -- Описание службы.
* `Documentation` -- Ссылка на документацию.
* `After` -- Указывает, что служба должна быть запущена после указанных служб.
* `Wants` -- Указывает, что служба требует наличия указанных служб.
* `Requires` -- Указывает зависимость от сокета `cri-docker.socket` .
* [Service] -- Конфигурация службы.
* `Type` -- Определяет тип службы.
* `ExecStart` -- Указывает команду, которая будет запущена при старте службы.
* `ExecReload` -- Указывает команду, которая будет запущена при перезагрузке службы.
* `TimeoutSec` -- Устанавливает время ожидания завершения службы.
* `RestartSec` -- Устанавливает время между перезапусками службы.
* `Restart` -- Указывает, как ведет себя сервис в случае ошибки. `always` -- перезапускать всегда.
* `StartLimitBurst` -- Устанавливает количество попыток запуска службы.
* `StartLimitInterval` -- Устанавливает интервал между попытками запуска службы.
* `LimitNOFILE` -- Устанавливает максимальное количество открытых файлов. `infinity` -- неограничено.
* `LimitNPROC` -- Устанавливает максимальное количество процессов.
* `LimitCORE` -- Устанавливает максимальный размер ядра.
* `TasksMax` -- Устанавливает максимальное количество задач.
* `Delegate` -- Указывает, что служба может делегировать свои привилегии.
* `KillMode` -- Устанавливает режим завершения процесса.
* [Install] -- Указывает, когда и как служба должна быть активирована.
* `WantedBy` -- Указывает, что служба должна быть активирована вместе с ёmulti-user.targetё.
Создадим конфигурацию сокета `cri-docker.socket` для службы `cri-dockerd` . Она определяет, как и где сервис будет
слушать входящие соединения и управлять доступом к нему. Создадим файл:
```shell
sudo nano /etc/systemd/system/cri-docker.socket
```
Содержимое файла ([см. тут](https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.socket)):
```toml
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-docker.service
[Socket]
ListenStream=%t/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
```
Где:
* [Unit] -- Описывает службу.
* `Description` -- Описание сокета.
* `PartOf` -- Указывает, что этот сокет является частью службы cri-docker.service.
* [Socket] -- Конфигурация сокета.
* `ListenStream` -- Указывает путь к сокету, который будет использоваться для связи.
* `SocketMode` -- Устанавливает права доступа к сокету (0660 -- чтение и запись для владельца и группы, чтение для остальных).
* `SocketUser` -- Устанавливает владельца сокета.
* `SocketGroup` -- Устанавливает группу, которой принадлежит сокет.
* [Install]: Указывает, когда и как сокет должен быть активирован.
* `WantedBy` -- Указывает, что сокет должен быть активирован вместе с sockets.target.
* Этот файл гарантирует, что cri-dockerd будет слушать на указанном сокете .