Подстелить Kubernetes-соломку: как предусмотреть высокую нагрузку на проекте с самого начала?

Roman Biriukov
Заметки про Evrone
6 min readSep 22, 2020

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

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

В нашей практике было несколько случаев, когда приходили клиенты с крупными проектами, с большим количеством пользователей и кричали «Спасите!». Из-за сбоев, связанных с инфраструктурой, они за минуту простоя сервисов теряли миллионы рублей.

Зачастую это направление работ оставляют на будущее из-за его кажущейся сложности и пугающей стоимости создания, поддержания реализованной инфраструктуры. Но при определенном подходе заложить все необходимое в инфраструктуру проекта можно на начальных этапах, и в Evrone, приступая к разработке новых проектов, мы применяем подходы highload с первого дня.

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

При этом Kubernetes одинаково хорош как в локальном исполнении, так и в облачном. Amazon WS и Microsoft Azure, Google Cloud, Яндекс.Облако, Облако Mail.ru, Alibaba Cloud, Huawei Cloud поддерживают его, что называется, из коробки. Но часто можно услышать, что Kubernetes — это сложно и, что важнее, это дорого. Давайте разберемся, почему это ошибочные представления.

Kubernetes — это сложно?

Kubernetes имеет обширную документацию и массу наработок сообщества.

Вы можете использовать пакетный менеджер Helm (по аналогии с Apt и Yum). С его помощью можно значительно упростить развертывание. Helm использует так называемые «чарты» — некие наборы данных для создания экземпляра приложения в кластере Kubernetes.

Чарты (шаблоны) готовы под многие случаи, и вы можете взять уже существующее решение, к примеру, на Kubeapps — в каталоге приложений для Kubernetes инфраструктуры.

В результате деплой приложения, по сути, можно настроить одной кнопкой. Конечно, можно написать чарт и самостоятельно, но в большинстве случаев найдется подходящий чарт, и если он даже не полностью соответствует вашим требованиям, то на его примере несложно будет написать свой.

Kubernetes — это дорого?

Считается, что Kubernetes довольно тяжелый. Ноды — машины в кластере по терминологии Kubernetes — содержат множество компонентов и требуют ресурсов. Минимально комфортная конфигурация начинается с пяти-шести машин с двухъядерными CPU и 4 Гб оперативки. В случае высоконагруженных сервисов, а мы часто делаем именно такие, показатели рекомендуемой RAM на управляющей мастер-ноде поднимаются до 8 Гб. Но это немного не соотносится с заявленной нами ранее концепцией — работой на доступном железе.

Master node: etcd cluster​
Master node: etcd cluster​

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

Что такое K3S. Как говорят сами разработчики, им удалось «ужать» Kubernetes в 5 (!) раз. В результате бинарник получился всего 40 Мб, а памяти требуется от 512 Мб при потреблении около 75 Мб на рабочей ноде. Для того чтобы представить весь минимализм дистрибутива, достаточно сказать, что его можно запустить даже на Raspberry Pi, что уж говорить про боевой, пусть и старенький, сервер любой компании.

За счет чего получилось так сократить «аппетит»? Если внимательно посмотреть на состав Kubernetes, то видно, что в число самых ресурсоемких компонентов входят распределенное ETCD-хранилище и облачный Cloud‑Controller Manager. Поскольку изначально в описываемой ситуации мы работаем на слабом локальном железе, то очевидно, что облачный контроллер нам на этом этапе не нужен. Тем более что в облаках уже присутствует свой менеджер Kubernetes. А значит, этот компонент можно сократить. Ну а что касается ETCD-хранилища, то его можно заменить на sqlite (или любую другую БД из списка поддерживаемых — по вашему выбору), что также облегчает дистрибутив.

Таким образом, дистрибутив K3S можно представить схемой:

Что будет, если отрезать от Kubernetes все
Что будет, если отрезать от Kubernetes все

Получилось очень легкое решение, которое, если идти совсем до конца, может вообще не использовать Docker. По умолчанию система работает с Containerid — некогда частью Docker, а сейчас самостоятельным решением, реализующим исполняемую среду для запуска контейнеров. Как пишут сами разработчики Containerid, при его создании они стремились к простоте, надежности и портируемости. Однако K3S очень гибкий, и ничего не мешает вернуть в его настройках Docker как среду контейнеризации, чтобы в дальнейшем облегчить себе переезд в облака.

Как Kubernetes применяется в Evrone

Знакомство с Kubernetes у нас началось три года назад, когда мы разрабатывали проект Vexor. Это был CI/CD-сервис, который вырос из внутреннего продукта в коммерческое решение, но сейчас проект мы приостановили. Kubernetes в этом случае позволил скомпоновать всю архитектуру, которая раньше запускалась на нескольких виртуальных машинах, в единое окружение. Как результат — мы перестали оперировать масштабами виртуальных машин, а легко перешли на сущности единого окружения с масштабируемыми ресурсами.

Так как сервисы внутри продукта теперь были слабо связаны друг с другом, а обмен данными происходил через брокер сообщений RabbitMQ, мы спокойно могли мигрировать контейнеры с одной машины на другую в зависимости от требуемых ресурсов. Все механизмы миграции, шедулинга и роутинга запросов, мониторинга за жизненным циклом сервисов брал на себя Kubernetes. И это было удобно и круто.

Сейчас все новые проекты мы запускаем в Kubernetes-окружении, независимо от их размера и сложности, а также переводим часть существующих проектов на этот стек с других решений контейнеризации, таких как docker-swarm и Nomad.

У нас в Evrone есть хороший опыт разворачивания Kubernetes-инфраструктуры на серверах bare-metal. Это немного труднее, чем в облаке, потому что нельзя заказать типовой сервер с типовой конфигурацией, а приходится работать с конкретным железом. В результате нужно решать вопросы балансировки трафика, добавления новых нод в кластер, выделения дискового пространства для постоянного хранения данных и т. п.

Также есть проекты, где приходилось разворачивать Kubernetes-окружение в режиме single node (на одной bare-metal-машине) в защищенном контуре, доступ внутрь которого производился исключительно по VPN, а внешний трафик был доступен только через http-proxy.

В этом варианте критически малого количества ресурсов мы разворачиваем кластер на базе сертифицированного дистрибутива K3S. Этот продукт позволяет производительно работать на одной, скажем прямо, довольно слабой машине. И это, что очень важно, даст возможность через некоторое время, с учетом развития проекта, мигрировать на большой кластер без переписывания всего конфигурационного стека.

Масштабирование по горизонтали или вертикали

Как мы говорили, думать о масштабировании стоит с самого начала. Замечательно, что концепция контейнеризации позволяет осуществить этот переезд с комфортом. Kubernetes становится все популярнее и позволяет работать с ним практически на всех крупных облачных площадках, дает возможность с легкостью масштабировать проект (конечно, если он изначально упакован в контейнеры), применяя горизонтальный или вертикальный подход.

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

Вертикальное масштабирование работает чуть сложнее. В зависимости от ресурсоемкости приложения выделяются более производительные серверы и/или отключаются недозагруженные. При указании технических характеристик программисты могут действовать на глазок, размышляя, к примеру, что 4 Гб точно хватит, или нерегулярно пересматривать спецификации. Как следствие, вы можете арендовать слишком мощные, а значит, дорогие серверы или, наоборот, не учесть пиковые нагрузки и «упасть» в самый ответственный момент.

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

Более подробно о работе с Kubernetes — в видеозаписи выступления Александра Кириллова, CTO Evrone, на DevOps meetup в рамках конференции Metaconf, которую проводит наша компания.

--

--