Tech Recipe Book
My Services
  • Book
    • About the author
    • Architect
      • Algorithms
        • DB index algorithms
          • How does database indexing work
        • Neural network optimization
          • Neural Network Optimization
        • Route search
          • Road network in a database to build a route
          • Traveling Salesman Problem (TSP)
      • Architecture Frameworks
        • DODAF
        • TOGAF
        • Enterprise Architecture (EA) Tools Reviews 2023 | Gartner
      • Zero Trust
      • Billing
        • SHM billing system
      • Bots
        • Discord
        • Telegram
          • Chat GPT Telegram bot
          • Получаем статистику Telegram-канала при помощи api и python или свой tgstat с регистрацией и смс
          • Как хостить телеграм-бота (и другие скрипты на Python) на Repl.it бесплатно 24/7
          • Создание Telegram бота на PHP #1: основные понятия для работы с API
          • Создание Telegram бота на PHP #2: создание первого бота для Telegram
          • Создание Telegram бота на PHP #3: примеры отправки сообщений с кнопками в Telegram
          • Создание Telegram бота на PHP #4: отправка файлов и изображений в Telegram
          • Создание Telegram бота на PHP #5: работа с хуками
      • Business intelligence
      • Cloud Storage
        • Ceph
        • Virtual Distributed File System
      • Cryptography
        • Open Source PKI Software
        • OpenPGP
          • Email Encryption
          • Kleopatra
          • Miscellaneous Tools
          • Server side applications
      • Message broker
        • Kafka
          • Kafka UI-tools
          • Kafka streams ksqlDb
        • RabbitMQ
      • DB
        • MySQL
          • Auto sharding
          • MariaDB Zabbix monitoring
          • MySQL and MariaDB replication with Zabbix monitoring
        • Postgres
          • HA PostgreSQL with Patroni, Haproxy, Keepalived
          • Mass parallel requests - Greenplum
          • PostgreSQL cluster for development and testing
        • Vitess - Scalable. Reliable. MySQL-compatible. Cloud-native. Database.
      • Identity and Access Management (IDM)
        • FreeIPA - Identity, Policy, Audit
        • FreeIPA as an Enterprise solution
        • Keycloak
          • Keycloak HA cluster
        • Open Identity Platform
        • SSO
          • Keycloak for Java app
          • OpenAM
          • OpenIG
      • Firewall
        • nftables
      • Infrastructure As a Code
        • Ansible
        • IaC Packer Ansible Teraform
        • Installing Jenkins using terraform in Kubernetes in Yandex Cloud with letsencypt
        • Teraform Crosplan Pulumi
        • Yandex IaC solutions
      • Kubernetes
        • Installation
          • Install Kubernetes cluster
          • Deploying a Kubespray cluster to OpenStack using Terraform
          • Kube deploy in Yandex cloud
        • Frameworks
          • Deckhouse
            • LDAP authentification
            • On premise Install
            • Yandex Cloud Install
          • K3S
          • OpenShift OKD
          • RKE2
          • Rancher
            • Rancher Install
        • Auth
          • Keycloak in k8s
          • LDAP
        • GUI management Lens
        • Monitoring
          • Monitoring with Falco
          • Network monitoring
          • Nginx ingress
          • Prometheus Graphana for sample Nodejs app
          • Rsource monitoring Avito
        • Exposing services
          • Exposing Kubernetes Services
          • Cilium BGP
        • CNCF
        • Helm
          • Repositories
            • Artifact Hub | official
            • Bitnami | vmware
          • Awesome helm charts and resources
          • Essential Services for Modern Organizations
          • Security and Compliance
          • Additional charts
        • Isolation
          • vcluster - Virtual Kubernetes Clusters
          • Kiosk
          • KubeArmor
          • Control Plane Hardening
          • Hierarchical namespaces
        • Security Center
          • Minesweeper
          • NeuVector by SUSE
          • SOAR in Kubernetes
          • Security Сenter for Kubernetes
        • Terraform CI security
          • Terraform plan analysis with Checkov and Bridgecrew
          • Yandex Terraform scan
        • Vulnerability management
          • Aqua
          • Sysdig
          • Kyverno
          • GitLab
          • NeuVector by SUSE
        • Image scanning
          • Snyk
          • Sysdig
          • Harbor
          • Trivy
        • Signature verification
          • Sigstore
        • Control plane security
          • Gatekeeper
            • Applying OPA Gatekeeper
          • Kyverno
            • Policy as a code. Kyverno
        • Runtime Security
          • Osquery
          • Falco
          • ClamAV
        • Network security
          • Cilium
          • Control Plane Hardening (API restriction)
          • Network policy recipes
          • Service mesh
            • Istio HA, LoadBalance, Rate limit
          • mTLS Autocert
        • Honeypot
          • Building honeypot using vcluster and Falco
        • Backup
          • Kasten K10
        • Secrets
          • Vault CSI Driver
      • Load Balance
        • Nginx
        • HAProxy
          • Proxy methods
          • HAProxy for RDP
          • Payment gateway A/B test with HAProxy
          • HAPRoxy for Percona or Galera
      • Monitoring
        • Zabbix
          • Apache Zabbix
          • Disc Quota
          • Nginx Zabbix
          • SSL certificates Zabix
          • Zabbix notifications
        • Nagios
          • Datacenter monitoring
        • Prometheus and Grafana
      • Windows
        • Sysmon enhanced Windows audit
        • Sysmon to Block Unwanted File
      • Linux
        • Rsync
        • Debian based
          • Apt-Cacher NG
          • Unattended Upgrades in Debian / Ubuntu
        • RedHat basede
          • RPM Server
        • Logs analysis
        • Build armhf qemu
      • NGFW
      • CI/CD
        • DevSecOps
          • DAST
            • Burp
              • Dastardly
            • StackHawk
            • ZAP and GitHub Actions
          • SAST
            • Checkmarx
            • OSV by Google
            • Snyk
            • SonarQube
        • GitLab Runner in Yandex Cloud
        • Dynamic Gitlab Runners in Yandex Cloud
        • GitLab runner in Kubernetes with Werf
        • Kubernetes deploy strategies
        • Kubernetes highload deploy. part 1
        • Kubernetes highload deploy. part 2
        • Kubernetes Argo Rollouts
        • Jenkins in Kubernetes
        • Ansible Semaphore
        • Image storage, scaning and signing
        • Install WireGuard with Gitlab and Terraform
        • CI/CD example fror small web app
        • Threat matrix for CI CD Pipeline
      • SIEM / SOC
        • Datadog
        • Splunk
          • Splunk — general description
        • MaxPatrol
          • MaxPatrol 8 and RedCheck Enterprise
        • QRadar IBM
        • Cloud Native Security Platform (CNAPP) - Aqua
        • OSSIM | AT&T
          • AlienVault (OSSIM) install
        • Wazuh
        • EDR
          • Cortex XDR | Palo Alto Networks
          • Cynet
          • FortiEDR | Fortinet
          • Elastic
        • Elastic
          • Install Elasticsearch, Logstash, and Kibana (Elastic Stack) on Ubuntu 22.04
          • Setting Up Elastic 8 with Kibana, Fleet, Endpoint Security, and Windows Log Collection
        • Threat Intelligence
          • MISP
          • msticpy Microsoft
          • X-Force | IBM
          • Elastic
      • VPN
        • Full-Mesh VPN fastd, tinc, VpnCloud
        • Wireguard
          • WireGuard for Internet access
          • WireGuard on MikroTik and Keenetic
          • WireGuard site to site
        • SoftEther VPN Project
        • Cisco AnyConnect client
        • OpenConnect
        • SSTP python server
      • OS hardening
        • CIS Benchmarks
      • Cloud Providers
      • OpenNebula
        • OpenNebula Edge Cloud - Open Source Cloud & Edge Computing
        • Discover OpenNebula – Open Source Cloud & Edge Computing Platform
        • OpenNebula Multi-Cloud
        • Kubernetes on OpenNebula
        • The Open Source Alternative to Nutanix
        • The Simple Alternative to OpenStack
        • OpenNebula Partner Ecosystem
      • OpenStack
        • Install manual
        • Install with DevStack
      • VM
        • Create a VHD file from a Linux disk
        • Backup / Migration
          • Coriolis
          • Proxmox Backup Server
        • oVirt
        • VMware vCenter
        • Proxmox
      • Docker
        • Container optimization
        • Ubuntu RDP container
      • LXC
        • LXD on Ubuntu 18.04
        • Install, Create and Manage LXC in Ubuntu/Debian
    • Big Data
      • OLAP data qubes
      • Storage and autoscale in Lerua
    • Machine Learning
      • Yandex YaLM 100B. GPT model
      • Kaggle Community Datasts Models
      • AI in video production
      • Image search
      • Chat bots
        • You.com
        • Chat GPT
          • Implementing GPT in NumPy
        • Jailbreak Chat
      • Coding plugins CodeWhisperer
    • Malware
      • Isiaon/Pitraix: Modern Cross-Platform Peer-to-Peer Botnet over TOR
      • theZoo A repository of LIVE malwares
    • Pentest
      • Red Team
        • MITRE ATT&CK matrix
        • C2 Frameworks
          • Brute Ratel C4
          • Cobalt Strike
          • Covenant
          • Havoc Framework
          • Merlin
          • Metasploit
          • Sillenttrinity
          • Sliver
        • Manage and report
          • Dradis Framework
          • Hexway
        • Underground
      • Social engineering
        • Social Engineer Toolkit setoolkit
      • OSINT
        • OSINT for comapny
        • Instagram fishing
      • Forensics
        • Forensics tools
      • Pentesting Methodology
      • Web
      • CI/CD Methodology
      • Cloud Methodology
        • Hacking The Cloud
      • Kubernetes Pentesting
      • Android
        • SSL Unpinning for Android applications
      • iOS
        • SSL unpinning iOS and macOS applications
      • HackBar tool
      • CyberChef Tools
      • Python virtualenv
      • IppSec - YouTube
      • Hacktricks.xyz
    • Compliance
      • 152 ФЗ. Personal data
      • PCI DSS and ГОСТ Р 57580.1-2017
      • Cloud compliance
      • ГОСТ Р 57580.1-2017 для Kubernetes
      • Kubernets as DevSecOps and NIST compliance
      • NIST SP 800-61 cyberincidece control
      • CIS Kubernetes Benchmark v1.6 - RKE2 v1.20
      • CIS Kubernetes Benchmark v1.23 - RKE2
      • Requirements for Russian Banks
      • Tools
        • Chef InSpec
        • Elastic SIEM
    • Asset management
      • CMDBuild
    • Project management
    • Incident management SRE
    • Risk management
      • IT risk management
      • BSI-Standard 200-3
    • Web Dev
      • Cookie security
      • OWASP Top 10 2021
      • Docker nginx php mysql
      • Docker tor hiddenservice nginx
      • Docker Compose wp nginx php mariadb
      • Dependency Checking
        • Nexus Analyzer
        • OWASP dependency-check
      • Yii skeeks cms
      • YiiStudio
    • Art
      • GTK Themes
      • Themes for Xfce Desktop
      • XFCE / Xubuntu Windows 95
      • Moscow events
      • Photo goods
      • Russian style gifts
    • Cryptocurrency
      • News
      • Arbitrage
      • Stocks
      • Exchange aggregators
      • Where to use
      • Prepaid cards
        • BitFree
        • Pyypl Your Money at Your Fingertips
    • IT magazines
      • WIKI and Writeups tools
        • BookStack
        • GitBook
        • MkDocs
        • Wiki.js
        • DokuWiki
    • Languages
    • Learning
      • (ISC)2
        • CISSP
      • Offensive Security
        • OSCP
        • OSEP
        • OSED
      • DevSecOps
        • Certified DevSecOps Professional (CDP)
        • Certified DevSecOps Expert (CDE)
      • Web Security Academy: PortSwigger
    • Relocation
      • London experience
      • IT visas in 2022
      • Remote work
      • Running business in UAE
    • Freenet
      • Independent online services: the philosophy of a free Internet
      • Tor Project Anonymity Online
      • I2P Anonymous Network
    • Services
      • SMS Registration
        • Registering ChatGPT in Russia
      • Local and regional eSIMs for travellers - Airalo
      • Digital busines cards
      • No KYC services and exchanges
Powered by GitBook
On this page
  • 9. PodDisruptionBudget
  • 10. HorizontalPodAutoscaler
  • Дополнительные фичи
  • Итог по HPA
  • 11. VerticalPodAutoscaler
  • Режим Off
  • Другие режимы VPA
  • Итоговые рекомендации по VPA
  • Заключение
  • P.S.

Was this helpful?

  1. Book
  2. Architect
  3. CI/CD

Kubernetes highload deploy. part 2

Last updated 1 year ago

Was this helpful?

В были рассмотрены рекомендации по множеству механизмов Kubernetes для оптимального деплоя высокодоступных приложений включая особенности работы планировщика, стратегии обновления, приоритеты, пробы и т.п. Во втором и заключительном материале поговорим о трёх важных оставшихся темах: PodDisruptionBudget, HorizontalPodAutoscaler, VerticalPodAutoscaler, — продолжив нумерацию из первой части.

9. PodDisruptionBudget

Однако может случиться ситуация, при которой из эксплуатации одновременно выйдет не один узел. Например, вы решили поменять инстансы на более мощные. Могут быть и другие причины, но сейчас это не так важно. Важно, что несколько узлов выведены из эксплуатации в один момент времени. «Это же Kubernetes! — скажете вы. — Тут всё эфемерно. Ну, переедут pod’ы на другие узлы — что такого?» Давайте разберёмся.

Предположим, приложение состоит из 3-х реплик. Нагрузка распределена равномерно по ним, а pod’ы — по узлам. Оно выдержит, если упадет одна из реплик. Но вот при падении двух реплик из трёх начнётся деградация сервиса: один pod просто не справится с нагрузкой, клиенты начнут получать 500-е ошибки. Ок, если мы подготовились и заранее прописали rate limit в контейнере c nginx (конечно, если у нас есть контейнер с nginx в pod’е…), то ошибки будут 429-е. Но это все равно деградация сервиса.

Тут нам на помощь и приходит PodDisruptionBudget. Взглянем на его манифест:

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: app-pdb
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: app

Конфиг довольно простой, и большая часть полей в нем скорее всего знакома (по аналогии с другими манифестами). Самое интересное — это maxUnavailable. Данное поле позволяет указать, сколько pod’ов (максимум) могут быть недоступны в момент времени. Указывать значение можно как в единицах pod’ов, так и в процентах.

Предположим, что для приложения настроен PDB. Что теперь произойдет, когда два или более узлов, на которые выкачены pod’ы приложения, начнут по какой-либо причине вытеснять (evict) pod’ы? PDB позволит вытеснить лишь один pod, а второй узел будет ждать, пока реплик не станет хотя бы две (из трёх). Только после этого еще одну из реплик можно вытеснить.

Есть также возможность определять и minAvailable. Например:

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: app-pdb
spec:
  minAvailable: 80%
  selector:
    matchLabels:
      app: app

Так можно гарантировать, что кластер будет следить за тем, чтобы 80% реплик всегда были доступны, а вытеснять с узлов [при такой необходимости] можно только оставшиеся 20%. Указывать это соотношение снова можно в процентах и единицах.

Есть и обратная сторона медали: у вас должно быть достаточное количество узлов, причем с учетом podAntiAffinity. Иначе может сложиться ситуация, что одну реплику вытеснили с узла, а вернуться она никуда не может. Результат: операция drain просто ждет вечность, а вы остаетесь с двумя репликами приложения… В describe pod’а, который висит в Pending, можно, конечно, найти информацию о том, что нет свободных узлов, и исправить ситуацию, но лучше до этого не доводить.

Итоговая рекомендация: всегда настраивайте PDB для критичных компонентов вашей системы.

10. HorizontalPodAutoscaler

Рассмотрим другую ситуацию: что происходит, если на приложение приходит незапланированная нагрузка, которая значительно выше той, что мы «привыкли» обрабатывать? Да, ничто не мешает вручную зайти в кластер и отмасштабировать pod’ы… но ради чего тогда мы тут все тогда собрались, если все делать руками?

В итоге, все входящие запросы обработаны в нормальном режиме. Причем — и это важно! — как только нагрузка вернется в привычное русло, HPA отмасштабирует pod’ы обратно, тем самым снижая затраты на инфраструктуру. Звучит здорово, не так ли?

Разберемся, как именно HPA вычисляет, сколько реплик надо добавить. Вот формула из документации:

desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]

Предположим:

  • текущее количество реплик = 3;

  • текущее значение метрики = 100;

  • пороговое значение метрики = 60.

Получаем следующее выражение: 3 * ( 100 / 60 ), т.е. на выходе получаем «около» 5 (HPA округлит результат в б_о_льшую сторону). Таким образом, приложению будут добавлены еще две реплики. А значение будет по-прежнему вычисляться по формуле, чтобы, как только нагрузка снизится, уменьшилось и количество необходимых реплик для обработки этой нагрузки.

Здесь начинается самое интересное. Что же выбрать в качестве метрики? Первое, что приходит на ум, — это базовые показатели, такие как CPU, Memory… И такое решение действительно сработает, если у вас… нагрузка на CPU и Memory растет прямо пропорционально входящей нагрузке. Но что, если pod’ы обрабатывают разные запросы: одни могут потребовать много тактов процессора, другие — много памяти, а третьи — вообще укладываются в минимальные ресурсы?

Рассмотрим на примере с очередью на RabbitMQ и теми, кто эту очередь будет разбирать. Допустим, в очереди 10 сообщений. Мы видим (спасибо мониторингу!), что очередь разбирается довольно быстро. То есть для нас нормально, когда в среднем в очереди скапливается до 10 сообщений. Но вот пришла нагрузка — очередь сообщений выросла до 100. Однако нагрузка на CPU и Memory не изменится у worker’ов: они будут монотонно разбирать очередь, оставляя там уже около 80-90 сообщений.

А ведь если бы мы настроили HPA по нашей (кастомной) метрике, описывающей количество сообщений в очереди, то получили бы понятную такую картину:

  • текущее количество реплик = 3;

  • текущее значение метрики = 80;

  • пороговое значение метрики = 15.

Теперь взглянем на несколько манифестов:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 50

Тут все просто. Как только pod достигает нагрузки по CPU в 50%, HPA начнет масштабировать максимум до 10.

А вот более интересный вариант:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: worker
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: worker
  minReplicas: 1
  maxReplicas: 10
 metrics:
  - type: External
    external:
      metric:
        name: queue_messages
      target:
        type: AverageValue
        averageValue: 15

Дополнительные фичи

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

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: worker
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: worker
  minReplicas: 1
  maxReplicas: 10
 metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
  - type: External
    external:
      metric:
        name: queue_messages
      target:
        type: AverageValue
        averageValue: 15

Как будет считать HPA? У какой из метрик при подсчете получилось большее количество реплик, на тот он и будет опираться. Если из расчета потребления CPU выходит, что надо масштабировать до 5, а по расчетам на основании размерности очереди — до 3, то произойдет масштабирование до 5 pod’ов.

behavior:
  scaleDown:
    stabilizationWindowSeconds: 60
    policies:
    - type: Percent
      value: 5
      periodSeconds: 20
   - type: Pods
      value: 5
      periodSeconds: 60
    selectPolicy: Min
  scaleUp:
    stabilizationWindowSeconds: 0
    policies:
    - type: Percent
      value: 100
      periodSeconds: 10

Здесь заданы две секции: одна определяет параметры масштабирования вниз (scaleDown), вторая — вверх (scaleUp). В каждой из секций есть интересный параметр — stabilizationWindowSeconds. Он позволяет избавиться от «флаппинга», то есть ситуации, при которой HPA будет масштабировать то вверх, то вниз. Грубо говоря, это некий таймаут после последней операции изменения количества реплик.

Теперь о политиках, и начнем со scaleDown. Эта политика позволяет указать, какой процент pod’ов (type: Percent) можно масштабировать вниз за указанный период времени. Если мы понимаем, что нагрузка на приложение — волнообразная, что спадает она так же волнообразно, надо выставить процент поменьше, а период — побольше. Тогда при снижении нагрузки HPA не станет сразу убивать множество pod’ов по своей формуле, а будет вынужден делать это постепенно. Вдобавок, мы можем указать явное количество pod’ов (type: Pods), больше которого за период времени убивать никак нельзя.

Также стоит обратить внимание на параметр selectPolicy: Min — он указывает на необходимость исходить из политики минимального количества pod’ов. То есть: если 5 процентов меньше, чем 5 единиц pod’ов, будет выбрано это значение. А если наоборот, то убирать будем 5 pod’ов. Соответственно, выставление selectPolicy: Max даст обратный эффект.

Со scaleUp аналогичная ситуация. В большинстве случаев требуется, чтобы масштабирование вверх происходило с минимальной задержкой, поскольку это может повлиять на пользователей и их опыт взаимодействия с приложением. Поэтому stabilizationWindowSeconds здесь выставлен в 0. Зная, что нагрузка приходит волнами, мы позволяем HPA при необходимости поднять реплики до значения maxReplicas, которое определено в манифесте HPA. За это отвечает политика, позволяющая раз в periodSeconds: 10, поднимать до 100% реплик.

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

behavior:
  scaleDown:
    selectPolicy: Disabled

Как правило, политики нужны тогда, когда у вас HPA работает не так, как вы на это рассчитываете. Политики дают большую гибкость, но усложняют восприятие манифеста.

Итог по HPA

Закончим примером финального манифеста для HPA:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: worker
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: worker
  minReplicas: 1
  maxReplicas: 10
 metrics:
  - type: External
    external:
      metric:
        name: queue_messages
      target:
        type: AverageValue
        averageValue: 15
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 5
        periodSeconds: 20
     - type: Pods
        value: 5
        periodSeconds: 60
      selectPolicy: Min
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 10

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

Подведем итог по Horizontal Pod Autoscaler. Использовать HPA для production-окружений всегда полезно. Но выбирать метрики, на которых он будет основываться, надо тщательно. Неверно выбранная метрика или некорректный порог ее срабатывания будет приводить к тому, что либо получится перерасход по ресурсам (из-за лишних реплик), либо клиенты увидят деградацию сервиса (если реплик окажется недостаточно). Внимательно изучайте поведение вашего приложения и проверяйте его, чтобы достичь нужного баланса.

11. VerticalPodAutoscaler

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

Конечно, актуальные для приложения (до этого обновления) requests и limits уже были выставлены. И вот теперь приложение достигает лимита по памяти, приходит мистер ООМ и совершает над pod’ом насильственные действия. VPA может это предотвратить! Если посмотреть на ситуацию в таком срезе, то, казалось бы, это замечательный инструмент, который надо использовать всегда и везде. Но в реальности, конечно, все не так просто и важно понимать сопутствующие нюансы.

Основная проблема, которая на текущий момент не решена, это изменение ресурсов через перезапуск pod’а. В каком-то ближайшем будущем VPA научится их патчить и без рестарта приложения, но сейчас не умеет. Допустим, это не страшно для хорошо написанного приложения, всегда готового к перекату: приложение разворачивается Deployment’ом с кучей реплик, настроенными PodAntiAffinity, PodDistruptionBudget, HorizontalPodAutoscaler… В таком случае, если VPA изменит ресурсы и аккуратно (по одному) перезапустит pod’ы, мы это переживем.

Но бывает всё не так гладко: приложение не очень хорошо переживает перезапуск, или мы ограничены в репликах по причине малого количества узов, или у нас вообще StatefulSet…. В худшем сценарии придет нагрузка, у pod’ов вырастет потребление ресурсов, HPA начал масштабировать, а тут VPA: «О! Надо бы поднять ресурсы!» — и начнет перезапускать pod’ы. Нагрузка начнет перераспределяться по оставшимся, из-за чего pod может просто упасть, нагрузка уйдет на еще живые и в результате произойдет каскадное падение.

Поэтому и важно понимать разные режимы работы VPA. Но начнем с рассмотрения самого простого — Off.

Режим Off

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

Итак, вот простой манифест:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: my-app
  updatePolicy:
    updateMode: "Recreate"
    containerPolicies:
      - containerName: "*"
        minAllowed:
          cpu: 100m
          memory: 250Mi
        maxAllowed:
          cpu: 1
          memory: 500Mi
        controlledResources: ["cpu", "memory"]
        controlledValues: RequestsAndLimits
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: my-app
  updatePolicy:
    updateMode: "Off"   # !!!
  resourcePolicy:
    containerPolicies:
      - containerName: "*"
        controlledResources: ["cpu", "memory"]

Теперь VPA начнет собирать метрики. Если спустя несколько минут посмотреть на него через describe, появятся рекомендации:

  Recommendation:
    Container Recommendations:
      Container Name:  nginx
      Lower Bound:
        Cpu:     25m
        Memory:  52428800
      Target:
        Cpu:     25m
        Memory:  52428800
      Uncapped Target:
        Cpu:     25m
        Memory:  52428800
      Upper Bound:
        Cpu:     25m
        Memory:  52428800

Спустя пару дней (неделю, месяц, …) работы приложения рекомендации будут точнее. И тогда можно будет корректировать лимиты в манифесте приложения. Это позволит спастись от ООМ’ов в случае недостатка requests/limits и поможет сэкономить на инфраструктуре (если изначально был выделен слишком большой запас).

А теперь — к некоторым сложностям.

Другие режимы VPA

Режим Initial выставляет ресурсы только при старте pod’а. Следовательно, если у вас неделю не было нагрузки, после чего случился выкат новой версии, VPA проставит низкие requests/limits. Если резко придет нагрузка, будут проблемы, поскольку запросы/лимиты установлены сильно ниже тех, что требуются при такой нагрузке. Этот режим может быть полезен, если у вас равномерная, линейно растущая нагрузка.

В режиме Auto будут пересозданы pod’ы, поэтому самое сложное, чтобы приложение корректно обрабатывало процедуру рестарта. Если же оно не готово к корректному завершению работы (т.е. с правильной обработкой завершения текущих соединений и т.п.), то вы наверняка поймаете ошибки (5XX) «на ровном месте». Использование режима Auto со StatefulSet вообще редко оправдано: только представьте, что у вас VPA решит добавить ресурсы PostgreSQL в production…

А вот в dev-окружении можно и поэкспериментировать, чтобы выяснить необходимые ресурсы для выставления их для production. Например,мы решили использовать VPA в режиме Initial, у нас есть Redis, а у него — параметр maxmemory. Скорее всего нам надо его изменить под свои нужды. Но загвоздка в том, что Redis’у нет дела до лимитов на уровне cgroups. Если случится так, что maxmemory будет равен 2GB, а в системе выставлен лимит в 1GB, то ничего хорошего не выйдет. Как же выставить maxmemory в то же значение, что и лимит? Выход есть! Можно пробросить значения, взяв их из VPA:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  labels:
    app: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:6.2.1
        ports:
        - containerPort: 6379
        resources:
           requests:
             memory: "100Mi"
             cpu: "256m"
           limits:
             memory: "100Mi"
             cpu: "256m"
        env:
          - name: MY_MEM_REQUEST
            valueFrom:
              resourceFieldRef:
                containerName: app
                resource: requests.memory
          - name: MY_MEM_LIMIT
            valueFrom:
              resourceFieldRef:
                containerName: app
                resource: limits.memory

Получив переменные окружения, можно извлечь нужный лимит по памяти и по-хорошему отнять от него условные 10%, оставив их на нужды приложения. А остальное выставить в качестве maxmemory**.** Вероятно, придется также придумывать что-то с init-контейнером, который sed’ает конфиг Redis, потому что базовый образ Redis не позволяет ENV-переменной пробросить maxmemory. Тем не менее, решение будет работать.

Итоговые рекомендации по VPA

  • Всем приложениям будет полезен режим Off.

  • В dev можно экспериментировать с Auto и Initial.

  • В production стоит применять только тогда, когда вы уже собрали/опробовали рекомендации и точно понимаете, что делаете и зачем.

А вот когда VPA научится патчить ресурсы без перезапуска… тогда заживем!

Заключение

На этом мы завершаем обзор лучших практик в контексте деплоя HA-приложений в Kubernetes. Будем рады любой обратной связи и пожеланиям на будущие подобные материалы.

P.S.

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

Механизм (PDB) — это must have для работы приложения в production-среде. Он позволяет контролировать, какое количество pod’ов приложения могут быть недоступны в момент времени. Читая первую часть статьи, можно было подумать, что мы уже ко всему подготовлены, если у приложения запущены несколько реплик и прописан podAntiAffinity, который не позволит pod’ам schedule’иться на один и тот же узел.

На помощь приходит (HPA). Этот механизм позволяет указать нужную метрику(и) настроить автоматический порог масштабирования pod’ов в зависимости от изменения её значений. Представьте, что вы спокойно спите, но внезапно, ночью, приходит небывалая нагрузка — скажем, заокеанские пользователи узнали про ваш сервис на Reddit. Нагрузка на CPU (или показатель иной метрики) у pod’ов вырастает, достигает порога… после чего HPA начинает доблестно масштабировать pod’ы, чтобы способствовать распределению нагрузки благодаря выделению новых ресурсов.

Т.е.: 3 * ( 80 / 15 ) = 16. Тогда HPA начнет масштабировать worker’ы до 16 реплик, и они быстро разберут все сообщения в очереди (после чего HPA может масштабировать их вниз). Однако для этого важно, чтобы мы были «инфраструктурно готовы» к тому, что дополнительно может развернуться еще столько pod’ов. То есть они должны влезть на текущие узлы, или же новые узлы должны быть заказаны у поставщика инфраструктуры (облачного провайдера), если вы используете . В общем, это очередная отсылка к планированию ресурсов кластера.

Мы уже смотрим на . Опираясь на значение queue_messages, HPA будет принимать решение о необходимости масштабирования. Учитывая, что для нас нормально, если в очереди около 10 сообщений, здесь выставлено среднее значение в 15 как пороговое. Так можно контролировать количество реплик уже более точно. Согласитесь, что и автомасштабирование будет куда лучше и точнее [чем по условному CPU] в случае разбора очереди?

С релиза появилась возможность прописывать политики scaleUp и scaleDown. Например:

А в скором времени получится даже опираться на ресурсы конкретного контейнера в pod’е (представлено как alpha в ).

позволяет считать потребление ресурсов pod’ами и (в случае соответствующего режима работы) вносить изменения в ресурсы контроллеров — править их requests и limits.

Подробно разбирать каждый параметр в манифесте не будем: у нас есть , в деталях рассказывающий о возможностях и особенностях VPA. Вкратце: здесь мы указываем, на какой контроллер нацелен наш VPA (targetRef) и какова политика обновления ресурсов, а также задаем нижнюю и верхнюю границы ресурсов, которыми VPA волен распоряжаться. Главное внимание — полю updateMode. В случае режима Recreate или Auto (пока не сделают упомянутую возможность патча) будет происходить пересоздание pod’а со всеми вытекающими последствиями, но мы этого не хотим и пока просто поменяем режим работы на Off:

Напоследок, упомяну неприятный момент, связанный с тем, что VPA «выбрасывает» pod’ы DaemonSet сразу, скопом. Со своей стороны мы начали работу над , который исправляет эту ситуацию.

Важно также помнить, что существует ряд нюансов при совместном использовании HPA и VPA. Например, эти механизмы нельзя использовать совместно, опираясь на одни и те же базовые метрики (CPU или Memory), потому что при достижении порога по ним VPA начнет поднимать ресурсы, а HPA начнет добавлять реплики. Как результат, нагрузка резко упадет и процесс пойдет в обратную сторону — может возникнуть «flapping». Существующие ограничения более подробно описаны в . Благодарю за это полезное дополнение!

«» (обзор и видео доклада);

«».

PodDisruptionBudget
HorizontalPodAutoscaler
Cluster Autoscaler
custom metrics
Kubernetes 1.18
Kubernetes 1.20
VPA
перевод
патчем
документации
@Rinck
Автомасштабирование и управление ресурсами в Kubernetes
Вертикальное автомасштабирование pod'ов в Kubernetes: полное руководство
https://habr.com/ru/companies/flant/articles/549464/
прошлой части