Это первая часть из цикла статей посвященных инфраструктуре для стартапов. Всего их будет две, поделенные, по-моему мнению, на логически законченные блоки.

Часть первая. Настройка окружения
Часть вторая. CI/CD и советы

Для кого эта статья

Эта статья будет полезна, если вы:

  • Запускаете стартап или пет-проект и хотите минимальными усилиями и затратами настроить инфраструктуру

  • Уже немного разбираетесь в Docker и хотите что-то посерьёзнее, но без оверинженеринга

  • Ищете альтернативу Kubernetes, которую можно легко развернуть и поддерживать без отдельного DevOps-инженера

  • Не боитесь немного покопаться в настройках, но при этом хотите сохранить гибкость и контроль

Не подойдёт, если:

  • У вас высоконагруженное продакшн-окружение с миллионами пользователей

  • Есть бюджет на полноценный DevOps-отдел

  • Уже используете Kubernetes и не хотите откатываться в "попроще"

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

Введение

Начнем с небольшой предыстории. Я, как и любой студент технического вуза, мечтаю о карьере в IT, а то и о собственном стартапе. И ровно год назад моя мечта осуществилась, своими руками и общими усилиями была собрана команда классных ребят из ИТМО под названием Шампиньоны.
Изначально мы были командой из 4 разрабов и 1 дизайнера, ходили на всякие хакатоны, но мы поняли, что этого мало. Мы можем больше. Так мы обрели людей по недостающим компетенциям и начали заниматься продуктовой разработкой. Вместе с этим начали сталкиваться с новыми вызовами — и инфраструктура стала одним из них.

Один из нас уже писал статью на хабр про то, как мы поймали майнер на одном из серверов, а теперь же на своем примере поделимся инфраструктурным решением.

Шампиньоны. Слева направо =)

Как только стартап начинает разработку продукта, а то и нескольких, то остро встает вопрос о том, как наиболее выгодно поднять инфраструктуру, чтобы добиться идеального баланса. Подобно CAP теореме, выводятся сотни различных других, так и с инфраструктурой можно вывести свою — CPF.

  • Cheap

  • Performance

  • Fault Tolerance

Стартапы с деньгами эфемерны, и даже там не всегда есть средства на полноценного DevOps-инженера для поддержки системы. Отсюда вытекает, что девопсом зачастую будут заниматься сами разработчики, но как же этот процесс сгладить?

Как решать?

Для поднятия базовой инфраструктуры в голову приходит сразу два варианта:

  • Монолитная с докером — если не самый надежный хостинг, то сильно страдает надежность, а с вертикальным расширением сильно растет и цена. Также сложно поддерживать изолированно различные окружения (dev/test/prod)

  • Распределенная с кубером — сложно поднять, легко уронить, стоимость devops инженера, который знает кубер определенно выше

Хочется оговориться, что мы рассматриваем все в рамках стартапа, где по определению не бывает много денег.

Зная все минусы, хочется какой-то третий вариант — и он есть! Многие наверняка сталкивались со статьей "Docker swarm для самых маленьких", так и я её давно заприметил. Далеко не сразу получилось придумать, как внедрить его в существующую систему. По ходу работы в команде обнаруживались различные классные инструменты: portainer, watchtower, traefik. Вместе с ними и получилось подружить docker swarm.

Почему именно он?
Это тот же Docker, только с нотками кубернетеса. Мастер и воркер ноды, стэки/поды, концепции очень близки и главное позволяют развернуть инфраструктуру на нескольких серверах. Это повысит отказоустойчивость и упростит работу с различными окружениями. Любой разработчик минимально знающий Docker способен задеплоить приложение, соответственно и стоимость данного решения будет минимальна.

Инфраструктура на Docker Swarm

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

Первичная настройка

Пример строится на 2 VPS'ках

Чтобы не ходить по разным статьям и сайтам, написал скрипт для минимально быстрой настройки машинки.
Для мастер ноды используйте m, для воркера — w:

curl -fsSL https://raw.githubusercontent.com/shampsdev/startup-infrastructure/refs/heads/main/init.sh | bash -s -- [m/w]

Теперь проинициализируем мастер ноду и подключим к ней воркеры. Все машинки находятся в одной приватной сети, поэтому их можно подключать, через внутренний ip. Для этого необходимо указать флаг --advertise-addr

docker swarm init --advertise-addr 10.16.3.1

> docker swarm join --token genarated_token 10.16.3.1:2377

Указанную команду вводим на своих воркер нодах. Хостнеймы и все свои ноды можно проверить с помощью команды docker node ls.
А чтобы было проще с ними взаимодействовать, то с помощью сварма к нодам можно добавить лейблы. Таким образом можно настроить гибкий деплой различный сервисов. К нему мы перейдем в следующей главе.

docker node update --label-add TAG=dev [hostname]

И последним этапом настройки станет добавление оверлей сети для траефика. Overlay-сеть позволяет контейнерам на разных нодах Docker Swarm иметь сетевой доступ друг к другу:

docker network create -d overlay --attachable traefik

Также, по желанию, вы можете отключить историю тасок с помощью команды:

docker swarm update --task-history-limit 0

Команда отключает сохранение истории выполненных задач в Docker Swarm. По умолчанию Docker сохраняет историю для мониторинга и отладки. Установив лимит на 0, вы отключаете её, что полезно, если не требуется отслеживать изменения и нужно снизить нагрузку на систему, особенно в крупных кластерах с частыми обновлениями.

Настройка Portainer

Portainer будет выступать в роли GUI нашей системы. Он поддерживает работу в Swarm-режиме и позволяет удобно управлять стеками, сервисами, томами и другими сущностями Docker. Особенно полезен для быстрой настройки и визуального контроля над инфраструктурой, а также отлично подходит для настройки CI/CD процессов — как для одиночных серверов, так и для кластеров.

После того, как скопируете себе докер компоуз для портейнера, исправьте лейбл с строчкой Host(your.domain.com) на нужный вам домен.

curl -o docker-compose.yaml https://raw.githubusercontent.com/shampsdev/startup-infrastructure/refs/heads/main/portainer-traefik/portainer.docker-compose.yaml

Поскольку ключевые понятия — стеки, таски и реплики — уже подробно описаны в других статьях, здесь я сосредоточусь только на необходимых командах. Так как мы используем Docker Swarm, docker-compose up работать корректно не будет — для развертывания нужно использовать стек:

docker stack deploy -c docker-compose.yaml portainer

Теперь заходим на сервер по адресу http://<ip>:9000 и проходим первичную регистрацию администратора:

После того, как создали админ пользователя -- перезапустите сервис:

docker service update --force portainer_portainer
GUI портейнера

Поздравляю — Portainer установлен и работает! Благодаря его интерфейсу вы можете:

  • запускать сервисы в GUI

  • отслеживать состояние контейнеров и стеков

  • просматривать логи

  • управлять конфигурацией без командной строки

  • работать с Secrets, сетями, томами и пр.

Как именно пользоваться Portainer’ом — тема для отдельной статьи, но в рамках этой серии мы ещё увидим пример его взаимодействия с Traefik.

Важно сказать, что вся работа должна происходить в primary окружении

Настройка Traefik

Traefik — это reverse proxy и load balancer, который просто интегрируется с Docker Swarm, Kubernetes и другими оркестраторами. Он автоматически отслеживает изменения в конфигурации и маршрутизирует трафик на основе меток и правил. В рамках нашей инфраструктуры Traefik будет выполнять роль маршрутизатора входящего трафика, обеспечивая:

  • автоматическую маршрутизацию по поддоменам

  • автоматическую выдачу и обновление SSL-сертификатов (через Let’s Encrypt)

  • балансировку нагрузки

  • базовую защиту на уровне доступа

  • мониторинг через встроенный дашборд

  • интеграцию с системами мониторинга

Далее — развернём его в рамках Docker Swarm и настроим базовые правила.

Настроим конфиг траефика через портейнер
Для этого зайдем во вкладку Configs > Add config. Далее необходимо указать уникальное имя для конфига. Я предпочитаю такой нейминг: service-config-v1. Содержимое можно скопировать из репозитория, там сразу подготовлена база для сбора метрик.

К сожалению, необходимо вводить такое версионирование, так как менять конфиги налету нельзя, придется делать копии.Считаю, что в Openshift'e реализован идеальный вариант, когда есть один конфиг и внутри него можно контролировать версии, но мы и не с кубером работаем.

Интерфейс настройки конфига

Настроим стек traefik
Теперь зайдем в Stacks > Add stack. Компоуз файл для стека можно взять из репозитория traefik.docker-compose.yaml. Однако перед тем, как запускать сервис, необходимо сгенерировать пароль для дашборда с помощью следующей команды:

echo $(htpasswd -nB user) | sed -e s/\\$/\\$\\$/g

Для дашборда используется basic auth и подробную информацию можно найти в документации траефика. Поэтому полученный пароль необходимо подставить для basicauth.users=

Важно: при работе с Traefik 3.x лучше не полагаться на GPT и ИИ как на единственный источник информации — обязательно сверяйтесь с официальной документацией, так как многое меняется.

Все. Вы настроили реверс прокси и балансировщик, который автоматически выдает и обновляет SSL без лишней головной боли.

Лейблы для Traefik

Для деплоя стека с доменом необходимо указать следующие лейблы траефика:

Лейбл

Назначение

traefik.enable=true

Подключает сервис к маршрутизации Traefik

traefik.docker.network=traefik

Указывает, в какой сети искать сервис. Лучше создавать отдельные сети для каждого сервиса

traefik.http.routers.<name>.entrypoints=https

Через какие порты сервис будет доступен (обычно 80 и 443)

traefik.http.routers.<name>.rule=Host(`example.com`)

Задает домен и правила маршрутизации для сервиса

traefik.http.routers.<name>.certresolver=letsEncrypt

Резолвер для TLS/SSL-сертификатов. Название, как в конфиге

traefik.http.services.<name>.loadbalancer.server.port=80

Внутренний порт контейнера, на который отправляется трафик

Дашборд Траефика

Важно: при работе в swarm-режиме траефик должен быть расположен на manager ноде. В примере нашей инфраструктуры используется 2 сервера и траефик расположен на мастере, так что никаких проблем не возникнет. Однако, если вы захотите вынести траефик на отдельный сервер, то его необходимо сделать менеджером с помощью docker node promote [name/ID]

Traefik — мощный инструмент, но он требует понимания некоторых особенностей при работе в Docker Swarm. Мы рассмотрели базовую настройку, включая автоматическое получение SSL-сертификатов, защиту dashboard и маршрутизацию трафика.


Если вы дошли до этого места — спасибо. Надеюсь, этот материал был полезен, а главное — показал, что даже без миллионов и команды DevOps-инженеров можно делать инфраструктуру с умом.


До встречи в следующей части!

Тут ссылка на репозиторий