Первый сервис команда подняла на виртуальной машине: поставили Java, скопировали jar, запустили. Через год сервисов двадцать, на каждой машине свой способ запуска, обновления накатывают по ночам руками, а половина машин простаивает. Другая команда с первого дня взяла Kubernetes «потому что так делают все» и полгода чинила кластер вместо продукта.
Обе ошибки — про выбор уровня вычислений. У любого облака их три, и различаются они тем, что провайдер берёт на себя, а что оставляет вам. В этой статье разберём эти уровни, два механизма, которые прилагаются к каждому, и правило выбора.
Главное
- Три уровня: виртуальная машина (всё внутри ваше), контейнер (вы отдаёте образ, платформа его запускает), функция (вы отдаёте код на событие).
- Чем выше уровень, тем меньше эксплуатации: не надо патчить ОС, следить за процессом, держать кластер, но тем меньше контроля и дороже единица ресурса.
- Балансировщик раздаёт запросы между копиями и убирает из ротации те, что не отвечают на проверку здоровья.
- Автомасштабирование меняет число копий по нагрузке в заданных границах; без осмысленной проверки готовности оно вредит.
- Функции засыпают без нагрузки и просыпаются с задержкой холодного старта; для чувствительного к задержке API это важно.
- Выбор идёт снизу вверх по потребности: один сервис с волнами нагрузки — контейнер без кластера; двадцать сервисов и команд — оркестратор; перенос «как есть» — машина.
Уровень первый: виртуальная машина
Виртуальная машина — сервер с операционной системой, который вы получаете через минуту после запроса. Провайдер отвечает за железо и гипервизор, всё остальное ваше: обновления системы, установка Java, запуск и перезапуск процесса, логи, диски. Это максимум контроля и максимум ответственности.
Берут машину, когда нужно именно это: перенести сервис «как есть» с его systemd-юнитом и cron, поставить то, что в контейнер не заворачивается, или получить полный контроль над ядром и сетью. Машины не устарели, они просто редко бывают лучшим первым выбором для обычного веб-сервиса.
Уровень второй: контейнер
Контейнер — упакованный образ приложения со всем окружением. На втором уровне провайдер запускает его сам, и здесь два подхода. Без оркестратора: вы отдаёте образ и лимиты, платформа поднимает столько копий, сколько нужно под нагрузку, вплоть до нуля, когда обращений нет; кластера, узлов и их обновлений вы не видите. С оркестратором: провайдер держит управляющую часть Kubernetes, а вы работаете с рабочими узлами и манифестами.
Разница — в цене сложности. Контейнер без кластера — самый простой способ запустить обычный HTTP-сервис, и для одного-двух сервисов он почти всегда лучше. Kubernetes окупается, когда сервисов и команд много и нужны единый выкат, общая сеть между сервисами и тонкая настройка размещения; для двух сервисов это оркестратор ради оркестратора.
Уровень третий: функция
Функция — кусок кода, который облако вызывает на событие: HTTP-запрос, сообщение в очереди, файл в хранилище, время по расписанию. Сервера нет вовсе: платите за миллисекунды работы, в простое ноль. Это идеальный клей между сервисами — обработать загруженную картинку, среагировать на событие, выполнить задачу по расписанию.
Ограничения тоже жёсткие. Функция засыпает без нагрузки, и первый вызов после паузы ждёт, пока окружение поднимется, — холодный старт, для Java с большим пакетом зависимостей это секунды. Есть потолок времени выполнения и размера ответа. Поэтому целый бэкенд в функциях — плавание против течения; функции берут под события, а сервис с постоянным трафиком запускают контейнером.
Балансировщик и автомасштабирование
К любому уровню, кроме одиночной машины, прилагаются два механизма. Балансировщик принимает запросы на одном адресе и раздаёт их между копиями, а копии, не ответившие на проверку здоровья, убирает из ротации. Автомасштабирование меняет число копий по нагрузке в заданных границах: минимум, максимум, целевая загрузка процессора или число запросов на копию.
Оба держатся на проверке здоровья, и здесь главная ловушка. Ответ «порт открыт» ещё не значит «готов работать»: сервис мог подняться, но не подключиться к базе. Проверять надо готовность — отдельный путь, который отвечает «ок» только когда сервис реально может обслуживать запросы. Без этого балансировщик шлёт трафик в неготовую копию, а автомасштабирование плодит копии, которые не помогают.
Как выбирать
Идите снизу вверх по потребности, а не сверху вниз по моде. Нужно перенести сервис как есть или нужен контроль над машиной — виртуальная машина. Один-два сервиса с неравномерной нагрузкой — контейнер без кластера. Много сервисов, несколько команд, единый выкат и команда, знающая Kubernetes, — оркестратор. Редкие события и склейка между сервисами — функции. Самая частая ошибка — начать с Kubernetes ради одного сервиса; вторая — держать сервис с постоянным трафиком в функциях и удивляться холодным стартам и счёту.
Глубже: что общего у всех трёх уровней внутри
Под всеми тремя уровнями лежат одни и те же машины провайдера. Контейнерная платформа — это машины, на которых провайдер сам держит среду выполнения и кладёт туда ваши образы; функции — те же контейнеры, которые провайдер поднимает на событие и гасит через минуты простоя. Поэтому холодный старт функции — это время на запуск контейнера с вашим кодом, а «масштабирование до нуля» — просто удаление контейнеров, за которые вы перестаёте платить.
Отсюда же растёт разница в цене. Секунда работы функции стоит дороже секунды той же машины, потому что вы платите ещё и за готовность провайдера поднять её мгновенно. При постоянной нагрузке машина или контейнер с фиксированным числом копий выходят дешевле, при редкой — функция.
Глубже: тонкости автомасштабирования
Автомасштабирование реагирует не мгновенно: метрика собирается раз в минуту, копия поднимается минуту-две, и на резкий всплеск трафика оно опаздывает. Поэтому границу «минимум копий» ставят с запасом на пик, а не по ночной нагрузке, и держат буфер в виде очереди там, где всплеск можно переждать.
Уменьшение копий опаснее увеличения: копия, которую гасят, может обрабатывать запросы, и без корректной остановки они оборвутся. Платформы дают время на завершение и сигнал перед остановкой; как приложение должно на него отвечать, разобрано в разделе про остановку приложения.
Что почитать дальше
- Где запускать сервис в AWS — четыре сервиса AWS на этой же лестнице.
- Kubernetes — оркестратор целиком: поды, деплойменты, пробы.
- Docker — образ, который облако запускает на втором уровне.