В каждом офисе есть кладбище техники. У нас это были старые Mac mini — аккуратно сложенные, тихие, бесполезные. Когда-то на них работали, потом они перестали тянуть современные задачи, а дальше стандартный сценарий: «Давайте не выкидывать, вдруг пригодятся».

Как оказалось, пригодились.

Привет, Хабр! Меня зовут Николай, я занимаюсь выстраиванием инфраструктуры в web-продакшне RocketDev. В этой статье я расскажу, как дал вторую жизнь офисному железу и приспособил его для рабочих задач.

Почему не облако?

Я не против облаков. Работаю с ними, использую, понимаю зачем они нужны. Но когда учишься инфраструктуре, хочешь разбираться в сетях, экспериментируешь с Kubernetes и периодически что-то ломаешь — облако становится проблемой.
Каждый новый VM — это счётчик. Каждый эксперимент — мысль: «А не дороговато ли?». А мне хотелось своё железо, свободу ломать и чинить, инфраструктуру максимально близкую к реальной.
Покупать сервер ради этого — сомнительная идея. А вот использовать то, что уже есть — вполне рационально.

Что было в распоряжении?

На складе нашлось около 6 Mac mini от 2010-2013 года на i3-i5 процессорах и с ОЗУ от 16-32ГБ. Не серверы, конечно, но у них есть важные плюсы: компактные, тихие, не жрут электричество, полноценный x86. Идеальные кандидаты для homelab, который не раздражает ни уши, ни бухгалтерию. Для работы выбрал 3 машины.

Характеристика машинок:

  • CPU: 4 x Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz

  • RAM: 16ГБ

  • Storage: ssd 256ГБ (на третьей железке объем 500ГБ)

  • Сеть: Gigabit Ethernet

    В офисе валялся и старый роутер с тремя свободными Ethernet-портами. Этого было более чем достаточно для начала.

Сеть без фанатизма

Никакой сложной схемы. Роутер, три Mac mini, каждый напрямую подключён. Да, без VLAN, без умных коммутаторов, без enterprise-подхода.
Моя цель была не в том, чтобы это красиво выглядело на схеме, а в том, чтобы система работала. Все ноды получили статические IP в одной подсети 192.168.31.0/24 — обычная домашняя сеть без излишеств. Оптимизация — потом.

Proxmox: первая нода без сюрпризов

В качестве гипервизора выбор был очевиден — Proxmox VE. Бесплатный, с web-интерфейсом, есть поддержка кластеров из коробки, широко используется в проде. Да и просто чаще всего про него слышал — было интересно попробовать его в деле.
Первую ноду разворачивал на чистый Debian 13. Процесс оказался довольно прямолинейным, хотя и требовал внимательности к деталям.
Первым делом пришлось разобраться с сетью. NetworkManager в Debian конфликтует с тем, как Proxmox управляет сетями, поэтому его нужно было отключить. Вместо этого настроил Linux Bridge через /etc/network/interfaces — это виртуальный коммутатор, к которому будут подключаться VM.

Физический интерфейс без IP:

iface enp1s0f0 inet manual

Linux Bridge с реальным IP:

auto vmbr0

iface vmbr0 inet static

        address 192.168.31.189/24

        gateway 192.168.31.1

        bridge-ports enp1s0f0

        bridge-stp off

        bridge-fd 0

Здесь важный момент: физический интерфейс теперь работает как порт моста, а сам bridge получает IP адрес. Через этот мост VM будут иметь прямой доступ к сети, как будто они подключены напрямую к роутеру.

После настройки сети добавил репозиторий Proxmox, установил пакеты, перезагрузился. Через 15 минут имел web-интерфейс на http://192.168.31.189:8006. Первая VM с Ubuntu 24.04 поднялась без проблем.

Вторая нода: когда начинается кластер

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

Главная засада поджидала в /etc/hosts. По дефолту Debian прописывает hostname на 127.0.0.1, что кажется логичным. Но для Proxmox кластера это смертельно — ноды не смогут найти друг друга по именам.

Правильная конфигурация выглядит так:

127.0.0.1       localhost.localdomain localhost

Реальный IP второй ноды:

192.168.31.190   pve2.local pve2

Проверить можно командой hostname --ip-address — она должна вернуть реальный IP, а не 127.0.0.1. Если возвращает локалхост — кластер не сложится, будет ругаться на недоступность нод. И у второй ноды прописать хостнэйм первой:

192.168.31.189 pve.local pve

Ещё один момент — синхронизация времени. Установил chrony на обеих нодах, настроил на один NTP сервер. Рассинхрон даже в пару секунд может сломать кворум кластера, и тогда начинается веселье с логами и дебагом.

Создание кластера: момент истины

Когда обе ноды были готовы, настало время их объединить. На первой ноде выполнил pvecm create RBRUclaster. Эта команда инициализирует Corosync — систему, которая следит за состоянием кластера и поддерживает кворум между нодами.

На второй ноде запустил pvecm add 192.168.31.189, ввёл root-пароль первой ноды, и началось волшебство. Proxmox скопировал конфигурацию кластера, перезапустил свои сервисы, и через минуту в web-интерфейсе я увидел обе ноды под одним Datacenter. Как потом узнал, аналогичное можно провести уже в админке системы — так уже подключал третью ноду:

pvecm status

Эта команда показала то, что я хотел видеть: Quorum OK, две ноды online. Теперь можно было мигрировать VM между нодами, и они видели общее хранилище конфигураций.

Третья нода: когда игрушка стала инфраструктурой

Самое интересное произошло не сразу. Я заметил, что виртуалки не удаляются неделями. На них появляются сервисы. Ими начинает пользоваться кто-то кроме меня.

Первой «прижилась» VM с GitLab Runner, потому что CI/CD на локальных машинах — это боль. Потом появилась dev-Ubuntu с Docker, на которой разработчики начали поднимать свои окружения. Затем мониторинг — Prometheus + Grafana, чтобы понимать, что происходит с кластером.

И в какой-то момент стало очевидно: двух нод уже мало. Нагрузка росла, VM множились. Хотелось распределить их более равномерно. Так появилась третья нода, и вот тут инфраструктура окончательно перестала быть «песочницей».

Процесс добавления третьей ноды был идентичен второй: настроил сеть, hostname, установил Proxmox, выполнил pvecm add. Единственное отличие — теперь кластер стал по-настоящему отказоустойчивым. С тремя нодами можно утратить одну без потери кворума.

Разработка через VM: неожиданный кейс

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

Теперь процесс выглядит так: разработчик говорит: «Мне нужно окружение для работы над проектом». Я за пару минут клонирую template с Ubuntu, Docker и базовым набором инструментов. Или, если сайт на Bitrix, то разворачиваю CentOS с BitrixVM, после чего разворачиваю про��кт для работы. Он получает доступ по SSH, подключается через VSCode Remote, клонирует проект из GitLab и начинает работать. Для публичного доступа к сайту или проектам я использую проксирование через VPN. Это также удобно с точки зрения безопасности: подключиться к VM можно только при активном VPN. Для этого использую простое решение Wireguard.

Окружение максимально похоже на production. Никакого «у меня работает» — если работает в VM, будет работать и на серверах. Локальная машина остаётся чистой. Можно выделить VM больше ресурсов, чем есть на ноутбуке. А если что-то сломалось — просто откатываемся на snapshot или разворачиваем новую VM.

Для особо частых сценариев я создал несколько templates: базовая Ubuntu с Docker, окружение для Python разработки, template с Node.js стеком. Разворачивание нового окружения занимает буквально две минуты через web-интерфейс Proxmox.

После этого возвращаться к локальной разработке становится трудно — слишком заметна разница.

Kubernetes: когда теория встречается с реальностью

Отдельным бонусом всей этой затеи стала возможность нормально поработать с Kubernetes. Не в Docker Desktop, не в демо-режиме «на попробовать», а с настоящим bare metal, несколькими нодами, реальной сетью и проблемами, которые нельзя решить кнопкой Restart cluster.

Кластер поднимал через kubeadm: один control plane и два worker. Каждый компонент — в отдельной VM внутри Proxmox. Всё максимально приближено к реальному продакшну, без магии и managed-абстракций.

Сеть организовал через Calico — де-факто стандарт дл�� bare metal. Storage реализовал через local-path-provisioner. Решение простое и наглядное: оно хорошо подходит для homelab, потому что позволяет явно контролировать, где именно хранятся данные.

И вот тут началось самое интересное: Pods не видели друг друга. Вообще.

Казалось бы — всё поднялось, ноды в Ready, CNI установлен, а трафика нет. Начался классический DevOps-квест: проверка конфигурации Calico, просмотр iptables, маршрутов между нодами, чтение issue на GitHub. В итоге оказалось, что проблема была в сетевой конфигурации Calico — из-за нюансов IP-in-IP трафик между нодами просто дропался. После правок и пересоздания компонентов сеть наконец-то ожила.

Дальше — Persistent Volumes. Pod стартует, контейнер падает с permission denied. Начинаю разбираться и понимаю: local-path-provisioner создаёт директории на хосте с правами, которые не совпадают с пользователем внутри контейнера. Пришлось разобраться с fsGroup, правами и тем, как Kubernetes вообще монтирует volume внутрь pod’а. После этого storage начал работать предсказуемо.

Отдельное удовольствие — Ingress и MetalLB.

Ingress вроде есть, сервис типа LoadBalancer, но трафик снаружи не идёт. Пришлось глубже разобраться, как MetalLB в L2-режиме раздаёт внешние IP, как работает ARP и почему «оно вроде настроено, но не работает». Зато после этого пропало ощущение чёрного ящика — стало понятно, что именно происходит на уровне сети.

Особенно запомнился именно этот момент:

в облачном managed Kubernetes я бы просто открыл тикет в поддержку. Здесь же пришлось разбираться самому — читать документацию, логи, чужие грабли. Да, было больно. Да, местами хотелось всё снести. Но именно в такие моменты приходит реальное понимание, как Kubernetes работает под капотом.

И, пожалуй, это был самый ценный результат всей затеи. Не просто «кластер работает», а понимание почему он работает — и почему иногда нет.

Как это выглядит сейчас

Сейчас кластер состоит из трёх нод Proxmox, объединённых в единый Datacenter. На них крутится шесть постоянно работающих виртуальных машин, плюс периодически появляются временные VM под эксперименты и тесты.

Нагрузка распределена неравномерно — и это осознанное решение.

pve (основная нода) — минимальная CPU-нагрузка, в пределах нескольких процентов, потребление памяти около 10 ГБ из 16 ГБ. Здесь живут наиболее «стабильные» сервисы: GitLab Runner, мониторинг, dev-базы данных. Это та часть инфраструктуры, которая должна работать предсказуемо и без сюрпризов.

pve1 (dev) основная рабочая лошадка. Здесь чаще всего запускаются dev-окружения разработчиков, тестовые VM, временные сервисы. Нагрузка по CPU выше, память почти всегда занята под завязку — именно сюда прилетает всё новое и экспериментальное.

pve2 (эксперименты) самая разгруженная нода. На ней крутится Kubernetes-кластер и различные тестовые VM, которые могут жить день-два и исчезать без сожалений. Это место для экспериментов, обновлений, проб новых подходов и идей без риска сломать остальное.

Такое разделение оказалось удобным на практике: есть чёткое понимание, где что живёт. Любая нестабильная активность не мешает работе остальной инфраструктуры.

Чек-лист для тех, кто решит повторить

Когда объясняешь коллегам как это всё работает, понимаешь что нужна структура. Что я рекомендую проверять на каждом этапе?

  1. Перед началом: убедитесь, что у вас есть минимум две машины (лучше три), работающая сеть и терпение на пару вечеров экспериментов.

  2. Сеть — самое важное: NetworkManager должен быть отключен, иначе он будет конфликтовать с bridge. Настройте статические IP. DHCP для кластерных нод — это плохая идея. Проверьте, что bridge поднимается после перезагрузки и VM видят сеть.

  3. Hostname критичен: команда hostname --ip-address должна возвращать реальный IP, а не 127.0.0.1. Если видите локалхост — идите править /etc/hosts. Иначе кластер не сложится, и вы будете час искать проблему в логах.

  4. Время должно быть синхронизировано: установите chrony на всех нодах, настройте на один NTP сервер. Проверьте через timedatectl status. Рассинхрон даже в пару секунд ломает кворум.

  5. Перед созданием кластера ноды должны пинговать друг друга по имени, а не только по IP. Между нодами нужен рабочий SSH. Все ноды должны видеть друг друга в /etc/hosts.

  6. После создания кластера: выполните pvecm status на каждой ноде — должно быть Quorum OK. При этом в web-интерфейсе любой ноды в левом меню отображаются все ноды кластера. Попробуйте создать VM и мигрировать её между нодами.

Что не получилось

Важно понимать границы. Mac mini не тянут тяжёлые базы данных под серьёзной нагрузкой. Процессоры уровня i5 справляются с dev-нагрузкой, но это не серверные Xeon — при параллельных запросах и интенсивных операциях CPU становится узким местом.

С дисками та же история. Локальные SSD обеспечивают нормальную отзывчивость для разработки и тестирования, но при высокой нагрузке на запись и большом количестве I/O начинают упираться в свои ограничения. Для production-сценариев с активной БД этого недостаточно.

Надёжность тоже не enterprise-уровня. Нет резервного питания, один сетевой интерфейс, отсутствует аппаратный RAID. Если что-то ломается — будет простой. Поэтому production-сервисы здесь не крутим, только dev и staging.

Масштабируемость ограничена текущей сетью и возможностями железа. Три ноды — комфортный потолок для такого сетапа. По 16 ГБ RAM на каждой хватает для нескольких VM и Kubernetes-кластера, но дальше упираешься в физические ограничения.

Отдельный момент — живая миграция VM. Без shared storage (NFS или Ceph) она работает только в offline-режиме, то есть с остановкой виртуальной машины. Для dev это приемлемо, для production было бы проблемой.

Что дальше?

В ближайшее время хочу добавить managed коммутатор — для VLAN и изоляции трафика между разными типами VM. Сейчас все VM в одной сети, что не очень безопасно.

Потом NAS для shared storage. Это позволит делать live migration VM без остановки и вынести backups на отдельное устройство. Сейчас всё хранится на локальных дисках нод, что не очень надёжно.

Ещё думаю про автоматизацию развёртывания через Terraform. Сейчас VM создаю руками через web-интерфейс или командами, но хотелось бы описать инфраструктуру как код.

Из интересного — хочу попробовать service mesh на Kubernetes кластере. Istio выглядит перспективно, но я пока не до конца понимаю все его возможности. Можно развернуть в тестовом неймспейсе и поэкспериментировать.

Стоило ли?

Да, стоило. Получил кластер из трёх нод, реальную dev-инфраструктуру, площадку для экспериментов с Kubernetes — место где можно безопасно ошибаться. И всё это на старом офисном железе, которое раньше просто пылилось.

Главный урок: инфраструктура — это навык, который нарабатывается практикой. Можно год читать документацию по Proxmox, Kubernetes, networking, но ничто не заменит опыт «собрал, сломал, починил, понял как оно работает».

Mac mini не стали серверами уровня датацентра. Но они стали отличной точкой входа в реальную инфраструктуру. Теперь, когда я работаю с production системами в облаке, я понимаю что происходит под капотом. Потому что сам это всё настраивал руками и хорошо знаком с типичными проблемами.


Если есть вопросы или хотите обсудить похожий опыт — пишите в комментариях.