Русский
Русский
English
Статистика
Реклама

Автомасштабирование

Как устроен Kubernetes as a Service на платформе Mail.ru Cloud Solutions

28.10.2020 14:12:50 | Автор: admin

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

Я Дмитрий Лазаренко, директор по продуктам облачной платформы Mail.ru Cloud Solutions (MCS). Сегодня я расскажу, что под капотом у нашего Kubernetes aaS, как обеспечивается его надёжность и какие у него есть интересные функциональности, которыми любят пользоваться наши клиенты. Это автомасштабирование, интеграция с другими PaaS нашей платформы и многое другое.

Главные фичи Kubernetes на платформе MCS


Наш Kubernetes aaS включает:

  • Интерфейс управления для создания кластера в несколько кликов, масштабирования и настройки.
  • Автоматическое масштабирование узлов кластера в большую или меньшую сторону, то есть добавление или удаление нод (Cluster Autoscaler).
  • Встроенный мониторинг на основе Prometheus Operator и Grafana. Многие наши пользователи начинают с базовых инсталляций, где запускается приложение. Когда оно выходит в продуктив, это позволяет им мониторить сервисы и сам кластер.
  • Свой Terraform-провайдер для Kubernetes. Он полностью поддерживает API MCS.
  • Интеграция с Docker Registry для хранения и управления образами.
  • Автоматизированное развёртывание федеративных кластеров Kubernetes на базе AWS и Mail.ru Cloud Solutions (о чём мы писали тут).
  • Возможность сделать Start/Stop для кластера целиком экономия для тестовых сред. Вы можете выключить кластер одним кликом в интерфейсе и платить только за диски в случае остановленных кластеров.
  • Поддержка создания Node Pools, пулов виртуальных машин разных размеров: можно запускать тяжелые задачи на больших машинах, веб-приложения на маленьких. Масштабировать группы можно независимо и размещать их в разных регионах либо зонах доступности (для большей надежности и доступности).
  • Persistent Volumes интегрированы с системой хранения OpenStack.
  • Поддержка приватных кластеров, доступных только через VPN-соединение.
  • Поддерживается Cluster Policy: Local, которая позволяет получать реальные IP пользователей внутри кластеров.
  • Создание и масштабирование кластеров Kubernetes с помощью UI или API MCS, управление сущностями через Kubernetes dashboard и kubectl.
  • Плавное обновление (rolling update) в один клик без простоя как для минорных, так и для мажорных версий. Обновления кластеров до 1.16.
  • На момент написания статьи мы поддерживаем Kubernetes вплоть до версии 1.17.




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

Дальнейшее развитие сервиса:

  • CI/CD aaS, интегрированный с Kubernetes и другими сервисами платформы: дополнительные сервисы, которые обеспечивают CI/CD, на базе наших собственных доработок OpenStack.
  • Логирование aaS для приложений приложений, которые работают в нашем Kubernetes. Логирование будет реализовано на базе нескольких решений OpenStack.
  • Service mesh: у нас появятся плагины для Kubernetes, которые в рамках реализации service mesh будут выполнять шифрование, бэкапирование и другие функции.

Сертификация дистрибутива в Cloud Native Computing Foundation


Mail.ru Cloud Solutions входит в CNCF (Cloud Native Computing Foundation). Дистрибутив Kubernetes от MCS получил сертификат Certified Kubernetes Hosted. Его проверили на надежность и соответствие стандартам, он отвечает всем функциональным требованиям сообщества и совместим со стандартным Kubernetes API. MCS пока единственный в России облачный провайдер, получивший такую сертификацию.

Место Kubernetes в инфраструктуре облачной платформы


Самый нижний слой типовые физические серверы (compute nodes). Сейчас их несколько тысяч, они используются под вычисления и хранение. Для хранения мы предоставляем файловые и блочные хранилища на базе Ceph и S3-совместимые объектные хранилища. Серверы распределены по дата-центрам, между которыми проложена сеть 40 Gbps.

Поверх уровня серверов работает OpenStack, который обеспечивает виртуализацию для пользовательских окружений. А уже поверх виртуальных машин, сетей и балансировщиков работают PaaS-решения: Kubernetes, базы данных, DWH на базе ClickHouse, Hadoop, Spark и другие.

Аналогичную схему мы строим и в приватных инсталляциях Kubernetes как сервиса в дата-центрах наших заказчиков в формате частного облака.



Архитектура облачной платформы

Интеграция Kubernetes с облаком не односторонняя. Kubernetes не просто развертывается на виртуальных машинах, он полностью интегрируется с IaaS OpenStack.

На основе провайдера Cloud Provider OpenStack мы сделали Cloud Provider для MCS, который в рамках вашего проекта (тенанта) OpenStack соединяется с API MCS и создает, конфигурирует, удаляет диски, балансеры, внешние IP-адреса, подключает их к нодам Kubernetes, конфигурирует security-группы (фактически виртуальный firewall). Без Cloud Provider создание тех же Persistent Volumes головная боль для всех, кто запускает Kubernetes on-premise, на железе либо просто в облаке.



Интеграция Kubernetes с IaaS OpenStack

Какие инструменты мы используем


  1. Операционная система. Сначала мы использовали CoreOS, которая работает на хостах, сейчас у нас Fedora Atomic (1.14-1.15) и CentOS (1.16).
  2. Сеть Calico. Сети Kubernetes зависят от облачной сети, которая обеспечивается SDN всего облака. В основе нашей SDN изначально был OpenStack Neutron. Но год назад мы начали разработку модуля Sprut нашего собственного SDN-решения, которое поддерживает API Neutron, но работает по другим принципам. Подход Sprut решил наши проблемы масштабируемости, возникающие из-за десятков тысяч сетевых сущностей (портов) у нас в облаке, когда при падении сетевых нод в сети такого размера начинался процесс полной синхронизации (fullsync). Сейчас Sprut мы задействуем для тех клиентов, для которых в силу особенностей нагрузки на сеть использовать его целесообразнее, чем Calico, в перспективе мы его откроем для всех.
  3. Кластерный DNS на базе CoreDNS, со всеми его Service Discovery, метриками Prometheus и другими стандартными фичами.
  4. Ingress Controller. Сейчас это Nginx, но мы также планируем добавить Envoy, как дополнительный Ingress Controller. Наши тесты показывают, что Envoy часто быстрее. Ingress Controller интегрирован с облачным балансировщиком нагрузки на базе OpenStack Octavia и поддерживает Proxy Protocol.
  5. Мониторинг на базе Prometheus Operator. Раньше использовали просто Prometheus, но сейчас все хотят автоматизацию и сервис-мониторы, поэтому мы уже несколько месяцев предлагаем Prometheus Operator + Grafana, в рамках которой можно добавлять сервис-мониторы и выполнять мониторинг кластеров.
  6. Аддоны (опциональные расширения). В один клик можно установить Docker registry, интегрированный с нашим S3-хранилищем, ingress controller, различные системы мониторинга (Heapster, Prometheus).

Multi Master и сетевая топология


Kubernetes от Mail.ru поддерживает деплой в формате Multi Master, при этом каждая пользовательская группа нод уже находится в конкретной зоне доступности.


Multi Master в облаке

В Multi Master etcd работает в кластерном режиме, так что если что-то случается с одним из мастеров, другие продолжают работать. Под каждый etcd выделен отдельный SSD-диск, что обеспечивает хороший latency и быструю работу API-сервера, т.к. в etcd находится служебная информация о всех ресурсах кластера Kubernetes.

Для доступа извне используется балансировщик нагрузки API сервера Kubernetes, который имеет внешний IP-адрес. При этом все ноды и мастера, и миньоны находятся в приватной сети (фактически в виртуальном частном облаке) и не имеют публичных адресов.

Доступ к кластеру Kubernetes из публичной сети: запуск трафика и балансировка нагрузки


В общем случае способы доступа к сервисам внутри кластера перечислены здесь. Подробности нашей реализации:

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

Load Balancer. Наш Kubernetes интегрирован с облачной платформой MCS, так что платформа предоставляет Load Balancer как сервис и может сама создавать балансировщики. Для сравнения, если пользователь настраивает Kubernetes (например, в он премисе), нужно самостоятельно поднимать и настраивать софтверные балансеры. На платформе MCS балансировщики поднимаются сразу в отказоустойчивом режиме active-standby. Когда поднимается основной балансер (на HAProxy), у него всегда есть standby, спящий балансер. Между ними настроен VRRP. Если основной балансер отказывает, весь трафик мгновенно переключается на standby, при этом IP-адрес не меняется.



Отказоустойчивый Load Balancer как сервис на платформе MCS. Kubernetes создаёт nodeport на каждой ноде и балансировщик

В настройке балансировки для Kubernetes помогает наш Cloud Provider. Нужно создать манифест, в котором пользователь указывает тип манифеста сервис и тип сервиса Load Balancer. После деплоя этого манифеста Kubernetes (точнее, Cloud Provider, который работает в Kubernetes) обращается к OpenStack API, создаёт балансировщик и внешний IP-адрес, если это необходимо. Если внешний адрес не нужен, нужно поставить аннотацию, что требуется внутренний балансировщик, и можно пускать трафик на кластер, не открывая публичный IP-адрес на каждой ноде.

apiVersion: v1kind: Servicemetadata:name: nginxlabels:  k8s-app: nginx-backend annotations:  service.beta.kubernetes.io/openstack-internal-load-balancer:"true"spec: type: LoadBalancer externalTrafficPolicy: Cluster selector:  k8-app: nginx-backend ports: -port: 80  name: http  targetPort: http -port: 443  name: https  targetPort: httpn

Сервисный манифест для создания балансировщика нагрузки с помощью Cloud Provider

Не всегда удобно создавать по балансеру на каждый сервис, 10 сервисов есть 10 балансировщиков, 50 сервисов 50 балансировщиков. Ими потом также приходится управлять, это тяжелые сущности. Эту проблему решает Ingress.

Ingress. Чтобы можно было не создавать много балансировщиков, мы добавили поддержку Ingress Controller. Ingress Controller интегрирован с балансировщиком OpenStack. То есть в декларации сервиса конкретного Ingress Controller указан тип Load Balancer. Для кластера создается один балансировщик, по которому Ingress Controller работает и дальше распределяет трафик по сервисам. Ingress Controller балансирует по DNS-именам.



Схема работы Ingress

Для некоторых клиентов было важно, чтобы в подах было видно IP-адреса клиентов, получающих доступ в кластер. При балансировке теряются заголовки IP-пакетов: приложение не получает реальный IP-адрес клиента. Балансировщик OpenStack ещё видит заголовок X-Forwarded-For, но Ingress Controller и под его уже не получают. Это не позволяет настроить доступ пользователей по White Lists, не работают сервисы типа GeoIP или anti-DDoS, которым нужно видеть реальные IP-адреса клиентов.



IP-адрес клиента не доходит до пода

И здесь у нас оказалось два решения:

Сделать режим proxy-протокола как в Amazon. Ради этой возможности мы перешли на балансировщик OpenStack Octavia, так как в стандартном балансировщике OpenStack нет такой опции. В итоге мы сделали новый балансировщик, который поддерживал как TCP-балансировку, так и HTTP с терминацией SSL.

При этом поддержку proxy-протокола нужно включать как на самом балансировщике (HAproxy), так и на Nginx Ingress Controller, который выступает таким приемником. Иначе схема пропускания трафика ломается. Также важно, что SSL-терминация, если у вас стандартный веб-трафик, должна проходить на Ingress:



Терминация SSL на балансировщике. Здесь на балансер приходит HTTPS, он расшифровывается, и в кластер идет HTTP. Если всё это сделать и активировать в сервисе ExternalTrafficPolicy: Local, вы будете видеть заголовки IP-пакетов:



Storage и Kubernetes


Если разворачивать Kubernetes локально или в облаке просто на виртуальных машинах, то по умолчанию в нем нет нормальной работы с постоянными дисками. Можно использовать Host Path, Local volume (no-provisioner), либо прямо в кластере Kubernetes разворачивать экзотические программно-определяемые системы хранения типа Linstor или OpenEBS. Но что произойдет с данными или очередью данных, которая размещается в кластере, если умрет нода или под?

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

Мы используем Ceph. Главное, что они работают через OpenStack, который предоставляет специальные модули, абстрагирующие Kubernetes (или любые виртуальные машины, работающие в облаке), на конкретных драйверах OpenStack Cinder.

У нас несколько разных storage-классов, которые работают в Kubernetes: SSD Ceph, HDD Ceph, геораспределенные Ceph между нашими ЦОДами. Есть storage-класс, отвечающий за блочные диски: фактически это дисковые шкафы с SSD, они подключаются к хост-машинам по iSCSI.



Несколько Storage-классов в MCS

При необходимости мы используем NFS, когда клиенты не могут переписать приложения в микросервисную архитектуру. У нас есть аналог сервиса EFS от Amazon файловое хранилище с NFS-протоколом, доступное как сервис. Оно подходит, если у вас legacy-приложение, которое вы переводите в Kubernetes.

Кроме того, у нас есть локальные SSD, но здесь сложно гарантировать их доступность и переезд данных, поскольку они доступны только с физических серверов, к которым подключены.

Всё это подключается через единый модуль OpenStack OpenStack Cinder, к каждой ноде Kubernetes и обеспечивает возможность переезда стораджа в случае падения ноды. А также когда повышается нагрузка чтения/записи и Kubernetes решает перевозить неважные поды на другие ноды тогда он автоматически переводит монтирование этого диска к другим Kubernetes-нодам.



Так происходит автоматическое перемонтирование

Можно использовать storage class, написав декларации PersistentVolumeClaim. На примере, который изображён ниже, Cloud Provider выделит в заданной зоне доступности новый Persistent Volume, размером 30 ГБ с типом диска SSD, подключит его к ноде и примонтирует к подам. Также он будет следить, чтобы этот диск переезжал между нодами в случае переезда подов:

kind: PersistentVolumeClaimapiVersion: v1metadata: name: nginx-pvc-ssdspec: accessModes: -ReadWriteOnce storageClassName: dp1-ssdresources: requests:  storage: 30Gi


Автоматическое масштабирование


В MCS есть Cluster Autoscaler. Это не просто автоскейлинг подов внутри кластера, а автоскейлинг самого кластера по необходимости: новые ноды добавляются, когда нагрузка выросла, и удаляются, если нагрузка упала. Масштабирование происходит автоматически до 100 узлов и обратно за несколько минут.

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

Cluster Autoscaler лучше настраивать совместно с Horizontal Pod Autoscaler. Различие использования двух вариантов Autoscaler:

  • Cluster Autoscaler позволяет расширять сами выделенные для кластера ресурсы. По сути он может автоматически арендовать дополнительные ресурсы или сократить их использование через Cloud Provider.
  • Horizontal Pod Autoscaler позволяет расширять ресурсы подов в рамках существующих выделенных ресурсов кластера, чтобы оптимально их использовать.




Настройка автоскейлинга

Функциональности


Совместимость со стандартными инструментами Kubernetes


Так как наш Kubernetes aaS полностью совместим со стандартным Kubernetes API, вы можете свободно пользоваться всеми возможностями экосистемы Kubernetes.

  • Хранение и обработка serverless-функций в контейнерах: OpenFaaS, OpenWhisk, Kubeless.
  • Инструменты Service Mesh: Istio, Consul, Linkerd.
  • Мониторинг, аналитика, логирование: Prometheus, Fluentd, Jaeger, OpenTracing.
  • CI/CD: Gitlab, CircleCI, Travis CI.
  • IaC (описание приложений): Terraform, Helm.

И многие другие инструменты.

Про Terraform отдельно стоит сказать, что стандартный провайдер OpenStack не был полностью совместим с API платформы MCS, так что мы сделали собственный Terraform-провайдер, который полностью совместим с последней версией API MCS. Поддержка API включает:

  • листинг ресурсов MCS (cluster, cluster template, node group)
  • поддержку managed node groups
  • поддержку действий через API: создание/удаление, горизонтальное и вертикальное масштабирование, включение/выключение кластера, обновление версии.


Безопасность


  • Kubernetes использует аутентификацию по сертификатам.
  • Систему безопасности кластеров можно интегрировать с LDAP/Active Directory для аутентификации пользователей. При этом ролевую модель безопасности в Kubernetes можно настроить на проверку прав доступа на основе принадлежности пользователя к группам в LDAP-каталоге.
  • Для сетевой безопасности можно применять Calico Network Policy.
  • В наш Kubernetes aaS интегрирован Docker Registry, защищённый SSL.
  • Планируем реализовать SSO (single sign-on) в интеграции с нашим IAM (identity and access management) на уровне OpenStack.

Резервное копирование и миграция


  • Мы поддерживаем интеграцию с Velero. Velero выполняет резервное копирование, которое позволяет бэкапить манифесты etcd и Persistent Volumes, вот гайд по тому, как это сделать.
  • Также с помощью Velero можно мигрировать кластеры on-premises и других провайдеров на наш Kubernetes.
  • Или запросите миграцию на наш Kubernetes под ключ. Поможем.

Работа с большими данными


Kubernetes по сути можно использовать для любых микросервисных приложений, работающих с данными. Чем Kubernetes на платформе MCS интересен для data scientistов:

  • Автомасштабирование позволяет выдерживать большие вычислительные нагрузки.
  • Можно создавать событийные (event-triggered) обработчики данных.
  • Приложения на Kubernetes легко интегрировать с другими нашими PaaS для Big Data, машинного обучения, в рамках одной сети.
  • Если хочется поэкспериментировать, то для ускорения обучения к очереди событий или событийному обработчику на базе Kubernetes можно напрямую подключить GPU.

Ещё о нашем Kubernetes aaS


  1. Попробовать бесплатно наш Kubernetes aaS можно тут.
  2. В этих двух Telegram-каналах вас ждут новости нашего Kubernetes aaS и анонсы мероприятий @Kubernetes meetup.
Подробнее..

Перевод Вертикальное автомасштабирование podов в Kubernetes полное руководство

16.02.2021 10:21:44 | Автор: admin

Прим перев.: месяц назад Povilas Versockas, CNCF Ambassador и software engineer из Литвы, написал очень подробную статью о том, как работает и как использовать VPA в Kubernetes. Рады поделиться её переводом для русскоязычной аудитории!

Это полное руководство по вертикальному автомасштабированию pod'ов (Vertical Pod Autoscaling, VPA) в Kubernetes. Вот его краткое содержание:

  • Зачем нам VPA?

  • Модель ресурсных требований Kubernetes;

  • Что такое вертикальное автомасштабирование pod'ов?

  • Работа с рекомендациями;

  • Когда использовать VPA?

  • Ограничения VPA;

  • Реальные примеры использования;

  • Как работает VPA?

  • Модель рекомендаций VPA;

  • Дополнительная информация.

Схема работы Kubernetes VPA от Banzai CloudСхема работы Kubernetes VPA от Banzai Cloud

Что ж, давайте приступим.

Зачем нам VPA?

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

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

Кроме того, со временем модель использования приложения может меняться. Некоторым приложениям потребуется больше CPU и памяти. У других, менее популярных, требования к ресурсам, наоборот, снизятся.

  • С недостатком заявленных ресурсов обычно разбираются DevOps- или SRE-инженеры при поступлении соответствующих оповещений. SRE-инженеры видят, что приложение отбрасывает запросы конечных пользователей из-за убийств pod'ов, вызванных ошибкой Out-of-Memory, или оно начинает медленно работать из-за троттлинга процессора.

  • С другой стороны, избыток заявленных ресурсов не приводит к проблемам сразу, но вносит свой вклад в масштабный перерасход ресурсов. В результате команда по обслуживанию инфраструктуры/платформы вынуждена добавлять новые K8s-узлы, хотя реальная потребность в ресурсах невелика.

Решением этих проблем и занимается автомасштабирование. Горизонтальное масштабирование определяет оптимальное число реплик для приложения. Например, у вас может быть завышено количество pod'ов, что приводит к ненужному расходованию ресурсов.

В свою очередь, вертикальное масштабирование определяет оптимальные требования к CPU и памяти. В этой статье пойдет речь исключительно о вертикальном автомасштабировании pod'ов.

Но сначала давайте поговорим о модели ресурсных требований Kubernetes.

Модель ресурсных требований Kubernetes

Kubernetes требует от пользователей указывать заявки на ресурсы с помощью resource requests (запросов на ресурсы) и resource limits (лимитов на ресурсы). Давайте начнем с запросов:

Запросы на ресурсы резервируют некоторое количество ресурсов за приложением. Можно определять запросы для контейнеров в pod'е. Планировщик использует эту информацию, чтобы определить, куда разместить pod. Запросы можно представить как некоторый минимальный объем ресурсов, который требуется pod'у для нормальной работы.

Тут важно отметить, что приложение может задействовать больше ресурсов, если узел располагает свободными мощностями. А максимальный объем ресурсов, которыми может воспользоваться контейнер, устанавливается в лимитах. Если потребление памяти окажется больше указанного предела, pod будет убит. Если контейнер использует больше процессорной мощности, чем позволяет лимит, начинается троттлинг.

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

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

Кроме того, если вы не определите запросы, Kubernetes автоматически приравняет их к лимитам pod'а.

Многие ограничиваются заданием запросов на ресурсы, и это распространенная ошибка. Пользователи надеются, что в этом случае приложение будет располагать неограниченными ресурсами и ему не придется иметь дело с нехваткой памяти или троттлингом. Однако Kubernetes этого не допустит. Поэтому обязательно задавайте как запросы на ресурсы (resource requests), так и лимиты (limits).

Более того, эту ресурсную модель можно расширить. Могут быть и другие вычислительные ресурсы, такие как эфемерное хранилище, GPU, huge pages в Linux.

В статье же мы ограничимся процессорными мощностями и памятью, поскольку на данный момент Vertical Pod Autoscaler работает только с ними. Тем, кто желает узнать больше, рекомендую обратиться к соответствующему разделу документации Kubernetes (Managing Resources for Containers).

Что такое вертикальное автомасштабирование pod'ов?

Как следует из названия, вертикальное автомасштабирование pod'ов (VPA) позволяет автоматически устанавливать запросы на ресурсы и лимиты для контейнеров. Решения принимаются на основе прошлых данных об использовании CPU и памяти.

Основная цель VPA уменьшить потери ресурсов и минимизировать риск снижения производительности из-за троттлинга CPU или ошибок, вызванных убийством pod'ов из-за Out Of Memory.

Поддержкой VPA занимаются инженеры Google. Система называется Autopilot и основана на опыте создания соответствующей внутренней системы для оркестратора контейнеров Borg. Результаты Google от использования Autopilot в production следующие:

На практике избыток ресурсов для заданий под управлением Autopilot составил всего 23% по сравнению с 46% для заданий, управляемых вручную. Кроме того, Autopilot на порядок сократил количество заданий, пострадавших от OOM.

Autopilot: workload autoscaling at Google

Дополнительную информацию можно почерпнуть из самой публикации (Autopilot: workload autoscaling at Google).

VPA вводит несколько Custom Resource Definitions (CRD) для управления поведением автоматических рекомендаций. Как правило, разработчикам требуется добавить объект VerticalPodAutoscaler в свои deploymentы.

Давайте разберемся, как его использовать.

Как использовать VPA?

Ресурс VPA предоставляют массу возможностей для управления рекомендациями. Чтобы получить лучшее представление об использовании VPA, посмотрим на сам объект VerticalPodAutoscaler:

apiVersion: autoscaling.k8s.io/v1kind: VerticalPodAutoscalermetadata:  name: prometheus-vpaspec:  targetRef:    apiVersion: "apps/v1"    kind: StatefulSet    name: prometheus  updatePolicy:     updateMode: "Recreate"    containerPolicies:      - containerName: "*"        minAllowed:          cpu: 0m          memory: 0Mi        maxAllowed:          cpu: 1          memory: 500Mi        controlledResources: ["cpu", "memory"]        controlledValues: RequestsAndLimits

Настройка VerticalPodAutoscaler начинается с задания targetRef, указывающего на некий контроллер-объект Kubernetes, отвечающий за управление pod'ами.

VPA поддерживает все распространенные типы контроллеров: Deployment, StatefulSet, DaemonSet, CronJobs. Он также должен работать с любыми кастомными типами, реализующими подресурс scale. VPA получает набор pod'ов с помощью метода контроллера ScaleStatus. В примере выше мы автомасштабируем StatefulSet с именем prometheus.

Поле updateMode позволяет выбрать режим работы контроллера. Есть несколько вариантов:

  • Off VPA не будет автоматически изменять ресурсные требования. Autoscaler подсчитывает рекомендации и хранит их в поле status объекта VPA;

  • Initial VPA устанавливает запросы на ресурсы только при создании pod'а и не меняет их потом;

  • Recreate VPA устанавливает запросы на ресурсы при создании pod'ов и обновляет их для существующих pod'ов, вытесняя (evict) в случаях, когда запрашиваемые ресурсы значительно отличаются от новой рекомендации;

  • Auto в настоящее время делает то же самое, что и Recreate. В будущем возможно использование обновлений без перезапуска (restart-free updates), когда этот механизм станет доступен (подробнее о нем рассказывается, например, в этом видео прим. перев.).

Далее для каждого контейнера в pod'е нужно определить resourcePolicy. Эти политики позволяют выбрать контейнеры, для которых будут приводиться рекомендации по ресурсам, и задать способ, которым это будет осуществляться.

Вы определяете список resource policies, которые фильтруются по containerName. Можно выбрать конкретный контейнер в pod'е и сопоставить его с некой resource policy. Также можно указать * в качестве значения containerName этим вы определите resource policy по умолчанию (на случай, если ни одна другая resource policy не соответствует containerName).

Resource policies позволяют ограничить ресурсные рекомендации диапазоном, лежащем между minAllowed и maxAllowed. В случае, если minAllowed и maxAllowed не заданы, ресурсы не ограничены.

С помощью controlledResources можно выбрать ресурсы для рекомендаций. Пока поддерживаются только CPU и память. Если типы ресурсов не указаны, то VPA будет давать рекомендации как по использованию процессора, так и по использованию памяти.

Наконец, controlledValues позволяет выбрать, какие параметры будут контролироваться: RequestsOnly (только запросы на ресурсы) или RequestsAndLimits (запросы на ресурсы и лимиты). Значение по умолчанию RequestsAndLimits.

Если выбрать RequestsAndLimits, то запросы будут вычисляться на основе фактического использования. Тем временем, лимиты будут вычисляться на основе текущего соотношения между запросами и лимитами pod'а. Например, если pod изначально запрашивает 1 CPU, а его лимит установлен на 2 CPU, то VPA будет устанавливать лимит таким образом, чтобы тот всегда в два раза превышал запрос. Аналогичный способ расчета применяется и к памяти. Поэтому в режиме RequestsAndLimits рассматривайте изначально заданные для приложения запросы на ресурсы и лимиты как некий шаблон.

Объект VPA можно упростить, используя режим Auto и вычисляя рекомендации для CPU и памяти. А именно:

apiVersion: autoscaling.k8s.io/v1kind: VerticalPodAutoscalermetadata:  name: vpa-recommenderspec:  targetRef:    apiVersion: "apps/v1"    kind: Deployment    name: vpa-recommender  updatePolicy:     updateMode: "Auto"  resourcePolicy:    containerPolicies:      - containerName: "*"        controlledResources: ["cpu", "memory"]

Теперь давайте посмотрим на рекомендации, которые VPA записывает в поле status соответствующего CRD.

Работа с рекомендациями

Как только вы примените (apply) объект VeritcalPodAutoscaler, VPA начнет собирать данные об использовании ресурсов и вычислять рекомендации по ним. Спустя некоторое время в поле status объекта VerticalPodAutoscaler должны появиться рекомендации.

Просмотреть их можно с помощью:

kubectl describe vpa NAME

Давайте проанализируем пример отчета о состоянии:

Status:   Conditions:    Last Transition Time:  2020-12-23T08:03:07Z    Status:                True    Type:                  RecommendationProvided  Recommendation:      Container Recommendations:      Container Name:  prometheus      Lower Bound:          Cpu:     25m          Memory:  380220488      Target:          Cpu:     410m          Memory:  380258472      Uncapped Target:          Cpu:     410m          Memory:  380258472      Upper Bound:          Cpu:     704m          Memory:  464927423

Как видно, для контейнера prometheus предлагаются четыре различные оценки. При этом оценки объема памяти приводятся в байтах. Оценки CPU в миллиядрах (m, millicores). Давайте разберемся, что означают эти оценки:

  • Lower bound (нижняя граница) минимальная оценка для контейнера. Это значение не гарантирует, что приложение сможет стабильно работать. Такие минимальные запросы на CPU и память, скорее всего, окажут значительное влияние на производительность и доступность.

  • Upper bound (верхняя граница) это максимальный рекомендованный объем ресурсов для контейнера. Запросы выше этих значений, скорее всего, будут приводить к тому, что ресурсы будут расходоваться впустую.

  • Оценку Target (цель) мы будем использовать для задания запросов на ресурсы.

Все эти оценки ограничены значениями minAllowed / maxAllowed в containerPolicies.

  • Uncapped target (неограниченная цель) это целевая оценка, которая получилась бы, если бы ограничения minAllowed и maxAllowed не были заданы.

Зачем нам четыре оценки? Vertical Pod Autoscaler использует Lower и Upper bound для вытеснения (eviction) pod'ов. Если текущий resource request ниже, чем lower bound, или выше, чем upper bound, и происходит 10%-ное изменение ресурсных запросов по сравнению с target-оценкой, то может произойти вытеснение.

Классно то, что VPA добавляет аннотации к pod'у при изменении требований к ресурсам. Если сделать describe pod'а, контролируемого VPA, то можно увидеть аннотации вроде vpaObservedContainers (перечисление отслеживаемых контейнеров) или vpaUpdates (описание предпринятых действий). Также здесь можно увидеть, ограничена ли рекомендация параметрами minAllowed/maxAllowed или Kubernetes-объектом LimitRange. Вот пример аннотаций pod'а:

apiVersion: v1kind: Podmetadata:  annotations:    vpaObservedContainers: recommender    vpaUpdates: 'Pod resources updated by vpa-recommender: container 0: cpu request, memory request, cpu limit, memory limit' 

Давайте разберемся, в каких случаях следует использовать Vertical Pod Autoscaler.

Когда использовать VPA?

Во-первых, можно добавить VPA к базам данных и stateful-нагрузкам при их запуске в Kubernetes. Как правило, stateful-нагрузки тяжелее поддаются горизонтальному масштабированию, поэтому автоматический способ, позволяющий отмасштабировать потребляемые ресурсы или точно оценить потребность в них, помогает решить многие проблемы с недостатком мощностей. Если база данных не настроена как высокодоступная или не готова к перерывам в работе, можно включить режимы Initial или Off. В этом режиме VPA не будет вытеснять pod'ы и ограничится рекомендациями запросов или их обновлением при перевыкате приложения.

Во-вторых, VPA хорошо подходит для CronJobs. Vertical Pod Autoscaler способен проанализировать потребление ресурсов повторяющимися заданиями и применить рекомендации, полученные на основе этих данных, к очередному запланированному запуску. Для этого нужно установить режим рекомендаций в Initial. В таком случае каждое только что запущенное задание будет получать рекомендации, подсчитанные на основе прошлого запуска того же задания. Важно отметить, что это не работает для кратковременных (менее 1 минуты) заданий.

В-третьих, stateless-нагрузки отличный кандидат для Vertical Pod Autoscaling. Stateless-приложения обычно менее чувствительны к перерывам в работе и вытеснению, так что это отличный кандидат для старта. На них можно протестировать режимы Auto и Recreate. Одно существенное ограничение состоит в том, что VPA не будет работать совместно с горизонтальным автомасштабированием, если оно производится по тем же самым метрикам: CPU или памяти. Как правило, VPA используют с приложениями с предсказуемым потреблением ресурсов, а также в том случае, если запуск более чем нескольких реплик не имеет смысла. Подобный тип приложений не имеет смысла масштабировать горизонтально, и для них VPA правильный выбор.

Важно знать, что на данный момент VPA имеет некоторые ограничения, из-за которых его не всегда хорошо использовать.

Ограничения VPA

  1. Прежде всего, не используйте VPA с рабочими нагрузками на базе JVM. Дело в том, что JVM не позволяет установить объем фактически используемой памяти, поэтому рекомендации могут сильно отклоняться от адекватных значений.

  2. Также не стоит использовать VPA совместно с горизонтальным автомасштабированием (HPA), основанном на тех же метриках (CPU или памяти). В то же время два этих типа можно применять совместно, если HPA работает с кастомными метриками.

  3. Рекомендации VPA могут превысить доступные ресурсы, такие как ресурсы кластера или квота вашей команды. Недостаток ресурсов может привести к тому, что pod'ы окажутся в состоянии Pending. С помощью объектов LimitRange можно ограничивать запросы ресурсов для конкретного пространства имен. Также можно устанавливать максимальные допустимые рекомендации по ресурсам для pod'а в объекте VerticalPodAutoscaler.

  4. VPA в режиме Auto или Recreate не будет выселять pod'ы с единственной репликой, так как это приведет к простою в работе. Однако желающие включить автоматические рекомендации для приложений с единственной репликой могут изменить такое поведение. Для этого в компоненте updater имеется флаг --min-replicas.

  5. При работе в режиме RequestsAndLimits устанавливайте первичные лимиты для CPU таким образом, чтобы они многократно превышали request'ы. Связано это с известной проблемой Kubernetes/ядра Linux, которая в некоторых случаях может приводить к излишнему троттлингу (ситуация подробно разобрана в этой статье прим. перев.). Многие пользователи Kubernetes либо полностью отключают троттлинг, либо устанавливают огромные лимиты CPU, чтобы обойти проблему. Как правило, это не приводит к плохим последствиям, поскольку использование CPU на узлах кластера обычно невелико.

  6. Не все рекомендации VPA достигают своей цели. Предположим, что у вас имеется высокодоступная система из двух реплик, и один из контейнеров решает быстро нарастить объем используемой памяти. Такое стремительное увеличение потребляемой памяти может привести к тому, что контейнер будет убит из-за Out of Memory. Поскольку pod'ы, убитые Out Of Memory, не планируются заново, VPA не сможет применить новые рекомендации для ресурсов. Вытеснение pod'а также не произойдет, поскольку один pod всегда либо Not Ready, либо попал в crash loop. То есть вы оказались в тупике. Единственный способ разрешить эти ситуации убить pod и позволить новым рекомендациям вступить в силу.

Теперь давайте рассмотрим несколько примеров из реальной жизни.

Реальные примеры использования

Кластер MongoDB

Давайте начнем с кластера MongoDB, состоящего из трех реплик. Первоначальные требования StatefulSet'а к ресурсам таковы:

resources:  limits:    memory: 10Gi  requests:    memory: 6Gi

Pod Disruption Budget допускает отключение только одной реплики.

Далее мы разворачиваем StatefulSet без Vertical Pod Autoscaling и даем ему поработать некоторое время.

На этом графике показано использование памяти кластером MongoDB. Каждая из линий соответствует отдельной реплике. Видно, что фактическое использование памяти для двух реплик близко к 3 Гб, а для одной около 1,5 Гб.

Спустя некоторое время мы включаем автоматизацию ресурсных требований, устанавливая объект Vertical Pod Autoscaler в режим Auto (автоматическое масштабирование ресурсов CPU и памяти). VPA рассчитывает рекомендацию и последовательно выселяет pod'ы. Вот как может выглядеть рекомендация:

Container Recommendations:   Container Name:  mongodb  Lower Bound:    Cpu:     12m    Memory:  3480839981  Target:    Cpu:     12m    Memory:  3666791614  Uncapped Target:    Cpu:     12m    Memory:  3666791614  Upper Bound:    Cpu:     12m    Memory:  3872270071

VPA установил запросы на память на 3,41 Гб, лимит на 5,6 Гб (такое же отношение, как у 6 Гб и 10 Гб), запросы и лимиты для CPU на 12 миллиядер.

Давайте посмотрим, как это соотносится с первоначальными оценками. Мы запросили на 1,6 Гб меньше памяти на каждый pod. Таким образом, в общей сложности мы сэкономили 4,8 Гб памяти. Разница может показаться не особо существенной, но в случае большого числа кластеров MongoDB объем сэкономленной памяти стремительно возрастает.

etcd

Другой пример etcd. Это высокодоступная база данных, использующая Raft в качестве алгоритма выбора лидера. Первоначально запрашиваются только ресурсы CPU:

limits:  cpu: 7requests:  cpu: 10m

Далее мы разворачиваем StatefulSet без Vertical Pod Autoscaling и даем ему поработать некоторое время:

На графике показано использование памяти кластером etcd. Каждая из линий соответствует отдельной реплике. Как видно, одна реплика использует около 500 Мб, две другие по 300 Мб.

А этот график показывает использование CPU. Видно, что оно относительно постоянно и равно 0,03 ядра процессора.

Вот как выглядит рекомендация VPA:

Recommendation:    Container Recommendations:      Container Name:  etcd      Lower Bound:        Cpu:     25m        Memory:  587748019      Target:        Cpu:     93m        Memory:  628694953      Uncapped Target:        Cpu:     93m        Memory:  628694953      Upper Bound:        Cpu:     114m        Memory:  659017860

VPA запросил 599 Мб памяти (без лимитов) и 93 миллиядра CPU (0.093 ядра) с лимитом в 65 ядер (придерживаясь первоначально установленного соотношения запрос/лимит 1 к 700).

Таким образом, VPA зарезервировал предостаточно ресурсов для полноценной работы etcd. Изначально мы не запрашивали память для данного pod'а, что может привести к его планированию на слишком загруженный узел и вызвать проблемы. Аналогичным образом, запрошенные ресурсы CPU оказались недостаточны для работы etcd.

В нашем случае интересным открытием стало то, что текущий лидер использует значительно больше памяти, чем остальные реплики. Как видно, VPA рекомендовал одинаковый объем памяти всем репликам. Таким образом, существует разрыв между запрошенным и используемым объемом памяти. Поскольку вторичные узлы не будут использовать более 300 Мб памяти, пока не станут первичными, на каждом из этих узлов будут оставаться невостребованные ресурсы.

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

Резервирование с CronJob

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

Изначально запросы на ресурсы установлены не были. Объект VPA установлен в режим Initial, автомасштабируются память и CPU.

Первая пара запусков прошла без запросов на ресурсы: VPA собирал данные об их использовании. В это время VPA выводил ошибку No pods match this VPA object. Для третьего запуска VPA предложил следующие рекомендации:

Recommendation:    Container Recommendations:      Container Name:  backupjob      Lower Bound:        Cpu:     25m        Memory:  262144k      Target:        Cpu:     25m        Memory:  262144k      Uncapped Target:        Cpu:     25m        Memory:  262144k      Upper Bound:        Cpu:     507m        Memory:  530622257

И при очередном запуске задания был создан pod с запросами на 25m CPU и 262144k памяти. Главный плюс всего этого в том, что поскольку VPA работает в режиме Initial, никаких вытеснений или перебоев в работе не происходит.

Теперь давайте разберемся, как работает Vertical Pod Autoscaling.

Как работает VPA?

Vertical Pod Autoscaler состоит из трех различных компонентов:

  • Recommender использует некоторые эвристики для подсчета рекомендаций;

  • Updater отвечает за вытеснение pod'ов в случае, когда происходит значительное изменение ресурсных требований;

  • Компонент Admission Controller задает ресурсные требования pod'а.

Теоретически любой из компонентов можно заменить кастомным. И все должно по-прежнему работать. Давайте рассмотрим компоненты подробнее:

Recommender

Recommender содержит основную логику для оценки требующихся ресурсов. Он отслеживает их фактическое потребление и события out-of-memory, выдает рекомендации для запросов на ресурсы CPU и памяти для контейнеров. Текущие рекомендации хранятся в поле status объекта VerticalPodAutoscaler.

Можно выбрать, как именно Recommender будет получать начальную статистику по использованию CPU и памяти. Он поддерживает контрольные точки (checkpoints; установлены по умолчанию) и Prometheus. Изменить это можно с помощью флага --storage.

Контрольные точки хранят агрегированные метрики для CPU и памяти в CRD-объектах VerticalPodAutoscalerCheckpoint. Просмотреть сохраненные значения можно с помощью describe. Recommender поддерживает контрольные точки на основе сигналов, поступающих в реальном времени, которые он начинает собирать после загрузки исторических метрик.

При работе с Prometheus Recommender выполняет запрос на PromQL, в котором используются метрики cAdvisor. Recommender позволяет настроить лейблы, используемые в запросе. Можно менять пространство имен, имена pod'ов/контейнеров, лейблы имен заданий Prometheus. В общем, он будет посылать запросы, похожие на этот:

rate(container_cpu_usage_seconds_total{job="kubernetes-cadvisor"}[8d]

и на этот:

container_memory_working_set_bytes{job="kubernetes-cadvisor"}

Результатом таких запросов станет информация об использовании CPU и памяти. Recommender проанализирует результаты и будет использовать их для рекомендаций ресурсов.

После загрузки исторических метрик он начнет в реальном времени собирать метрики с API-сервера Kubernetes через Metrics API (аналогично команде kubectl top). Кроме того, он будет следить за событиями Out Of Memory, чтобы сразу адаптироваться к таким ситуациям. Далее VPA подсчитывает рекомендации, сохраняет их в объекты VPA и отслеживает контрольные точки. Интервал опроса можно настроить с помощью флага --recommender-interval.

О том, как VPA подсчитывает рекомендации, рассказано в следующем разделе (Модель рекомендаций VPA).

Updater

Updater отвечает за соответствие ресурсных требований pod'ов рекомендациям. Если VerticalPodAutoscaler работает в режиме Recreate или Auto, Updater может вытеснить pod, чтобы пересоздать его с новыми ресурсами. В будущем режим Auto скорее всего воспользуется преимуществами обновлений на месте (in-place updates), что позволит избежать вытеснения. Впрочем, работа над этой функцией пока не завершена. За ходом работ можно последить в этом issue на GitHub.

При этом в Updater встроен ряд защитных механизмов, ограничивающих вытеснение pod'ов:

  • Он не будет вытеснять pod, у которого нет по крайней мере двух реплик. Изменить такое поведение можно с помощью флага --min-replicas.

  • Поскольку используется API Kubernetes для вытеснения, Updater соблюдает Pod Disruption Budgets. PDB позволяют задать требования к доступности, чтобы предотвратить вытеснение слишком большого числа pod'ов. Например, если установить максимальное число недоступных (max unavailable) pod'ов равным единице, то компонент сможет вытеснять только один pod. Подробнее о PDB здесь.

  • По умолчанию вытесняется не более 50% pod'ов одного ReplicaSet. Даже если PDB не используются, Updater все равно будет вытеснять pod'ы медленно. Изменить это можно с помощью флага --eviction-tolerance.

  • Также можно настроить глобальный ограничитель скорости вытеснения с помощью флагов --eviction-rate-limit и --eviction-rate-burst. По умолчанию они отключены.

Updater принимает решение о вытеснении podов на основе нижней и верхней границ. Он вытеснит pod, если запрос на ресурсы меньше нижней границы или больше верхней, а также присутствует значительное изменение запросов на ресурсы по сравнений с целевой оценкой. В настоящее время пороговая разница составляет 10%.

После вытеснения pod'а в игру вступает последний компонент Admission Controller. Он отвечает за создание pod'а и применение рекомендаций.

Admission Controller

Компонент Admission Controller задает ресурсные требования pod'а.

Перед планированием pod'а Admission Controller получает webhook-запрос от API-сервера Kubernetes на обновление спецификации pod'а. Admission Controller делает это через конфигурацию mutating webhookа (подробнее в документации к Kubernetes Admission Control). Просмотреть mutating webhookи можно с помощью следующей команды:

kubectl get mutatingwebhookconfigurations

Если VPA установлен правильным образом, вы увидите конфигурацию mutating webhookа для Admission Controller'а VPA.

Как только Admission Controller получает запрос, он сопоставляет его с объектом VerticalPodAutoscaler. Если они не совпадают, pod остается без изменений. Если pod соответствует объекту VPA, Admission Controller (в зависимости от настроек объекта VPA) может обновить или только запросы на ресурсы pod'а, или запросы вместе с лимитами. Обратите внимание, что изменения в ресурсные требования pod'а не будут вноситься, если режим обновления установлен в Off.

Давайте теперь разберемся, как VPA рекомендует ресурсы.

Модель рекомендаций VPA для CPU

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

Для подсчета рекомендации для CPU мы создаем гистограмму с экспоненциально растущими границами интервалов. Первый интервал начинается от 0,01 ядра (1 миллиядра) и заканчивается примерно на 1000 ядрах CPU. Каждый интервал растет экспоненциально со скоростью 5%.

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

Когда запрос на CPU увеличивается, растет и вес интервала. Это свойство делает предыдущие наблюдения менее значимыми, что помогает быстро реагировать на троттлинг процессора.

Кроме того, мы уменьшаем вес со временем (по умолчанию период его полураспада равен 24 часам). Таким образом, при добавлении в гистограмму данных, с получения которых прошли сутки, их вес составит половину от запрошенных контейнером ресурсов в то время. Подобный распад позволяет увеличить значимость более поздних выборок (то есть они оказывают большее влияние на предсказания, нежели ранние данные). Период полураспада можно изменить с помощью флага --cpu-histogram-decay-half-life.

Давайте превратим график использования CPU, приведенный выше, в подобную гистограмму (с экспоненциальным ростом интервалов и данными, взвешенными с учетом распада). Предположим, что в течение всех 48 часов запрос на мощности CPU составляет 1 ядро.

Гистограмма будет выглядеть следующим образом:

Примечание: мы построили график только для первых 36 интервалов, поскольку остальные интервалы пусты. Значения интервалов варьируются в диапазоне от 0 до 0,958 ядра CPU (округленно). 37-й интервал имеет значение 1,016. Поскольку наш график никогда не достигает этого значения, он пуст.Примечание: мы построили график только для первых 36 интервалов, поскольку остальные интервалы пусты. Значения интервалов варьируются в диапазоне от 0 до 0,958 ядра CPU (округленно). 37-й интервал имеет значение 1,016. Поскольку наш график никогда не достигает этого значения, он пуст.

Далее VPA подсчитывает три различных оценки: target (цель), lower bound (нижняя граница), upper bound (верхняя граница). Мы используем 90-й процентиль для цели, 50-й процентиль для нижней границы и 95-й процентиль для верхней.

Давайте подсчитаем значения для примера, приведенного на первом рисунке:

Нижняя граница

0,5467

Цель

1,0163

Верхняя граница

1,0163

Примечание: красная линия показывает, где проходит нижняя граница; зеленая линия показывает на местоположение цели и верхней границы. В нашем примере два последних значения оказались одинаковыми.Примечание: красная линия показывает, где проходит нижняя граница; зеленая линия показывает на местоположение цели и верхней границы. В нашем примере два последних значения оказались одинаковыми.

После подсчета к начальным границам прибавляется некоторых резерв, чтобы оставить контейнеру пространство для маневра, если тот, например, внезапно решит съесть больше ресурсов, чем раньше. VPA добавляет некоторую долю от рассчитанной рекомендации. По умолчанию она равна 15%. Скорректировать ее можно с помощью флага --recommendation-margin-fraction.

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

оценка = оценка * (1 + 1/продолжительность сбора данных в днях)

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

5 минут

289

1 час

25,4

1 день

2

2 дня

1,5

1 неделя

1,14

1 неделя и 1 день

1,125

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

Аналогичным образом нижнюю границу мы умножаем на доверительный интервал. Однако в этот раз формула немного другая:

оценка = оценка * (1 + 0.001/продолжительность сбора данных в днях)^-2

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

5 минут

0,6

1 час

0,9537

1 день

0,9980

2 дня

0,0990

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

Далее VPA проверяет, превысили ли оценки некоторое минимальное пороговое значение. Если нет, VPA установит их на минимум. В настоящее время минимум для CPU равен 25 миллиядрам, но его можно изменить с помощью флага --pod-recommendation-min-cpu-millicores.

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

Нижняя граница

0,626

Цель

1,168

Верхняя граница

1,752

Окончательные оценкиОкончательные оценки

Наконец, VPA масштабирует границы таким образом, чтобы вписаться в диапазон minAllowed/maxAllowed, заданный в объекте VerticalPodAutoscaler. Кроме того, если pod находится в пространстве имен с настроенным LimitRange, рекомендация корректируется в соответствии с его правилами.

Модель рекомендаций VPA для памяти

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

Обратите внимание, что на графике показано использование памяти за семь дней. Более длительный интервал в данном случае имеет принципиальное значение, поскольку оценка требуемой памяти начинается с вычисления пикового значения для каждого интервала. Используется пиковое значение, а не все распределение, поскольку обычно стараются выделить объем памяти, близкий к пиковому потреблению: ведь ее недостаток приведет к прекращению задач по OOM. В то же время алгоритм выделения CPU-мощностей не так чувствителен к данной проблеме, поскольку при недостатке ресурсов pod'ы сталкиваются с троттлингом, а не убиваются.

По умолчанию интервал агрегации равен 24 часам. Его можно изменить с помощью флага --memory-aggregation-interval. Кроме того, мы сохраняем только восемь интервалов (этот параметр можно изменить с помощью --memory-aggregation-interval-count). Таким образом, у нас имеется информация о пиковом спросе на память за 8 * 24 часа = 8 суток.

Давайте посмотрим, как эти пиковые агрегации выглядят в нашем примере:

Агрегация пиковых нагрузок на памятьАгрегация пиковых нагрузок на память

Кроме того, если в течение этого времени возникает событие Out Of Memory, мы анализируем использование памяти данным pod'ом, берем максимальное значение и прибавляем к нему 20% или 100 Мб (в зависимости от того, что больше). Этот метод позволяет VPA быстро адаптироваться к OOM-инцидентам.

После того, как пиковые значения установлены, их можно свести в гистограмму. VPA создает гистограмму с экспоненциально растущими границами интервалов. Первый интервал начинается с 10 Мб и заканчивается примерно на 1 Тб. Каждый интервал растет экспоненциально со скоростью 5%.

Как и в случае CPU, вес данных уменьшается со временем (по умолчанию его период полураспада равен 24 часам). Если добавить новые данные в гистограмму, которым 24 часа, их вес будет равен 0,5. Подобный распад позволяет увеличить значимость более поздних выборок (то есть они оказывают большее влияние на предсказания, нежели ранние данные). Период полураспада можно скорректировать с помощью флага --memory-histogram-decay-half-life.

Давайте посмотрим, как выглядит гистограмма для пиковых значений из нашего примера:

Примечание: мы построили график только для интервалов с 16 по 38, поскольку остальные интервалы пусты. Значения интервалов варьируются от 225,62 Мб до 969,20 Мб (округленно). Значение 39-го интервала составляет 1088,10. Он пуст, так как наш график никогда не достигает этого значения.Примечание: мы построили график только для интервалов с 16 по 38, поскольку остальные интервалы пусты. Значения интервалов варьируются от 225,62 Мб до 969,20 Мб (округленно). Значение 39-го интервала составляет 1088,10. Он пуст, так как наш график никогда не достигает этого значения.

Далее VPA подсчитывает три различных оценки: target (цель), lower bound (нижняя граница), upper bound (верхняя граница). Мы использует 90-й процентиль для цели, 50-й процентиль для нижней границы и 95-й процентиль для верхней.

В нашем примере все три оценки одинаковы: 1027,2 Мб.

Оценки после вычисления 50-го, 90-го и 95-го процентиляОценки после вычисления 50-го, 90-го и 95-го процентиля

После подсчета к начальным границам добавляется некоторых резерв, чтобы оставить контейнеру пространство для маневра. Если, например, он внезапно решит съесть больше ресурсов, чем раньше. VPA добавляет некоторую долю от рассчитанной рекомендации. По умолчанию она равна 15%. Скорректировать ее можно с помощью флага --recommendation-margin-fraction.

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

Далее VPA проверяет, превысили ли оценки некоторое минимальное пороговое значение. Если нет, VPA установит их на минимум. В настоящее время минимальный объем памяти составляет 250 Мб. Его можно изменить с помощью флага --pod-recommendation-min-memory-mb.

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

Нижняя граница

1237422043 байт = 1,15 Гб

Цель

1238659775 байт = 1,15 Гб

Верхняя граница

1857989662 байт = 1,73 Гб

Обратите внимание, что зеленая линия это верхняя граница, красная нижняя. Цель не видна, так как она близка к красной линии (разница между ними составляет всего 1,18 Мб)

Наконец, VPA масштабирует границы таким образом, чтобы вписаться в диапазон minAllowed/maxAllowed, заданный в объекте VerticalPodAutoscaler. Кроме того, если pod находится в пространстве имен с настроенным LimitRange, рекомендация корректируется в соответствии с его правилами.

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

P.S. от переводчика

Читайте также в нашем блоге:

Подробнее..

Перевод Google признала сложность Kubernetes, поэтому разработала режим Автопилот

26.02.2021 18:20:16 | Автор: admin

Новый режим GKE более дорогой и менее гибкий, но зато проще и безопаснее



Автопилот в GKE управляет подами за вас

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

Чтобы упростить развёртывание и управление кластерами, компания представила всем клиентам GKE доступ к сервису Автопилот, который Google уже давно использует в собственных кластерах Borg. Это автоматическая конфигурация ресурсов на основе машинного обучения.

Несмотря на 6 лет прогресса, Kubernetes по-прежнему невероятно сложен, сказал Дрю Брэдсток (Drew Bradstock), руководитель продукта Google Kubernetes Engine (GKE), в интервью The Register. В последние годы мы видели, что многие компании принимают Kubernetes, но затем сталкиваются с трудностями.

GKE это платформа Kubernetes, которая работает в основном на Google Cloud Platform (GCP). Она также доступна и на других облаках или локально как часть Anthos.

Автопилот новый режим работы GKE, он более автоматизирован и предварительно настроен для сокращения операционных затрат на управление кластерами, оптимизации кластеров для продакшна и высокой доступности.


Использование Автопилота в собственной инфраструктуре Google, источник

В Kubernetes есть понятия кластеров (набор физических или виртуальных серверов), узлов (отдельные серверы), подов (блок управления, представляющий один или несколько контейнеров на узле) и самих контейнеров. GKE полностью управляется на уровне кластера. Автопилот распространяет это на узлы и поды.

Проще всего понять особенности и ограничения Автопилота из описания системы. Обратите внимание на предварительно настроенные параметры (pre-configured), которые нельзя изменить.

Сравнение режимов Autopilot и Standard

По сути, это ещё один способ резервирования и управления ресурсами GKE, который жертвует гибкостью ради удобства. Поскольку Google управляет большей частью конфигурации, то для подов Автопилота с распределением по многим зонам она гарантирует более высокий аптайм 99,9% (см. SLA).

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

Другое ограничение Автопилота предустановленная операционная система Linux с Containerd, оптимизированная для контейнеров. Нет возможности использовать Linux с Docker или Windows Server. Максимальное количество подов на узел 32, а не 110, как на стандартном GKE.

SSH-доступ к узлам отсутствует, узлы Автопилота заблокированы. Поддержка GPU и TPU (Tensor Processing Unit) недоступна, хотя и запланирована на будущее. Отказ от SSH был сложным решением, говорит Брэдсток. Конечно, это ограничивает возможности управления. Но Брэдсток сказал, что такое решение было принято по результатам исследований, показавших большой уровень критических ошибок в конфигурировании кластеров.

Деньги


Модель ценообразования здесь тоже отличается. Плату берут не за вычислительные инстансы (виртуальные машины), а за реальное использование CPU, памяти и хранилища всеми подами. Плюс $0,10 в час за каждый кластер на Автопилоте, как в стандартном GKE.

Очевидный вопрос: что будет дороже, стандартный кластер или Автопилот. Ответить непросто. Поскольку это в каком-то смысле премиальный сервис, Автопилот обойдётся дороже, чем тщательно оптимизированное стандартное развертывание GKE. Существует премия по сравнению с обычным GKE, сказал Брэдсток, потому что мы обеспечиваем не только функциональность, но полную поддержку SRE (Site Reliability Engineering) и гарантии SLA.

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


Интегральная функция распределения (CDF) неиспользуемой памяти и занятых машин для 5000 задач после включения Автопилота в собственной инфраструктуре Google, источник


Снижение ошибок памяти (OOM) и доли неиспользуемой памяти для 500 задач после включения Автопилота в инфраструктуре Google, источник

Почему просто не использовать Cloud Run, который запускает рабочие нагрузки контейнеров без какой-либо конфигурации кластеров, узлов и подов, даже на GKE? Cloud Run отличная среда для разработчиков, одно приложение может раскрутиться с нуля до 1000 инстансов и обратно опуститься до нуля, для того и созданы облака, объясняет Брэдсток. Автопилот облегчает жизнь людям, которые хотят использовать именно Kubernetes, хотят всё видеть и держать под контролем, хотят использовать сторонние скрипты, хотят построить свою собственную платформу.

Определённой проблемой является совместимость с существующими надстройками сторонними инструментами для Kubernetes. Некоторые из них пока не совместимы с Автопилотом, но другие уже работают, такие как мониторинг Datadog. Также поддерживается DaemonSets эту функцию для запуска демонов на всех узлах используют многие инструменты.

Конфигурация хранилища, вычислений и сети вынудила отказаться от некоторого уровня гибкости и некоторых интеграций: Но мы определённо хотим, чтобы на нём [Автопилоте] работала сторонняя экосистема, говорит Брэдсток.

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

У инженерной службы Google репутация гораздо лучше, чем службы поддержки клиентов. Разработчик Кевин Лин (Kevin Lin) недавно описал, как выглядит схема зачисления бонусов для стартапов в AWS и Google.

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

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

Перевод Как спокойно спать, когда у вас облачный сервис основные архитектурные советы

19.08.2020 18:13:30 | Автор: admin
LOST by sophiagworld

В этой статей собраны некоторые общие шаблоны, помогающие инженерам работать с масштабными сервисами, к которым делают запросы миллионы пользователей.

По опыту автора, это не исчерпывающий список, но действительно эффективные советы. Итак, начнем.

Переведено при поддержке Mail.ru Cloud Solutions.

Начальный уровень


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

Инфраструктура как код


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

Развертывание 100 виртуальных машин

  • с Ubuntu
  • 2 ГБ RAM на каждой
  • у них будет следующий код
  • с такими параметрами

Вы можете отслеживать изменения в инфраструктуре и быстро возвращаться к ним с помощью системы управления версиями.

Модернист во мне говорит, что можно использовать Kubernetes/Docker, чтобы сделать всё выше перечисленное, и он прав.

Кроме того, обеспечить автоматизацию, можно с помощью Chef, Puppet или Terraform.

Непрерывная интеграция и доставка


Для создания масштабируемого сервиса важно наличие конвейера сборки и теста для каждого пул-реквеста. Даже если тест самый простой, он, по крайней мере, гарантирует, что код, который вы деплоите, компилируется.

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


Нет ничего прекраснее, чем видеть эти галочки

Для этой технологии можете оценить Github, CircleCI или Jenkins.

Балансировщики нагрузки


Итак, мы хотим запустить балансировщик нагрузки, чтобы перенаправлять трафик, и обеспечить равную нагрузку на всех узлах или работу сервиса в случае сбоя:


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

Обычно балансировщики нагрузки настраиваются в том облаке, которым вы пользуетесь.

RayID, сorrelation ID или UUID для запросов


Вам когда-нибудь встречалась ошибка в приложении с сообщением вроде такого: Что-то пошло не так. Сохраните этот id и отправьте его в нашу службу поддержки?


Уникальный идентификатор, correlation ID, RayID или любой из вариантов это уникальный идентификатор, который позволяет отслеживать запрос в течение его жизненного цикла. Это позволяет отследить весь путь запроса в логах.


Пользователь делает запрос к системе A, затем А связывается с B, та связывается с C, сохраняет в X и затем запрос возвращается в A

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

Средний уровень


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

Централизованное ведение журналов


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

Хотя это звучит как забавное приключение, однако, лучше убедиться, что у вас есть возможность поиска по всем журналам из одного места. Я решил задачу централизации журналов с помощью встроенной функциональности стека ELK: здесь поддерживается сбор журналов с возможностью поиска. Это действительно поможет решить проблему с поиском конкретного журнала. В качестве бонуса вы можете создавать диаграммы и тому подобные забавные штуки.


Функциональность стека ELK

Агенты мониторинга


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

На этом этапе вы проверяете, что запущенная сборка хорошо себя чувствует и нормально работает.

Для небольших и средних проектов я рекомендую Postman для мониторинга и документирования API. Но в целом просто следует убедиться, что у вас есть способ узнать, когда произошел сбой, и получить своевременное оповещение.

Автомасштабирование в зависимости от нагрузки


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


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

Система экспериментов


Хорошим способом безопасно развернуть обновления станет возможность протестировать что-то для 1% пользователей в течение часа. Вы, конечно, видели такие механизмы в действии. Например, Facebook показывает части аудитории другой цвет или меняет размер шрифта, чтобы посмотреть, как пользователи воспринимают изменения. Это называют A/B-тестированием.

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

Продвинутый уровень


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

Сине-зеленые развертывания


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

Этот шаг зависит от наличия балансировщика нагрузки. Представим, что у вас версия N вашего программного обеспечения, а затем вы хотите развернуть версию N+1.

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

Если вы действительно хотите достичь таких показателей, нужно два деплоя одновременно:

  • тот, который есть прямо сейчас (N);
  • следующая версия (N+1).

Вы указываете балансировщику нагрузки перенаправить процент трафика на новую версию (N+1), в то время как сами активно отслеживаете регрессии.


Здесь у нас есть зеленый деплой N, который нормально работает. Мы пытаемся перейти к следующей версии этого деплоя

Сначала мы посылаем действительно небольшой тест, чтобы посмотреть, работает ли наш деплой N+1 с небольшим количеством трафика:


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


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

Обнаружение аномалий и автоматическое смягчение последствий


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


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

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

Вот и всё!


Этот список приоритетов избавит вас от многих проблем, если вы поднимаете облачный сервис.

Автор оригинальной статьи приглашает читателей оставлять свои комментарии и вносить изменения. Статья распространяется как open source, пул-реквесты автор принимает на Github.

Что еще почитать по теме:

  1. Go и кэши CPU.
  2. Kubernetes в духе пиратства с шаблоном по внедрению.
  3. Наш канал Вокруг Kubernetes в Телеграме.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru