Экономим на Kubernetes с помощью OpenCost — и другие прелести FinOps

от автора

Вне зависимости от того, кто вы: небольшой стартап или развитая компания — задача управления затратами особенно важна. Модное понятие FinOps, оно же Financial Operations или Cloud Financial Operations, помогает организациям наиболее эффективно и экономически выгодно использовать облачные ресурсы.

Но как FinOps работает на практике? В этой статье рассмотрим один из способов применения этого подхода в управлении кластерами. Познакомимся с инструментом OpenCost и обсудим его работу в Kubernetes. Подробности под катом!

Используйте навигацию, если не хотите читать текст полностью:

Зачем FinOps в Kubernetes
Как применить FinOps? Знакомство с OpenCost
Установка OpenCost в Managed Kubernetes
OpenCost на практике: тестирование с нагрузкой
Что нужно учитывать

Зачем FinOps в Kubernetes


FinOps помогает привязать вычислительные мощности к деньгам и учитывать стоимость IT-инфраструктуры в бюджете проекта. Мониторинг позволяет получить детальную аналитику потребления, чтобы проводить бюджетирование, основываясь на реальных цифрах.

Одна из наиболее популярных сред развертывания Kubernetes — облако. Например, у нас в Selectel есть сервис управления кластерами Managed Kubernetes. Клиенты могут использовать отказоустойчивые и автомасштабируемые кластеры в облачной платформе. При этом — создавать их в фиксированной или произвольной конфигурации с разными типами групп нод, платить только за услугу и используемые ресурсы облака.

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

В этом выражена мотивация внедрения FinOps. Но то, насколько она сильна, — зависит от команды и зрелости процессов. Можно выделить две основные цели, которые ставят перед собой организации.

  • Прогнозирование и подсчет расхода текущих ресурсов. Это помогает понимать и контролировать затраты на облачные услуги.
  • Создание культуры принятия экономически обоснованных решений. Подход включает в себя понимание затрат и их влияния на бизнес-модель. На основании этой информации компании могут принимать более взвешенные решения.

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


Как применить FinOps? Знакомство с OpenCost


С излишними тратами на инфраструктуру часто сталкиваются при масштабировании кластеров Kubernetes. Наладить ситуацию вот уже с 2021 года пытаются разработчики kubecost. Они разрабатывают разные решения, в том числе OpenCost — «инспектор» для мониторинга контейнеров с открытым исходным кодом.

Интерфейс OpenCost, дашборд потребления ресурсов.

Каждый желающий может сделать вклад в проект, например написать интеграцию со своим облачным провайдером. Сегодня OpenCost нативно работает с AWS, Azure и GCP, то есть может автоматически подгружать и рассчитывать стоимость ресурсов данных облаков. Однако можно также подключить таблицы с ценами для кластеров Kubernetes у собственного провайдера и использовать OpenCost в его «экосистеме».

Ниже — параметры расценки ресурсов, которые предлагают использовать разработчики при работе с облаками без интеграции:

{     "provider": "custom",     "description": "Default prices based on GCP us-central1",     "CPU": "0.031611",     "spotCPU": "0.006655",     "RAM": "0.004237",     "spotRAM": "0.000892",     "GPU": "0.95",     "storage": "0.00005479452",     "zoneNetworkEgress": "0.01",     "regionNetworkEgress": "0.01",     "internetNetworkEgress": "0.12" } 

Набор параметров может отличаться для облака, в котором вы разворачиваете OpenCost. Например, в Managed Kubernetes от Selectel нет zoneNetworkEgress и regionNetworkEgress, а spotCPU и spotRAM пока не актуальны, наша команда разработки занимается вопросом их поддержки.

Впрочем, это не все нюансы, которые стоит учитывать для более точного расчета ресурсов. Разберемся на практике: посмотрим, как развернуть OpenCost на базе кластера Managed Kubernetes в облачной платформе Selectel.

Установка OpenCost в Managed Kubernetes


В целом, инструмент можно развернуть в любом кластере, начиная с Kubernetes 1.8. Сегодня в облаке Selectel доступны все актуальные версии. Выбрать можно любую — для примера развернем свежий Kubernetes 1.29: Mandala.

Создание кластера Managed Kubernetes

Кластер можно легко создать с помощью нашего Terraform-провайдера. Но мы покажем на примере панели управления.

Новость для тех, кто давно не пользовался Managed Kubernetes. Мы упростили создание кластеров. Разбили форму на три простых шага: выбор конфигурации кластера, добавление групп нод и настройка автоматизации.

1. Перейдем в панель управления, откроем раздел Облачная платформа → Kubernetes и настроим кластер.

Панель управления. Первый этап создания кластера, настройка.

2. Следующим этапом настроим группы нод:

В параметрах OpenCost для каждого ресурса можно указать только один тип. Если вы используете один тип дисков или GPU, проблем не будет — можно указать стоимость, инспектор ее «съест» и примет в расчет. Но если вы используете два разных диска или GPU, OpenCost не сможет точно посчитать потребление. Это нужно учитывать при выборе конфигурации кластера.

3. Далее настроим процессы автоматизации: автовосстановление и автообновление — и нажмем кнопку Создать.

Готово — спустя пару минут кластер будет создан. Теперь к нему можно подключиться, установить Helm и OpenCost.

Установка и настройка OpenCost

1. Установим Prometheus — он нужен для сбора данных о потреблении ресурсов. Для этого инструмента нужно указать Storage Class или объявить значение по умолчанию.

kubectl get sc 

В выводе будет название существующего Storage Class. В нашем случае оно такое:

NAME         PROVISIONER                RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE fast.ru-2c   cinder.csi.openstack.org   Delete          Immediate           true                   15m 

Используйте данное имя, чтобы задать Storage Class по умолчанию.

kubectl patch storageclass fast.ru-2c -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' 

Установите Prometheus в репозиторий и загрузите его.

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts &&\   helm repo update 

helm install my-prometheus --repo https://prometheus-community.github.io/helm-charts prometheus \   --namespace prometheus --create-namespace \   --set prometheus-pushgateway.enabled=false \   --set alertmanager.enabled=false \   -f https://raw.githubusercontent.com/opencost/opencost/develop/kubernetes/prometheus/extraScrapeConfigs.yaml 

Если имя my-prometheus, порт или namespace поменяются, не забудьте заменить значения в values.yaml, описанном в п.4.

2. Добавим репозиторий opencost-charts в Helm.

helm repo add opencost-charts https://opencost.github.io/opencost-helm-chart &&\ helm repo update 

3*. Если планируете публиковать дашборды с потреблением ресурсов в интернет, создайте Ingress Controller и укажите необходимый хост файла values.yaml в п.4.

 ingress:       enabled: true       ingressClassName: ""       annotations: {}       hosts:         - host: opencost.example.com           paths:             - /       servicePort: http-ui       tls: [] 

opencost.example.com — имя вашего домена со значением А-записи облачного балансировщика, который использует Ingress Controller.

4. Создадим файл values.yaml для OpenCost со следующим содержимым:

networkPolicies:   enabled: false   prometheus:     namespace: prometheus     port: 9090     labels:       app.kubernetes.io/name: prometheus updateStrategy:   rollingUpdate:     maxSurge: 1     maxUnavailable: 1   type: RollingUpdate service:   enabled: true   annotations: {}   labels: {}   type: ClusterIP   extraPorts: [] rbac:   enabled: true opencost:   cloudIntegrationSecret: ""   exporter:     apiPort: 9003     cloudProviderApiKey: ""     defaultClusterId: 'default-cluster'     image:       registry: quay.io       repository: kubecost1/kubecost-cost-model       tag: ""       pullPolicy: IfNotPresent       fullImageName: null     extraArgs: []     replicas: 1     resources:       requests:         cpu: '10m'         memory: '55Mi'       limits:         cpu: '999m'         memory: '1Gi'     livenessProbe:       enabled: true       path: /healthz       initialDelaySeconds: 120       periodSeconds: 10       failureThreshold: 3     readinessProbe:       enabled: true       path: /healthz       initialDelaySeconds: 120       periodSeconds: 10       failureThreshold: 3     securityContext: {}     extraVolumeMounts: []     env: []     extraEnv: {}   customPricing:     enabled: false     configmapName: custom-pricing-model     configPath: /tmp/custom-config     createConfigmap: true     provider: custom     costModel:       description: Modified pricing configuration.       CPU: 0.9       spotCPU: 0       RAM: 0.33       spotRAM: 0       GPU: 38.4       storage: 0.05       zoneNetworkEgress: 0       regionNetworkEgress: 0       internetNetworkEgress: 0.52   dataRetention:     dailyResolutionDays: 15   cloudCost:     enabled: true     refreshRateHours: 6     runWindowDays: 3     monthToDateInterval: 6     queryWindowDays: 7   prometheus:     internal:       enabled: true       serviceName: my-prometheus-server       namespaceName: prometheus       port: 80   ui:     enabled: true     image:       registry: quay.io       repository: kubecost1/opencost-ui       tag: ""       pullPolicy: IfNotPresent       fullImageName: null     resources:       requests:         cpu: '10m'         memory: '55Mi'       limits:         cpu: '999m'         memory: '1Gi'     uiPort: 9090     livenessProbe:       enabled: true       path: /healthz       initialDelaySeconds: 30       periodSeconds: 10       failureThreshold: 3     readinessProbe:       enabled: true       path: /healthz       initialDelaySeconds: 30       periodSeconds: 10       failureThreshold: 3     ingress:       enabled: true       ingressClassName: "nginx"       annotations: {}       hosts:         - host: opencost.example.com           paths:             - /       servicePort: http-ui       tls: []   extraContainers: [] extraVolumes: [] 

Полный список возможных параметров доступен по ссылке.

5. Установим OpenCost через менеджер пакетов Helm с использованием конфигурации values.yaml.

helm install opencost opencost-charts/opencost --namespace opencost --create-namespace -f values.yaml 

6. Подождите, пока поды OpenCost перейдут в состояние Ready. Статус можно проверить с помощью команды:

kubectl get pods -n opencost -w 

7. Выполняем запрос к веб-странице по нашему домену — например, opencost.example.com — в браузере. На этом этапе вы должны увидеть интерфейс инспектора.

Примечания

1. Если необходимо обезопасить доступ к данным, в поле extraContainers конфигурации values.yaml можно добавить дополнительный контейнер, который будет проксировать запросы на сервер авторизации. Пример доступен по ссылке.

2. По умолчанию валюта выбирается в долларах (USD), но ее можно изменить в правом верхнем углу на RUB. Или использовать специальную ссылку, чтобы потребление сразу отображалось в рублях. Вот так:

http://opencost.example.com/?currency=RUB 

3. Стоимость ресурсов кластера задается в customPricing.costModel конфигурации values.yaml. В нашем примере указаны цены для быстрого SSD и Tesla T4. Стоимость ресурсов облачной платформы Selectel указана в рублях для пула ru-2. Значения также можно задать через ConfigMap с ценами ресурсов и указание его в values.yaml. О том, как это сделать, написано в документации.

OpenCost на практике: тестирование с нагрузкой


Попробуем проверить, как поведет себя OpenCost, если на кластер оказать дополнительную нагрузку.

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

Дашборд OpenCost до оказания нагрузки.

Окажем небольшую нагрузку на тестовое веб-приложение в соседнем пространстве имен (web-test-app) и посмотрим, как OpenCost оценит эффективность загрузки ресурсов.

Получились следующие результаты по запущенным процессам и потреблению вычислительных ресурсов:

Дашборд OpenCost после оказания нагрузки. Примечание: кластер был под непрерывной нагрузкой целые сутки.

Метрики можно частично проверить в выводе kubectl top pod -A. Видим, что пространство имен web-test-app действительно забирает большую часть по CPU в кластере:

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

Оптимизация потребления ресурсов

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

Подберите оптимальную конфигурацию

Обсудим на примере видеокарт. Для начальных задач необязательно брать самые топовые видеокарты. Та же GTX 1080 до сих пор актуальна в задачах инференса — наравне с T4 и A2000. CUDA-ядер меньше, но зато они все используются вашим кластером, а вы — не переплачиваете.

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

Сократите потребление сети

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

Эти вопросы особенно актуальны, если вы работаете с большими объемами данных, например дата-сетами, и постоянно их скачиваете или загружаете в облако. На этом процессе можно не только сэкономить бюджет, но и время, настроив кэширование данных в кластере. В облаке Selectel предоставляются 3 ТБ внешнего трафика бесплатно, но если его больше, то такая аналитика может быть особенно полезна.

Освобождайте неиспользуемые ресурсы

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

С такой проблемой столкнулись и мы, когда настраивали тестирование микросервисов на базе OpenStack. О том, как нам удалось утилизировать остаточные ресурсы, рассказали в отдельной статье.

Что нужно учитывать


В нашем случае OpenCost хорошо подходит для оценки эффективности потребления ресурсов в кластере, но не более. Почему так? Давайте разбираться.

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

  • OpenCost не учитывает стоимость балансировщика, Managed Kubernetes как услуги, дисков самих воркер-нод и публичных IP-адресов. Это связано с тем, что они являются сущностями облачной платформы, а не кластера, в котором развернут инспектор. Этот вопрос могла бы легко решить полная интеграция OpenCost с API облака Selectel.
  • OpenCost считает стоимость балансировщика через стоимость пройденного через него трафика, что неверно, так как она фиксирована. То есть, если взять проект облачной платформы, в котором нет ничего кроме кластера, все равно не получится посчитать полную сумму за потребление. Опять же, это решается интеграцией с нашим API.

Проще говоря, широкий выбор конфигураций в Managed Kubernetes — это как преимущество, так и некий «ограничивающий фактор» для OpenCost, когда он пытается посчитать потребление ресурсов.

Потребление платформы в панели управления.

Разумеется, все расходы можно посмотреть в панели управления, в том числе — потребление ресурсов нодами кластера. Однако инструменты вроде OpenCost отлично дополняют статистику и помогают анализировать расходы на уровне отдельных процессов, запущенных в кластере.

Какими инструментами FinOps пользуетесь вы? Поделитесь своим опытом в комментариях!


ссылка на оригинал статьи https://habr.com/ru/articles/795659/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *