29 сент. 2024 г.·7 мин чтения

Аудит инфраструктуры внешним CTO для снижения затрат и рисков

Аудит инфраструктуры внешним CTO помогает безопасно сократить расходы: убрать старые зависимости, почистить деплои и сначала проверить мощность.

Аудит инфраструктуры внешним CTO для снижения затрат и рисков

Почему расходы растут незаметно

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

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

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

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

Глубинная проблема — в ответственности. Многие компании смотрят только на общий ежемесячный итог, но почти никто не отвечает за счёт построчно. Финансы видят расходы. Инженеры следят за стабильностью. Продуктовые команды гонятся за сроками. У никого нет ни времени, ни чётких полномочий, чтобы спросить, почему теперь пять сервисов делают то, что раньше делали три.

Страх удерживает хаос на месте. Команды часто подозревают, что часть сервисов уже не нужна, но боятся, что удаление чего-то вызовет сбой. Поэтому они оставляют всё как есть ещё на один месяц, потом на другой. Осторожность понятна. Но она дорого стоит.

Хороший аудит обычно показывает один и тот же рисунок. Инструменты остаются после завершения исходного проекта. Команды платят за пересекающиеся сервисы. Никто один не проверяет счёт подробно. Очистку откладывают, потому что риск кажется неясным.

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

Как внешний CTO проверяет стек

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

Первый проход должен быть простым: запишите инструмент, счёт, владельца и что перестанет работать, если он исчезнет завтра. Звучит базово, но многие команды никогда этого не делали.

Дальше разделите то, с чем взаимодействуют клиенты, и то, чего они никогда не видят. Логин, production-базы данных, API, бэкапы и живой трекинг ошибок — это клиентская сторона. Старые staging-серверы, лишние CI-раннеры, неиспользуемые SaaS-места и дублирующиеся админ-инструменты обычно к ней не относятся. Такое разделение важно. Дешёвый внутренний инструмент часто проще заменить, чем среднебюджетную систему, связанную с оплатой или доступом к аккаунту.

Также полезно разбить стек на несколько групп: приложения, данные, деплой и мониторинг. Когда стек разложен так, пересечения заметить проще. Одна компания может платить за два инструмента для логов, отдельный сервис для доступности и второй сервис сборки, которому никто уже не доверяет. Другая может держать платную staging-базу долго после того, как команда перестала её использовать.

После инвентаря ранжируйте каждый пункт по стоимости, риску и простоте удаления. Начинайте с инструментов, которые стоят дорого, несут низкий риск для клиента и выглядят простыми для замены или отключения. Высокорисковые системы лучше оставить в покое, пока у команды не появится больше данных. Торопливое удаление production-базы может сэкономить деньги на один месяц и создать куда больший счёт позже.

Именно здесь часто помогает внешний взгляд. Например, Oleg Sotnikov работает с более компактными схемами и AI-first-операциями, поэтому такой обзор часто показывает, где один хорошо настроенный инструмент может закрыть работу, которую сегодня выполняют несколько платных продуктов. В итоге у команды должна получиться одна страница, где видно, что остаётся, что нужно протестировать и что уже выглядит лишним.

Сначала уберите зависимости

Удаление серверов до того, как вы уберёте ненужные зависимости, — это как создавать неожиданные сбои. Старые базы данных, тихие очереди и забытые сторонние API часто поддерживают сервис в живом состоянии гораздо дольше, чем все предполагают.

Начните с ответственности. У каждой базы данных, очереди, cron-задачи и внешнего API должен быть один человек, который сможет ответить на простой вопрос: кто этим ещё пользуется и что сломается, если это исчезнет? Если владельца нет, считайте это рискованным даже тогда, когда ежемесячный счёт выглядит небольшим.

Потом проверяйте реальное использование, а не предполагаемое. Посмотрите кодовую базу, файлы деплоя и переменные окружения. Проверьте логи, сетевой трафик и историю задач, чтобы увидеть, какое приложение ещё вызывает каждый сервис. Команды часто находят одного старого worker-а, один billing-скрипт или один админ-инструмент, который всё ещё зависит от системы, которую собирались убрать несколько месяцев назад.

Типичный пример выглядит так: компания хочет снизить облачные расходы без риска, убрав лишний узел базы данных. На бумаге им никто не пользуется. На деле одна retry-задача всё ещё записывает туда неудачные заказы раз в ночь. Уберите узел первым — и ошибка останется скрытой, пока заказы не начнут пропадать.

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

Короткий чек-лист выключения помогает сохранять спокойствие:

  • Назначьте одного владельца зависимости.
  • Подтвердите каждого живого вызывающего по логам или метрикам.
  • Сначала остановите новое использование, а потом удаляйте.
  • Назначьте дату отключения и путь отката.

Путь отката должен быть конкретным. Сохраните свежий снимок, держите старую конфигурацию под рукой и решите, кто сможет восстановить сервис, если удаление создаст проблемы. Дата отключения тоже важна. Без неё команды продолжают платить за «временные» сервисы ещё год.

Почистите путь деплоя

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

Начните с одного прямого вопроса: чем команда реально пользуется каждую неделю? Старые staging-стэки — частая проблема. У компании может быть три тестовых окружения, но перед релизом команда проверяет только одно. Остальные два всё равно каждый день запускают базы данных, хранят файлы и собирают логи.

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

Ручные шаги согласования тоже стоят денег. Если релиз зависит от того, что один человек войдёт в систему, скопирует файлы или вручную проверит сервер, команда часто держит лишнюю мощность онлайн, чтобы ничего не истекло по таймауту, пока все ждут. Лучшая автоматизация не только ускоряет работу. Она позволяет выключать то, чем вы не пользуетесь.

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

Хранилище тоже растёт незаметно. Build-артефакты накапливаются, контейнерные registry хранят каждый образ, а логи остаются навсегда, хотя через несколько дней их уже никто не читает. Сокращение правил хранения может быстро уменьшить расходы, не трогая production-трафик.

Небольшая продуктовая команда может сэкономить реальные деньги скучными изменениями: оставить одно staging-окружение вместо трёх, объединить дублирующиеся задачи в один pipeline, автоматизировать утверждение релиза и удалять образы старше 30 дней. В этом нет ничего драматичного. Это работает потому, что путь деплоя должен быть коротким, понятным и дешёвым в поддержке.

Проверьте мощности, прежде чем что-то уменьшать

Правильно рассчитайте размер мощностей
Тестируйте меньшие узлы на реальном трафике и оставляйте запас на пиковые дни.

Средние значения скрывают моменты, которые ломают системы. Сервис может почти весь день работать на 20% CPU и всё равно упасть, когда запуск продукта, импорт данных или всплеск трафика продержится 15 минут.

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

Измеряйте всю машину, а не один график

CPU — это только часть картины. Давление на память может замедлить приложение задолго до того, как CPU покажется загруженным. Задержки диска могут остановить базу данных даже тогда, когда память выглядит нормально. Ограничения сети могут задушить синхронизацию, бэкапы или доставку изображений.

Сравнивайте всё это на одной временной шкале:

  • загрузку CPU и всплески нагрузки
  • рост потребления памяти, swap и перезапуски
  • дисковый ввод-вывод, задержку и глубину очереди
  • пропускную способность сети, потери и всплески повторных попыток

Если одна метрика выглядит спокойно, а другая почти на пределе, пока не уменьшайте мощности. Сокращения расходов часто проваливаются, потому что команда смотрела на одну панель и не заметила остальное.

Сначала уменьшите один узел

Не меняйте размер всего пула за один шаг. Замените один узел на более маленький инстанс, оставьте остальные без изменений и посмотрите, что произойдёт под реальной нагрузкой. Этот один тест обычно даёт больше пользы, чем неделя предположений.

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

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

Такой right-sizing лучше всего работает, когда он остаётся скучным. Сначала уберите лишнее, тестируйте более маленькие изменения по одному и оставляйте достаточно запаса, чтобы один сюрприз не превратил экономию в сбой.

Простой пример из растущего продукта

У команды SaaS-продукта рост оказался достаточно быстрым, чтобы после него остался запутанный след. После двух спешных запусков у них было три облачных аккаунта, каждый создан в свой момент срочности, и никто не имел чёткой карты того, что ещё важно.

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

Та же проблема была и в деплое. Два отдельных pipeline публиковали одно и то же приложение. Один жил в текущем репозитории, а второй всё ещё запускался из старой схемы, которую никто не хотел трогать, потому что она «всё ещё работала». А это означало двойной набор секретов, двойной объём алертов и больше шансов на неудачный релиз.

Команда начала с прямого вопроса: что сломается, если мы это выключим? Ответ дали логи, недавние проверки доступа и быстрый взгляд на то, кто использовал каждый сервис.

Потом они сокращали расходы небольшими шагами. Неиспользуемый аналитический кластер они пометили на отключение и несколько дней наблюдали за трекингом ошибок. Старый pipeline они поставили на паузу в часы низкого трафика и убедились, что новый обрабатывает каждый деплой. Общие сервисы они перевели в один основной аккаунт, а остальные на короткое время оставили в режиме read-only. Только после этого они проверили CPU, память, глубину очереди и время ответа, прежде чем уменьшать что-либо ещё.

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

Самая безопасная экономия часто приходит от удаления, а не от тонкой настройки. Как только команда убрала простаивающий кластер и закрыла лишний pipeline, ежемесячный счёт снизился без какого-либо удара по пользователям. И только после этого они уменьшили размер инстансов там, где мощностей всё ещё было заметно больше, чем нужно.

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

Ошибки, которые повышают риск

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

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

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

Другая частая ошибка — удалить сервис, потому что кому-то кажется, что им никто не пользуется. На самом деле им часто пользуются. Он может выполнять ночной экспорт, старый шаг биллинга или процесс поддержки, который появляется только в конце месяца. Перед удалением нужно назвать владельца, получить согласование от затронутых людей и записать, как откатываться. Если никто не знает, что делает сервис, это предупреждение, а не разрешение на удаление.

Команды также обжигаются, когда уменьшают production после одной спокойной недели. Трафик меняется быстро. Несколько тихих дней почти ничего не говорят о запуске продукта, импорте клиента или цикле биллинга, который сильно нагружает базу данных. Используйте более длинный период и смотрите на пики, а не только на среднее.

Шум алертов создаёт более медленный и запутанный риск. Когда инженеры каждый день видят одну и ту же ложную страницу, они перестают доверять каналу оповещений. Потом настоящий всплеск CPU, проблема с диском или переполнение очереди проходит мимо, потому что выглядит как очередной фоновой шум. Чистка алертов — скучная работа, но она предотвращает пропущенные инциденты.

Короткая проверка ловит большинство таких проблем:

  • Оставьте бэкапы и проверку восстановления, прежде чем что-то удалять.
  • Получите чёткое одобрение владельца перед удалением сервиса.
  • Рассчитывайте мощности по нескольким неделям пиковых данных, а не по одному спокойному периоду.
  • Уберите шумные алерты, чтобы реальные инциденты были заметны.

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

Быстрые проверки до и после каждого изменения

Проверьте свой облачный стек
Получите CTO-аудит сервисов, деплоев и лишних расходов до того, как что-то сокращать.

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

Перед тем как кто-то уберёт сервис, уменьшит сервер или изменит задачу деплоя, запишите одно простое правило: если что-то пойдёт не так, кто вернёт всё обратно и сколько это займёт времени? Если ответ расплывчатый, изменение ещё не готово.

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

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

Затем делайте изменение достаточно маленьким, чтобы его можно было оценить. Уберите одну группу worker-ов, одну реплику базы данных, один слой кэша или один шаг деплоя за раз. Узкое изменение даёт чистый сигнал.

После изменения снова проверьте те же цифры. Не полагайтесь на интуицию. Посмотрите, сдвинулось ли время ответа, изменился ли уровень ошибок и продолжают ли алерты срабатывать как надо. Если команда использует Grafana, Prometheus, Loki или Sentry, именно здесь эти инструменты показывают свою ценность.

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

Если хотя бы одна из этих проверок не проходит, верните изменение назад и посмотрите ещё раз. Экономить деньги — это хорошо. А вот экономить 8% ценой потери наблюдаемости или хрупких деплоев — обычно плохая сделка.

Следующие шаги

Не проверяйте весь стек сразу. Выберите на этой неделе одну группу сервисов, например фоновые задачи, поиск, staging или внутренние инструменты. Узкий фокус помогает работать спокойно и легче замечать сюрпризы.

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

Достаточно простого чек-листа. Выберите одну группу сервисов. Нанесите на карту, что от неё зависит и что она сама вызывает. Уберите мёртвые шаги деплоя, старые раннеры и дублирующиеся окружения. Зафиксируйте текущий трафик, использование памяти, глубину очереди и уровень ошибок.

Записывайте результат каждого изменения, пока он ещё свежий. Вам нужны три заметки: сколько денег это изменение должно сэкономить в месяц, какой риск ещё остаётся и какая следующая дата отключения. Эта дата важна, потому что старые системы обычно остаются «для безопасности» и продолжают выставлять счёт.

Небольшой пример хорошо показывает порядок. Если staging-окружение работает весь день, но после релизов никто им не пользуется, не уменьшайте его сначала. Проверьте, что ещё от него зависит, уберите старые hooks деплоя, а затем посмотрите, можно ли усыплять его вне рабочего времени или заменить более лёгкой схемой.

Если нужен второй взгляд, Oleg Sotnikov на oleg.is может провести обзор стека как Fractional CTO и показать низкорисковые сокращения. Его работа включает lean cloud architecture, custom CI/CD и практичные способы снизить расходы на инфраструктуру без азартной игры в случайные отключения сервисов.

На этой неделе достаточно одного фокусного аудита. Откройте облачный счёт, выберите одну группу сервисов и поставьте дату отключения в календарь. Небольшие сокращения, сделанные в правильном порядке, лучше большого cleanup-проекта, который никто так и не завершит.

Часто задаваемые вопросы

С чего лучше начать, чтобы безопасно сократить облачные расходы?

Начните с одной группы сервисов, а не со всего стека. Выберите, например, staging, фоновые задачи или внутренние инструменты, а затем запишите инструмент, ежемесячную стоимость, владельца и что сломается, если его убрать. Так вы получите быстрые результаты и не превратите аудит в рискованную зачистку.

Что нужно описать перед тем, как что-то выключать?

Запишите каждый оплачиваемый инструмент, сервер, базу данных, очередь, сторонний API, CI-раннер, бэкап-задачу и SaaS-место. Для каждого пункта назовите владельца и бизнес-эффект, если он исчезнет завтра. Если команда не может ответить на эти два вопроса, пока не отключайте его.

Как понять, что сервис действительно не используется?

Не полагайтесь на память или старые документы. Проверьте кодовую базу, файлы деплоя и переменные окружения, а затем посмотрите логи, трафик и историю задач, чтобы понять, кто ещё обращается к сервису. Если у него нет владельца, считайте его рискованным, пока кто-то не докажет обратное.

Стоит ли уменьшать серверы до удаления старых зависимостей?

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

Что обычно тратит деньги на пути деплоя?

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

Как правильно уменьшить мощности и не вызвать сбой?

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

Какие ошибки делают сокращение расходов рискованным?

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

Как доказать, что изменение действительно сэкономило деньги?

Сначала зафиксируйте текущее время отклика, уровень ошибок, объём трафика и точную строку в счёте, на которую должен повлиять change. После изменений сравните те же показатели и проверьте следующий счёт. Если сумма уменьшилась в другом месте или не изменилась вовсе, команда, скорее всего, сократила не то.

Когда внешний CTO приносит больше всего пользы?

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

Можно ли небольшой команде снизить расходы без большой миграции?

Да. Небольшие работы по чистке часто экономят больше, чем громкий передел. Выведите из эксплуатации неиспользуемый кластер, уберите лишний пайплайн, оставьте одно staging-окружение вместо трёх, сократите срок хранения логов или переводите внутренние системы в сон вне рабочего времени.