Советы по снижению затрат на облачные ресурсы

Как снизить затраты на облако


Август 25, 2022


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

В этой статье мы расскажем, какие ловушки таит в себе облако и как их избежать.

  1. Почему счета за облако такие огромные?
    1. Дефолтные контейнеры — это черные ящики
    2. Недостаточное и чрезмерное использование ресурсов
    3. SLO или SLA? И то, и другое!
  2. Облачный мониторинг или жизнь после деплоя
    1. Метрики Kubernetes
    2. Данные GC
    3. Производительность под нагрузкой
    4. Анализ статистики VM
  3. Заключение
  4. Полезные ссылки
  5. Еще по теме

Почему счета за облако такие огромные?

Часто осознание непомерных трат на облачные сервисы приходит внезапно. Ничто не предвещало беды: приложение продемонстрировало оптимальную пиковую производительность на чистом сервере, проблем с созданием контейнера и его масштабированием не возникло, требования SLA (соглашения об уровне сервиса) выполнены — что могло пойти не так? Всё, что угодно.

Даже не углубляясь в метрики, можно идентифицировать несколько типичных ошибок:

  1. Разработчики не участвуют в процессе оптимизации затрат. Они пишут код, не учитывая особенности среды исполнения. При этом администраторы Yandex Cloud или облачные алгоритмы могут не брать в расчет характеристики приложения или вообще не знают о них.
  2. SLA между поставщиком облачных услуг и компанией помогает обезопасить проект в облаке. Но если SLA составлено без учета наихудших сценариев, или в нем прописаны не все условия, существует риск непредвиденных издержек в экстренных ситуациях2.
  3. Производительность приложения на чистом сервере не равна производительности в кластере при разных нагрузках. Именно поэтому поды неожиданно падают, а HotSpot потребляет гораздо больше памяти на одном и том же инстансе.
  4. Незагруженные сервисы будут потреблять столько же ресурсов, сколько загруженные, если ко всем сервисам применять одинаковую стратегию масштабирования.
  5. Разработчики упаковывают приложения в контейнеры, используя настройки по умолчанию. В результате вы получаете контейнер, не отвечающий требованиям вашего бизнеса, занимающий слишком много места или недостаточно производительный.

Давайте подробнее остановимся на последних двух пунктах.

Дефолтные контейнеры — это черные ящики

Paketo Buildpacks, наиболее популярные билдпаки для контейнеризации, Cloud Native Buildpacks и другие подобные технологии позволяют создавать контейнерные образы прямо в Maven или Gradle. Пара кликов — и вы собрали маленький производительный контейнер. Но разработчики редко конфигурируют контейнеры самостоятельно, предпочитая дефолтные настройки, ведь если автоматически созданный образ нормально работает, зачем утруждаться?

Проблема с решениями «из коробки» в том, что, по сути, это черные ящики: разработчики не всегда знают с точностью, как эти решения работают. В результате контейнеры Paketo с настройками по умолчанию иногда используют память и CPU недостаточно эффективно. Более того, билдпаки пока не собирают контейнеры с российским ПО. Чтобы получить производительные, надежные, безопасные и маленькие контейнеры, нужно конфигурировать их вручную:

  • Начните с настроек JVM и оптимизируйте такие параметры, как
      -XX:+AlwaysActAsServerClassMachine
    

    или

      -XX:+PerfDisableSharedMem
    

    Также следует выбрать подходящий сборщик мусора

  • Протестируйте контейнер. Используйте нагрузочное тестирование, A/B, тестирование долговечности, спланируйте пропускную способность. Результаты тестирования под нагрузкой должны соответствовать варианту «без контейнера»
  • Помните, что у каждого контейнера в поде должен быть установлен лимит используемой памяти и требуемая память
  • При расчете требуемых ресурсов учитывайте размеры узла для правильного планирования его работы
  • Технический оверхед может быть невелик, но учитывайте также оверхед Kubernetes. Например, Fargate использует дополнительные 256 МБ оперативной памяти
  • Для уменьшения размера контейнеров без ущерба безопасности и производительности можно использовать Axiom JDK Lite, оптимизированную для облачных систем, и легковесную Alpine Linux

После развертывания приложения в облаке необходимо выполнять непрерывный мониторинг «здоровья» узлов и подов, ежедневно выполнять нагрузочное тестирование и контролировать метрики: время отклика, пропускную способность, статистику GC и т.д. Более подробное описание мониторинга метрик приведено в разделе «Жизнь после деплоя».

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

Недостаточное и чрезмерное использование ресурсов

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

  • Приложение не работает надлежащим образом, а занимается постоянной сборкой мусора
  • Нужно поднять еще один инстанс, что автоматически удваивает расходы

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

У этих проблем одна причина: установленный лимит памяти не соответствует функционалу приложения.

SLO или SLA? И то, и другое!

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

То же касается и SLO. Если в SLA прописываются обязательства компании перед клиентом, то в SLO (цели уровня обслуживания) указаны цели, которые команда должна достичь для выполнения требований SLA. Цели SLO должны быть четкими, реалистичными и привязанными к SLA. Выберите самые важные метрики, проанализируйте их и обговорите цели вместе с разработчиками. Также не забудьте включить в SLO и SLA наихудшие сценарии.

Облачный мониторинг или жизнь после деплоя

Мы рассмотрели основные ошибки, ведущие к большим затратам на облачные сервисы. Допустим, вы уже развернули в облаке свое приложение, но не уверены, какие показатели нужно анализировать. Где кроется проблема: в JVM, приложении, контейнерах, SLA? Ниже приведены метрики, обеспечивающие вас всеми необходимыми данными для последующей оптимизации.

Метрики Kubernetes

Начните с получения метрик Kubernetes, чтобы иметь представление о том, что происходит в ваших кластерах. Для этого можно использовать опенсорсные инструменты, например, Metrics Server, и различные команды kubectl.

Установите Metrics Server. Возможно, он уже работает в вашем кластере. Проверить это можно с помощью команды

kubectl get pods --all-namespaces | grep metrics-server

Если Metrics Server запущен, вы получите список всех работающих подов. В противном случае для установки последней версии ПО выполните

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

Metrics Server позволяет получать данные о доступных ресурсах: CPU, памяти, хранилище, а также о том, как они используются. kubectl top предоставляет метрики конкретного узла, пода или всех узлов и подов кластера.

Например, выполнив

kubectl top node

вы получите данные об использовании CPU и памяти со всех узлов.

Чтобы получить данные со всех подов:

kubectl top pod

Команда

kubectl top pod --namespace=kube-system –-container

Вернет данные об использовании ресурсов контейнерами в поде.

Команда

kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes/<NODE_NAME> | jq

или

kubectl get --raw /apis/metrics.k8s.io/v1beta1/namespaces/<NAMESPACE>/pods/<POD_NAME> | jq

вернет Metrics API в формате JSON с пода или узла.

Еще один полезный инструмент — kube-state-metrics, возвращающий состояние узлов и подов: статус, емкость, количество реплик на деплой и т.д.

Наконец, можно использовать

kubectl logs

для получения подробной информации о подах и узлах.

Данные GC

Java-приложения управляют используемой памятью с помощью сборщика мусора (GC). Настройка GC может значительно повлиять на производительность. Но для начала нужно понимать, что происходит со сборкой мусора в приложении. С этим помогут логи GC.

Сперва активируйте логи GC:

-Xlog:gc*:<gc.log file path>:time

После этого логи можно собирать с помощью централизованного управления логами или APM-систем. Также можно анализировать отдельные логи. Логи GC генерируются в текстовом формате, их можно обрабатывать с помощью скриптов или десктопных/онлайн инструментов анализа логов GC.

JFR — еще один полезный инструмент мониторинга. Его можно использовать для выявления проблем с памятью или причин Stop-the-World пауз. JFR регистрирует события GC, которые затем обрабатываются с помощью JDK Mission Control или APM. Также можно использовать мониторинг JMX.

Пропускная способность GC — это соотношение времени, затраченного на выполнение бизнес-логики, и общего времени, включающего работу GC и другую сервисную деятельность JVM. Ресурсы CPU используются правильно, если CPU-нагрузка и пропускная способность GC близки к 100%.

Производительность под нагрузкой

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

  • Выполняйте нагрузочное тестирование, чтобы понимать поведение приложения как в нормальных условиях, так и и под пиковой нагрузкой
  • Выполняйте тестирование долговечности для оценки стабильности и устойчивого качества приложения
  • Определите пиковую нагрузку и время отклика. Любая система может неожиданно дать сбой, но необходимо принять профилактические меры для снижения этого риска. Учитывайте, что пиковые нагрузки связаны с высоким потреблением ресурсов
  • Определите требования CPU и оперативной памяти для каждого сервиса
  • Используйте модели сервисов для упрощения тестирования

Анализ статистики VM

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

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

  • Машины
  • JVM
  • Веб-сервера, системы BigData, очереди сообщений и т.д.
  • Приложения

Часто клиентам важно время отклика. Оно измеряется в определенных процентилях (50%, 95%, 99%, 99,99%, 99,9999%). Поэтому его можно изучить под разными углами, например, с точки зрения общего времени выполнения приложения или времени выполнения по достижению пиковой производительности.

Заключение

В этой статье мы рассказали, как получать метрики, помогающие выявить проблемы с потреблением ресурсов в кластере. Самое главное — никакие дефолтные настройки, алгоритмы и инструменты автоматизации не оптимизируют потребление ресурсов в соответствии с вашими требованиями. Для этого нужно самостоятельно конфигурировать контейнеры и JVM.

Полезные ссылки

  1. Факты, тренды и статистика по облачным вычислениям за 2022 год
  2. Молния ударила в ЦОД в Дублине

Еще по теме

Работаете с контейнерами? Узнайте, как избежать побочных эффектов контейнеризации

Хотите уменьшить размер своей ОС? Узнайте, как Linux удается сохранить адекватный функционал при минимальном размере на примере Alpine Linux

Author image

Олег Чирухин

Директор по коммуникациям с разработчиками (DevRel)

Команда Axiom JDK roman.karpov@axiomjdk.ru Команда Axiom JDK logo Axiom Committed to Freedom 199 Obvodnogo Kanala Emb. 190020 St. Petersburg RU +7 812-336-35-67 Команда Axiom JDK 199 Obvodnogo Kanala Emb. 190020 St. Petersburg RU +7 812-336-35-67