Скидки, которые вы не получали - почему Spot и Graviton дешевле
Счёт от AWS второй месяц подряд превышал бюджет. Пытаясь найти, что урезать, я понял: настоящий рычаг - не «сколько потреблять», а «как покупать». История о том, почему Spot и Graviton дешевле, и о статье расходов (RDS Proxy), которая выглядит как трата впустую, но выключать её нельзя - о причине за каждой цифрой в счёте.
Главное
Когда просят сократить облачные расходы, рука сама тянется к вопросу «что выключить». Но если ресурсы уже оптимизированы, единственный оставшийся рычаг - способ оплаты. Fargate Spot - это распродажа свободных мощностей AWS с условием «заберём обратно за 2 минуты», поэтому он дешевле на 70% (условие приемлемо для staging). Graviton - это чип ARM собственной разработки AWS без посреднической наценки, поэтому он дешевле на 20% (безусловная скидка - можно использовать даже в продакшене). Но бывают и обратные случаи: расходы вроде RDS Proxy выглядят излишними, а на деле это страховка от всплеска подключений. Читать счёт - значит не сокращать цифры, а понимать причину каждой из них: скидки с приемлемыми условиями - забирать, расходы, предотвращающие сбои, - оставлять.
Содержание
Счёт от AWS второй месяц подряд превышал бюджет. Превышение составляло однозначный процент - в абсолютных цифрах немного, но направление было вверх. Я стал перебирать ресурсы один за другим в поисках, что ещё урезать, - и вывод оказался неожиданным. Сокращать было почти нечего. Настоящий рычаг лежал не в вопросе «сколько потреблять», а в вопросе «как покупать». Из этого я вынес: у каждой цифры в счёте есть причина, и только зная эту причину, можно решить, что выключить, а что оставить.
Ресурсы уже были подогнаны
Сначала я посмотрел на объём потребления. Но здесь работа уже была проделана. NAT-шлюз убрали в пользу публичных подсетей, логи хранились только 7 дней, трейсинг шёл с сэмплированием 1%, дашборд наблюдаемости укладывался в бесплатный лимит. База данных и Redis уже работали на более дешёвых ARM-инстансах, S3 использовал автоматическое тиринг, а бастион поднимался только при необходимости. На уровне ресурсов было выжато почти всё, что можно.
Июньский счёт по статьям выглядел так: больше всего приходилось на базу данных (RDS) - около 40% от общей суммы, затем на вычисления (ECS Fargate) - около 17%, балансировщик нагрузки и WAF - по около 10% каждый, а публичный IP, кеш (ElastiCache) и S3 - однозначные проценты каждый. Урезать инстансы ещё сильнее означало бы шаг назад. У базы уже была история апгрейда из-за нехватки памяти, а WAF стоял намеренно - чтобы проверять правила перед выкладкой в продакшен. Оставшийся рычаг был не в ресурсах, а в способе оплаты: пользоваться теми же мощностями, но покупать их дешевле.
Почему Spot дешевле
Первое, что бросилось в глаза, - вычисления покупались исключительно по прайсовой цене on-demand. У AWS есть канал, где те же серверы продаются гораздо дешевле, - Fargate Spot. Он дешевле on-demand примерно на 70%.
У такой цены есть причина. AWS строит дата-центры под пиковый спрос. В обычное время сервера простаивают. Держать свободные мощности без дела - это нулевая выручка, поэтому AWS продаёт их за бесценок с условием «если придёт клиент по полной цене - освобождаем место за 2 минуты». Это тот же принцип, что и распродажа авиакомпаниями пустых мест перед самым вылетом: раз уж место всё равно улетит пустым и выручка будет нулевой, выгоднее продать его хоть с условиями, чем не продать вовсе.
Вопрос в том, можно ли выдержать это самое условие - «освободить место по требованию». В продакшене это проблематично: если у задачи есть подключённые пользователи, а её отзовут через 2 минуты, сервис на мгновение, но пошатнётся. А вот staging - другое дело. Там нет реальных пользователей, и даже если что-то упадёт на несколько минут, это лишь ненадолго неудобно одному QA-инженеру. Поэтому я перевёл API в staging на Spot. Производительность полностью совпадает с on-demand - vCPU и память работают на том же самом железе. Меняется только одно условие доступности - «может быть отозвано», и staging готов был с этим мириться. После перехода задачи staging начали нормально работать на Spot.
Почему Graviton дешевле
Второй момент касался самого чипа вычислений. База данных и Redis уже работали на ARM, а вот Fargate, на котором крутилось приложение, всё ещё сидел на x86. При переходе на Graviton - собственный чип ARM от AWS - ту же производительность можно получить примерно на 20% дешевле.
Причина дешевизны здесь другая, чем у Spot. Обычный инстанс - это CPU, который AWS закупает у Intel или AMD, и в цену, которую платим мы, заложена маржа производителя чипа. Graviton спроектирован самой AWS, поэтому этой посреднической наценки нет. Кроме того, архитектура ARM тратит меньше энергии и выделяет меньше тепла на те же операции, а значит дата-центру нужно меньше электричества и охлаждения. Для AWS себестоимость ниже, так что продавать на 20% дешевле всё равно выгодно, и это ещё и стратегия - затянуть клиентов в собственную экосистему чипов дешёвой ценой.
Ключевое отличие вот в чём. К скидке Spot прилагается условие «смирись с тем, что тебя отзовут», а к скидке Graviton не прилагается никакого условия - это просто более дешёвый чип. Поэтому если Spot применим только к staging, то Graviton можно без оговорок использовать вплоть до продакшена. С производительностью тоже почти нет поводов для беспокойства: Node.js на Graviton показывает производительность на vCPU на уровне x86 или даже выше. Единственный момент, за которым стоит следить, - холодный старт. При первом запуске приложения важна скорость одного ядра, и здесь Graviton может немного уступать современным x86, из-за чего запуск иногда занимает на несколько секунд дольше. Поэтому я сначала выкатил его на staging, замерил время запуска и только потом перевёл в продакшен. Из предварительных проверок нужна лишь одна - убедиться, что нативные модули собраны под arm64.
Если резюмировать природу этих двух скидок, получается так. Spot - это скидка за готовность мириться с неудобством, поэтому у неё есть условие (отсюда и staging), а Graviton - это скидка за передачу нам ценового преимущества собственного чипа AWS, поэтому условий нет (отсюда и продакшен). При одинаковой производительности не было смысла оставаться на дорогом прайсе x86. По сути, эта оптимизация - не столько новая экономия, сколько наконец-то полученные скидки, которые мы раньше просто не забирали.
Бывают расходы, которые нельзя выключать
Но если пройтись по счёту дальше, встречается и обратная ловушка - статья, которая выглядит как лишняя трата, а на деле оказывается страховкой.
Таким был RDS Proxy. За него каждый месяц уходила фиксированная сумма, и на первый взгляд он казался кандидатом на сокращение. Одна из функций Proxy - беспростойная автоматическая ротация секретов, а эта ротация была у нас отключена. Возникал вопрос: зачем держать Proxy, если ротацией мы не пользуемся?
Это было ошибочное прочтение. Изначальное назначение Proxy - не ротация, а защита от всплеска подключений. При деплое или скейлауте число задач резко растёт, и вместе с ним резко растёт число подключений к базе, а у базы есть предел на количество одновременных подключений. Proxy собирает и мультиплексирует подключения перед базой, не давая превысить этот предел. Как назло, именно эта база уже была той самой, которую однажды пришлось апгрейдить из-за нехватки памяти, а каждое подключение съедает память. Иначе говоря, этот фиксированный расход - не трата впустую, а страховая премия за то, что база не падает от лавины подключений при каждом деплое. Отключить его значило бы не сэкономить, а снять защиту.
Причиной ошибочного прочтения был комментарий в коде. Комментарий, описывающий этот Proxy, был написан преимущественно с точки зрения ротации, из-за чего читающий легко мог решить: «раз ротация отключена, Proxy тоже не нужен». Поэтому вместо того чтобы убирать Proxy из плана сокращения расходов, я добавил в комментарий строку: «Основное назначение - сдерживание всплеска подключений, ротация - лишь дополнительная функция». Чтобы следующий, кто будет смотреть на счёт, не сделал той же ошибки.
У каждой цифры в счёте есть причина
Когда просят сократить облачные расходы, рука сама тянется к вопросу «что выключить». Урезать инстансы, отключить функции, удалить ресурсы. Но на этот раз урок оказался обратным. Прежде чем сокращать, нужно спросить: «почему эта цифра здесь?»
Одни цифры - это скидки, которые мы не забирали. Как в случае со Spot и Graviton: существует канал, где те же ресурсы можно купить дешевле, а мы просто покупали их по полной цене. У каждой такой скидки своя причина дешевизны, и если знать эту причину (готовность смириться с отзывом мощности или безусловное ценовое преимущество), становится ясно, где её безопасно применить. Другие цифры, наоборот, - это страховка, которую нельзя выключать. Даже если статья выглядит как лишняя трата, если за ней стоит предотвращаемый ею сбой, это не расход, а защита.
В итоге читать счёт - значит не делать цифры меньше, а понимать причину каждой из них. Зная причину, можно забрать скидки с приемлемыми условиями и оставить расходы, предотвращающие сбои. Всё, что мы сделали, - именно это. Не новая экономия, а разделение того, какие скидки забрать, а какую страховку оставить.
Частые вопросы
Можно ли использовать Fargate Spot в продакшене?
Компромисс Spot в том, что задача может быть отозвана через 2 минуты после предупреждения. Если среда способна пережить такое прерывание, Spot подходит и для продакшена. При HA-конфигурации с несколькими задачами, где кратковременное снижение мощности не критично, возможно и частичное применение. Но если задача одна или нагрузка чувствительна к прерываниям, это рискованно - безопаснее начать со staging, где прерывание безвредно.
Не упадёт ли производительность при переходе на Graviton (ARM)?
В большинстве нагрузок она такая же или даже выше. В частности, Node.js на Graviton показывает производительность на vCPU на уровне x86. Единственный момент, за которым стоит следить, - холодный старт: при первом запуске приложения скорость одного ядра у Graviton немного ниже, чем у современных x86, из-за чего запуск может занять на несколько секунд дольше. Достаточно измерить время запуска на staging, прежде чем переводить в продакшен, и заранее проверить, что нативные модули собраны под arm64.
Похожие статьи
- 💻 Разработка
Хуки остановки срабатывали дважды - когда у SIGTERM два хозяина
После каждого деплоя в Sentry падала ошибка Prisma P2028. Полез чинить порядок завершения работы и обнаружил, что enableShutdownHooks из NestJS и библиотека graceful shutdown одновременно ловят SIGTERM, из-за чего хуки завершения каждый раз выполнялись дважды.
- 💻 Разработка
«Да просто выключи в staging» - как шумный 404-алерт скрывал настоящий баг
Каждый день в staging прилетал одинаковый алерт про 404 от Google Play. Отключить источник шума и починить сам режим сбоя - это разные задачи. 404 - это постоянная ошибка, повторять запрос при которой бесполезно, но клиент валил её в одну кучу с 5xx и всё равно ретраил.
- 💻 Разработка
MDX-блог на Next.js своими руками - как сделан этот блог
Как я собрал блог на Next.js 16 App Router, который работает на одних markdown-файлах, без CMS. Структура папок, настройка MDX и SEO на реальном коде.