Как и зачем создавать нашу платформу SaaS на Hetzner и Kubernetes
17 марта 2023 г.Всем привет, это Ласло, основатель Gimlet.io 👋.
В этой записи блога я попытаюсь рассмотреть различные аспекты того, как и почему мы построили нашу платформу SaaS на Hetzner и Kubernetes, а не на одном из поставщиков гипермасштабируемых облачных услуг.
Это интересное время. Пока мы создавали нашу платформу на базе Hetzner, Дэвид Хайнемайер Ханссон, основатель 37Signals, также начал работу над своим новым проектом по отказу от AWS в пользу управляемого центра обработки данных. Его посты на эту тему получили широкое распространение в социальных сетях. Хотя DHH является противоположным и иногда хорошо задает тренды, мы здесь не для того, чтобы начинать какое-либо движение или присоединяться к нему.
В этом посте я просто хочу поделиться нашим выбором и опытом с Hetzner с любознательными. Покажите, какие инструменты мы использовали, какие компромиссы нам пришлось учитывать и каковы плюсы и минусы отказа от использования одного из крупных облачных провайдеров в начале 2023 года. Итак, приступим?
Перво-наперво:
Почему Hetzner?
Я не хочу слишком долго тянуть: это была цена.
Мы построили наши вычислительные узлы на базе модели EX43, новейшей скобяной машины Hetzner. Шестиядерный процессор Alder Lake с 64 ГБ ОЗУ и 2 твердотельными накопителями NVMe по 512 ГБ стоит
52,1 евро в одном из центров обработки данных Hetzner в Германии. В нашем случае НДС нет.
Сравнивая это с
* Экземпляры AWS m6a.2xlarge
и m6i.2xlarge
стоимостью 281 и 312 долларов США соответственно в eu-west-1
* а c3-standard-8
и n2-standard-8
от Google Cloud доступны по цене 277 и 311 долларов США в europe-west4
Существует значительное ценовое преимущество на стороне Hetzner.
И это только по сравнению с восемью виртуальными ядрами ЦП. Если принять во внимание количество дисковых IOPS, которые мы получаем от «голого» сервера, как минимум удвоенный объем памяти и тот факт, что мы получаем не восемь виртуальных ЦП, а шесть реальных ядер ЦП с двенадцатью потоками, Hetzner в пять раз дешевле. мягко сказано.
Но не все вещи равны; Хетцнер в пять раз дешевле, это имеет свою цену. Мы упускаем возможности, над созданием которых специалисты по гипермасштабированию потратили десятилетие.
Что мы теряем, не размещая хостинг в одном из больших облаков?
Нам нужно всего несколько вещей, чтобы запустить нашу платформу, и среди них больше всего нам не хватает в Hetzner:
* В первую очередь нам нужен Kubernetes; мы бы использовали управляемый Kubernetes, если бы он был доступен. * Нам нужна высокодоступная база данных SQL, но RDS или CloudSQL недоступны. * Виртуальные сети и группы безопасности. Нам пришлось работать даже над базовой безопасностью сети и хоста на Hetzner.
Решение проблемы с отсутствующим управляемым Kubernetes
Управление Kubernetes — это не то, чем мы предпочитаем заниматься, и обычно мы полагаемся на управляемые предложения Kubernetes, но с Hetzner это просто невозможно.
Несмотря на то, что мы сами управляем Kubernetes, мы старались свести к минимуму движущиеся части. Простота является ключевым для нас; поэтому мы решили использовать проект k3s. K3s — это полностью совместимый дистрибутив Kubernetes с несколькими заметными упрощениями:
* k3s использует базу данных SQL в качестве хранилища, поэтому нам вообще не нужно иметь дело с etcd. * Он упакован в виде одного двоичного файла и имеет соответствующую конфигурацию. Все кластерные операции — например, управление сертификатами — сводятся либо к аргументу бинарника k3s, либо к команде CLI. * Это безопасно по умолчанию с разумными значениями по умолчанию для облегченных сред
Мы приняли еще одно примечательное архитектурное решение, упростившее построение нашего кластера Kubernetes: мы сохранили наше состояние в базах данных SQL, поэтому нам не нужно было устанавливать и поддерживать кластерную файловую систему для постоянных томов.
Несмотря на то, что мы сократили многие из сложных частей в нашей настройке, мы ожидаем несколько дней обслуживания, иногда немедленных действий, в следующем году, которые будут связаны с нашим самоуправляемым Kubernetes.
Но узлы также умирают в управляемых предложениях Kubernetes, а диски заполняются. Возможно, в нашем случае перестроение узла будет дольше (запуск нового узла, выполнение скриптов Ansible и т. д.), чем на гиперскейлерах, но мы не ожидаем, что количество проблем и их серьезность станут неуправляемыми. Знаменитые последние слова, верно? Следующая запись в блоге должна быть опубликована через 12 месяцев.
Нет RDS, что теперь?
Управляемая база данных — это действительно то, за что я с радостью плачу больше. Высокодоступное восстановление на определенный момент времени одним нажатием кнопки — это не то, что легко воспроизвести.
Postgresql также имеет решающее значение для платформы Gimlet SaaS, поскольку мы сохраняем все состояния в базах данных Postgresql. Не только клиентские данные, но и плоскость управления Kubernetes также хранятся в базе данных SQL. Поэтому нам нужно было создать высокодоступный и безопасный кластер Postgresql, а также обеспечить правильное резервное копирование за пределы сайта.
Что вселило в нас уверенность в этом процессе, так это то, что у нас был опыт запуска реплицированных кластеров Postgres еще до появления Postgres-RDS. Кажется, что прошла целая жизнь, но Postgres на RDS нет и десяти лет.
Сеть и безопасность, главное
Большую часть времени мы потратили на настройку сети и вопросы безопасности.
По умолчанию Hetzner предоставляет вам root-доступ через SSH; нет виртуальных сетей или групп безопасности. Если вы запустите серверный процесс на своем узле, он будет мгновенно доступен в Интернете. Недружественное значение по умолчанию и отсутствие VPC и групп безопасности были самой большой проблемой, которую нам пришлось решить.
Это была также та часть, где мы привлекали внешнюю помощь. Проверка нашей установки двумя независимыми консультантами повысила нашу уверенность в этом процессе.
Создание инфраструктуры с нуля на голом железе в 2023 году
В этом разделе я перечисляю инструменты и шаги, которые потребовались для создания нашей платформы SaaS на базе Hetzner.
Инфраструктура как код
Хотя на дворе 2023 год, мы написали нашу инфраструктуру в виде настройки кода в Ansible. Поскольку большая часть конфигурации происходит внутри узла, в Terraform нет ничего особенного. Наша команда доверяла Ansible еще со времен виртуальных машин.
Безопасность узла
Первые учебники Ansible, которые мы написали, были посвящены усилению защиты узлов. Автоматические обновления, SSH fail2ban и десятки лучших практик автоматически применяются на всех наших узлах.
Безопасность сети
По умолчанию Hetzner назначает узлам общедоступный IP-адрес и предоставляет корневой доступ SSH, чтобы вы могли начать использовать узлы. Кроме того, каждый порт, который вы открываете, открыт для Интернета. По умолчанию нет частных сетей или групп безопасности. Поэтому мы начали с его создания.
Как мы построили нашу сеть:
- В Hetzner есть базовая поддержка VLAN; мы могли бы соединить наши узлы с безлимитным внутренним сетевым подключением.
- В этой внутренней сети мы также создали сетку VPN на основе Wireguard. По сути, шифрование всего трафика между нашими узлами.
- Мы установили брандмауэр на все узлы и привязали только порты 80 и 443 к IP-адресам общедоступной сети.
- Мы блокируем весь веб-трафик с помощью Cloudflare Loadbalancer и брандмауэра веб-приложений. Трафик принимается только с серверов Cloudflare.
Кубернет
Мы используем k3s. Единый бинарный дистрибутив и опыт настройки упростили работу, кроме того, мы могли поддерживать его с помощью базы данных SQL, что убрало etcd из набора. Мы не знаем etcd, так что это было потрясающе.
Мы приняли еще одно примечательное архитектурное решение, упростившее построение нашего кластера Kubernetes: мы сохранили наше состояние в базах данных SQL, поэтому нам не нужно было устанавливать и поддерживать кластерную файловую систему для постоянных томов.
Postgresql
Мы создали активно-пассивный кластер Postgresql на основе потоковой репликации.
Для простоты мы построили кластер вне Kubernetes и контейнеров. В противном случае это не было бы большой проблемой, но мы бы все равно закрепили модули Postgres на определенных узлах. Мы пока не решили использовать операторы Kubernetes Postgres, такие как Patroni.
Здесь мы пошли по одному существенному пути. На данном этапе отработка отказа предназначена для ручного управления. Это может быть значительным источником простоев, и мы можем улучшить эту практику в следующих версиях нашей платформы.
Важно отметить, почему мы пошли на этот риск: чтобы включить автоматическую отработку отказа, нам пришлось бы написать пуленепробиваемый сценарий отработки отказа, который максимизирует доступность и минимизирует риски непротиворечивости данных. Из-за ошибки в автоматизации аварийного переключения мы можем столкнуться с проблемами согласованности данных, с которыми потенциально сложнее справиться, чем с простоями. По сути, мы оптимизировали для простоты работы и достаточного времени безотказной работы.
Теперь судить о достаточно хорошем времени безотказной работы должен читатель, поскольку на данный момент Gimlet не предоставляет SLA, но позвольте мне оставить вас с двумя мыслями:
* Доступность на уровне 99,5 % — общеотраслевой стандарт для платформ SaaS — означает 1,83 дня простоя в год. Доступность на уровне 99 % означает простои в течение 3,65 дней в году. Последнее практически означает, что вся наша команда может быть в отпуске в джунглях Бразилии, вернуться в Европу, открыть свои ноутбуки и выполнить аварийное переключение базы данных, и мы все равно будем работать быстрее, чем за три дня. Само собой разумеется, что мы не планируем путешествовать по джунглям Бразилии без чьего-либо вызова. * Здесь полезно посмотреть, что предоставляет SLA база данных Amazon RDS. Они довольно мягко говорят о теме: «AWS приложит коммерчески разумные усилия», и если они потерпят неудачу, они вернут вам деньги в виде кредитов. Десять процентов, если они находятся в диапазоне от 99 до 99,95%, 25% процентов, если они находятся в диапазоне от 95 до 99 процентов, и все деньги в противном случае. На практике они могут быть недоступны 18 дней в году, а вы вернете только четверть своих денег.
Гитопс: пьем собственное шампанское
Каждый зарегистрировавшийся пользователь получает новый экземпляр Gimlet, идентичный последнему выпуску версии с открытым исходным кодом. Каждая пользовательская конфигурация хранится в gitops, и мы запускаем Gimlet для управления этими экземплярами Gimlet.
Помимо экземпляров Gimlet, мы также управляем компонентами нашего кластера с помощью gitops.
Резервные копии
Мы храним состояния только в одном месте, в нашем кластере Postgresql.
Во всем остальном источником истины является наша инфраструктура в виде репозиториев кода: Ansible и gitops.
Мы создаем резервную копию нашего кластера Postgresql, шифруем и отправляем наши резервные копии за пределы площадки.
Аварийное восстановление
Наша стратегия аварийного восстановления основана на двух столпах: наших резервных копиях и инфраструктуре в качестве репозиториев кода.
Во время наших усилий по созданию платформы мы много раз перестраивали весь стек из кода, и перед запуском программы раннего доступа мы пересобирали все с нуля. Мы также провели синтетические тесты восстановления базы данных.
Шифрование
Мы шифруем данные во многих местах.
В пути:
- Мы шифруем весь трафик в нашей внутренней сети VPN на основе Wireguard.
- Мы используем SSL между нашими приложениями и Postgresql.
- Между нашими услугами.
- Между нашими приложениями и контроллером входящего трафика.
- Между нашим входным контроллером и Cloudflare.
- Между Cloudflare и конечными пользователями.
В состоянии покоя:
- Мы шифруем диски наших узлов.
- Мы шифруем наши резервные копии.
- Экземпляры Gimlet шифруют конфиденциальные поля базы данных в базе данных.
- K3s шифрует свои секреты, которые хранятся в Postgresql.
Мониторинг
Мы используем стек Prometheus / Grafana для мониторинга, UptimeRobot для мониторинга времени безотказной работы и PagerDuty для дежурства.
Как дела у Hetzner?
Мы использовали Hetzner пару лет назад. Он был достаточно стабильным тогда и сегодня.
Мы используем стандартные типы узлов и ожидаем только линейного масштабирования. Мы выделяем узлы вручную, что занимает около пятнадцати минут, прежде чем мы сможем войти в систему. Мы слышали от друзей, что это не относится к нестандартным типам машин, но мы перейдем этот мост, когда доберемся до этого.
Улучшение по сравнению с нашей предыдущей поездкой с Hetzner — это функция VLAN. Его было легко настроить на основе документации, и до сих пор он был стабильным. Одного мы не смогли добиться: подключить наши выделенные узлы к виртуальным машинам Hetzner Cloud. Мы используем выделенные узлы, но мы могли бы развернуть виртуальные машины для небольших задач, если бы VLAN работала между ними.
Это все на данный момент. Это снимок того, где мы сейчас находимся. Ожидайте повторную публикацию через 12 месяцев или ранее, если что-то существенно изменится.
Вперед!
:::информация Также опубликовано здесь.
:::
Оригинал