Хочу рассказать об интересном эксперименте, суть которого заключалась в развертывании и настройке Kubernetes на двух старых ноутбуках — один из них, кроме того, был с процессором на архитектуре i386. В качестве теоретической основы использовалось руководство Kubernetes The Hard Way, которое по ходу дела пришлось немного доработать, а в качестве системы на хостах — Gentoo (да, вам не показалось). Давайте погрузимся в этот увлекательный хардкор! Наверное, многие слышали про полезный и по-своему легендарный репозиторий Келси Хайтауэра — Kubernetes The Hard Way, инструкцию по развертыванию кластера K8s без готовых скриптов и утилит. В ней объясняется, как вручную запустить Kubernetes на Google Cloud Platform (GCP). Но даже сам автор утверждает, что стоимость такого кластера будет больше, чем 300 USD, которые даются в подарок за регистрацию на сервисе. А что, если у вас есть один или несколько старых ноутбуков, которые пылятся на полке, и вы хотите поднять-таки Kubernetes своими руками и бесплатно? Попробуем! Важно: эту статью стоит воспринимать лишь как дополнение к оригинальному руководству Келси Хайтауэра, так как практически всё, что им описывается, применимо не только к GCP, но и к любому другому железу или виртуальным машинам, хотя и с некоторыми оговорками. Для экспериментов у меня было два ноутбука на базе Gentoo Linux: Dell G3 3590 на базе Intel Core i5-9300H (архитектура AMD64) (далее — просто dell); HP Compaq 6720s на базе Intel Core2 Duo (архитектура i386) (далее — hpcom). Они стали узлами кластера. Операционная система ставилась по официальной документации для amd64 и x32. Но ядро собиралось с несколькими дополнительными настройками для IPSet и Docker. Для kube-proxy были включены параметры ядра NETFILTER_XT_MATCH_COMMENT и NETFILTER_XT_MATCH_STATISTIC. Также в процессе установки я столкнулся с парой трудностей, решить которые помог форум сообщества Gentoo. На всякий случай оставлю ссылки: черный экран сразу после GRUB и ошибка с ​​non-PAE kernel. Что еще:  самый обычный роутер от провайдера; основной ноутбук, с которого удаленно проводились все работы; сильное желание повозиться с Kubernetes. Выше я отметил, что внес лишь небольшие правки в оригинальное руководство по Kubernetes. Поэтому еще раз подчеркну, что в статье описываю только эти правки, указывая места, где нужно отступить от исходных инструкций. В остальных случаях даю ссылки на оригинальные разделы руководства. В этом разделе ничего не делаем, поэтому его можно со спокойной душой пропустить. Здесь никаких изменений: делаем так, как написано. Эту страницу официального руководства можно пропустить, а вместо нее для упрощения дальнейшей работы записать локальные IP-адреса будущих узлов кластера (у меня получилось так: hpcom — 192.168.1.71, dell — 192.168.1.253). Для удобства запишем эти адреса в файлик node_list.txt: Для имитации Load Balancer’а на рабочей машине можно установить и развернуть NGINX. Затем добавить в конце конфигурационного файла nginx.conf строку include passthrough.conf (на Linux стандартная директория для конфигов NGINX — /etc/nginx/, а на macOS при установке через brew — /opt/homebrew/etc/). Далее рядом создаем файл passthrough.conf. Сделать это можно такой командой (не забудьте поменять путь до NGINX-директории и путь до файла с хостами на ваши): Это поможет нам создать простейшую имитацию High-Availability-кластера (HA). Для обучения большего и не нужно. В этом разделе выполняем все в точности до пункта The Kubelet Client Certificates. Теперь нам пригодятся записанные ранее IP-адреса узлов будущего кластера: Далее идем по исходной инструкции вплоть до пункта The Kubernetes API Server Certificate. Здесь меняем вводимые строки на такие: В следующем разделе, The Service Account Key Pair, выполняем все по инструкции, а в Distribute the Client and Server Certificates просто разносим все нужное по узлам с помощью scp. Чтобы это заработало, на рабочей машине создаем файл ~/.ssh/config с помощью команды: Копируем файлы на узлы: В моем случае оба ноутбука будут выступать в качестве master’а и рабочего узла одновременно, поэтому я скопировал на них не только сертификаты для control plane, но и для рабочих узлов. Здесь пропускаем пункт про Kubernetes Public IP Address, а в The kubelet Kubernetes Configuration File вместо исходной команды выполняем: И аналогично для The kube-proxy Kubernetes Configuration File: Далее следуем инструкции до момента копирования файлов на узлы. Вместо этого делаем так: В этом разделе выполняем всё по инструкции, за исключением копирования файлов по узлам. Копируем так: Вместо оригинальной инструкции вначале заходим на узел (выполнять для каждого узла): Устанавливаем следующие необходимые утилиты: Скачиваем и собираем etcd: Конфигурируем собранный etcd. Устанавливаем сертификаты: Получаем IP-адрес и имя узла: И формируем Unit для systemd: Теперь возвращаемся к исходной инструкции и выполняем все, что идет после пункта Start the etcd Server включительно. Вначале заходим на узел (выполнять для каждого узла): Создаем каталог для конфигурации: Скачиваем исходники Kubernetes и собираем control plane: Переносим сертификаты: Для имитирования HA ставим NGINX (перед этим создав файл для USE-флагов дополнительных модулей Gentoo): В nginx.conf в блок http добавляем проверку работы сервера: И также в конец файла дописываем строку с include по аналогии с Provisioning Compute Resources выше: Затем, как на рабочей машине, создаем рядом файл passthrough.conf: Конфигурируем API-сервер. Получаем нужные IP-адреса: Создаем Unit для systemd: Далее выполняем всё из оригинальной инструкции до пункта The Kubernetes Frontend Load Balancer. Устанавливать и настраивать balancer не требуется, хотя при желании можно развернуть MetalLB после окончательной настройки кластера. Блок Verification также можно пропустить, так как мы уже развернули NGINX. Проверить работоспособность API-сервера можно так: Заходим на каждый узел и устанавливаем необходимые пакеты: Создаем нужные каталоги, скачиваем и собираем нужные бинарники: crictl для i386: И для  amd64: runc: CNI plugins: containerd requirements для i386: И для amd64: containerd: K8s: Конфигурируем CNI-плагин: Конфигурируем containerd (используется другая версия конфига, в отличие от оригинального репозитория): Контейнер pause (он же sandbox_image в конфиге containerd) от K8s не собирается для i386-архитектуры. Поэтому его можно собрать самостоятельно или воспользоваться готовым образом из моего Docker Hub’а: docker.io/alexeymakhonin/pause:i386. Если вы решили пойти первым путем, на узле с i386-архитектурой нужно собрать бинарник: Полученный бинарник и всю директорию следует скопировать на рабочий ноутбук с Docker Buildx, на котором будет собираться образ: Затем в конфигурационном файле containerd нужно поменять sandbox_image на собранный образ. Теперь создаем Unit containerd для systemd: Сконфигурировать kubelet и kube-proxy можно по оригинальной инструкции. Однако стоит помнить, что ca.pem уже скопирован в /var/lib/kubernetes, поэтому команда mv упадет с ошибкой. Проверить работоспособность узла можно так: Из этого раздела нас интересует только самое начало — пункт The Admin Kubernetes Configuration File. Выполняем его: Эти инструкции можно пропустить. Здесь инструкции придется разделить на две части. Для машины с архитектурой amd64 выполняем всё, как в оригинале, а вот для i386 придется пойти другим путем. Обусловлено это тем, что официального образа coredns для i386 не существует, поэтому его придется собирать самим (или взять уже собранный мной). Чтобы собрать образ самостоятельно, на машине с Docker Buildx выполняем команды: Затем берем конфиг с заменой образа на наш и деплоим его: Теперь остается только наложить патч на созданный ресурс, заменив значение аннотации на i386 или amd64 в зависимости от того, на какой узел вы хотите назначить coredns по архитектуре: Теперь можно проверить, что все работает, выполнив команды из оригинальной инструкции.  На этом этапе может возникнуть ошибка: Pod’ы будут зависать в состоянии ContainerCreating с ошибкой: Если это произошло, починить можно так: Делаем всё по инструкции, за исключением двух пунктов.  Команда проверки шифрования: Для NODE_PORT-сервиса: На этом этапе можно просто снести систему :) Мы рассмотрели, как можно с интересом провести время и не дать пропасть старому железу, которое, например, давно отложено в кладовку, а выбросить руки не поднимаются. Также мы научились разворачивать Kubernetes на физическом оборудовании, используя готовые инструкции из Kubernetes The Hard Way с небольшими доработками. Особенно интересным и полезным может быть опыт самостоятельной сборки недостающих образов для архитектуры i386: хотя она уже давно выходит из обращения, иногда все-таки встречается. Надеюсь, статья поможет тем, кто хочет поглубже влезть в Kubernetes и его настройку. Читайте также в нашем блоге: «Kubernetes в миниатюре для локального запуска: k0s, MicroK8s, kind, k3s и Minikube»; «Внутреннее устройство Kubernetes-кластера простым языком»; «Kubernetes — это как океанариум».  DevOps enginner at flant