Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Нюансы запуска приложений в Kubernetes

Нюансы запуска приложений в Kubernetes

Сейчас контейнеризация и Kubernetes в частности — стандарт де-факто для запуска приложений «в бою». И запустить-то приложение в «кубе» несложно, но как всегда есть нюанс и не один. Обсудим, что нужно разработчику и админу учесть и сделать для того, чтобы приложение работало быстро и надёжно, не требуя к себе особого внимания. Например, посмотрим, как работают requests и limits на ресурсы, чем должны отличаться liveness и readiness пробы, и на что следует обращать внимание в мониторинге и так далее.

Andrey Novikov

February 24, 2022
Tweet

More Decks by Andrey Novikov

Other Decks in Programming

Transcript

  1. Марсианский Open Source Yabeda: Ruby application instrum entation fram ework

    Lefthook: git hooks m anager AnyCable: Polyglot replacem ent for ActionCable server PostCS S : A tool for transform ing CS S with JavaS cript Im gproxy: Fast and secure standalone server for resizing and converting rem ote im ages Logux: Client-server com m unication fram ework based on Optim istic UI, CRDT, and log Overm ind: Process m anager for Procfile-based applications and tm ux И многие другие на evilmartians.com/oss
  2. Зачем разработчику знать Kubernetes? TL;DR: Чтобы быстрее деплоить новые фичи

    самим и не ждать админов/девопсов. Kubernets’а бояться — в деплой не ходить от марсианского SRE. Кирилл Кузнецов - Кирилл Кузнецов - … … Вечерняя школа Kubernetes для разработчиков от Slurm.io Урок 1: Введение в Урок 1: Введение в … …
  3. Что такое Kubernetes… Кластерная операционная система для деплоя приложений Абстрагирует

    приложение от нижележащего железа/облаков* Декларативная конфигурация и встроенный control loop Использует (Docker-)контейнеры для запуска приложений… …и свои абстракции для их оркестрации и запуска * https://buttondown.email/nelhage/archive/two-reasons-kubernetes-is-so-complex/
  4. Pod минимальная и главная единица в k8s — «атом» ⚛️

    логически неделимая группа контейнеров (но обычно 1 основной) запускаются вместе на одной машине делят между собой localhost и сеть есть внутрикластерный IP-адрес с точки зрения приложения — как будто отдельный сервер Документация: kubernetes.io/docs/concepts/workloads/pods Картинка: kubernetes.io/docs/tutorials/kubernetes- basics/explore/explore-intro
  5. Service Абстракция для логической группировки pod’ов Service discovery — есть

    внутрикластерное DNS-имя Балансируют трафик между своими подами (round robin) Реализованы как набор правил iptables Позволяет нам масштабировать приложения горизонтально Документация: kubernetes.io/docs/concepts/services- networking/service Картинка: kubernetes.io/docs/tutorials/kubernetes- basics/expose/expose-intro
  6. Kubernetes health probes У каждого отдельного контейнера внутри каждого пода:

    liveness Контейнер убивается и перезапускается, если он не отвечает на «ты жив?». readiness Под исключается из балансировки трафика через сервис, если не отвечает на «ну что, готов?» и включается обратно, когда отвечает утвердительно. startup (k8s 1.20+) Позволяет отсрочить начало liveness и readiness проверок для долгозапускающихся приложений Важно: и liveness и readiness выполняются параллельно всё время жизни пода. https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
  7. Просто (и неправильно) Одинаковые пробы для веб-приложения: path: /health port:

    80 path: /health port: 80 containers: - name: app livenessProbe: httpGet: timeoutSeconds: 3 periodSeconds: 10 readinessProbe: httpGet: timeoutSeconds: 3 periodSeconds: 10 Картинка: behance.net/gallery/35173039/Stickers-for- another-one-IT-conference-(DUMP2016)
  8. Приходит нагрузка 🏋️ 1. Медленные запросы попадают на один под

    и «забивают» его 2. «Забитый» контейнер в поде перестаёт отвечать на liveness 🥀 3. Kubernetes убивает контейнер 💀 4. И тут же запускает его заново, но это занимает какое-то время… ⌚ 5. На время перезапуска на другие поды приходит больше запросов. 6. GOTO 1 🤡 Неправильно настроенная liveness-проба под нагрузкой убьёт приложение, под за подом!
  9. Что же делать? Пустить liveness пробу в обход! port: 8080

    # ← другой порт containers: - name: app livenessProbe: httpGet: path: /health timeoutSeconds: 3 periodSeconds: 10 readinessProbe: httpGet: path: /health port: 80 timeoutSeconds: 3 periodSeconds: 10 Картинка: behance.net/gallery/35173039/Stickers-for- another-one-IT-conference-(DUMP2016)
  10. Healthcheck’и: итого 1. Liveness ходит через «чёрный ход» Поднимите listener

    на отдельном порту, куда будет ходить только проба. Kubernetes не должен прибивать ваши поды под нагрузкой! 2. Readiness ходит вместе с клиентскими запросами Позвольте «забитому» поду выйти из балансировки и «остыть». Таймаут нужно подобрать эмпирически, он не должен быть слишком мал. Следите за наличием неготовых подов в мониторинге! Мораль: делайте стресс-тесты!
  11. Следите за очередью запросов! Время ожидания запросов в очереди —

    это главная метрика, которая показывает, что приложение «на пределе». Выведите её себе в мониторинг. Если она ощутимо больше 0 — надо скейлиться вверх (в Kubernetes есть Horizontal Pod Autoscaler) Если она всегда строго 0 — можно подумать о скейлинге вниз. Следите за USE и RED метриками, когда дело касается производительности! Utilization: количество свободных воркера Saturation: время ожидания свободного воркера (95p) Errors: процент ошибок при обработке запросов Duration: время обработки запроса (95p) USE method: https://www.brendangregg.com/usemethod.html RED method: https://grafana.com/blog/2018/08/02/the-red-method-how-to-instrument-your-services/
  12. А как масштабироваться-то? Kubernetes Horizontal Pod Autoscaler! Разбираем автоске Разбираем

    автоске… … Видео Слайды Используйте USE-метрики для масштабирования! Слайды: https://speakerdeck.com/dragonsmith/razbiraiem-avtoskieilingh-v-kubernetes
  13. Requests и limits 101 Для каждого контейнера в Pod’е: requests

    и limits для Pod — сумма значений его контейнеров. requests — инструкции для планировщика k8s limits — инструкции для ядра ОС на нодах кластера cpu — измеряются в millicpu (тысячных долях процессорного ядра) memory — измеряются в байтах и кратных (мебибайты, гебибайты) resources: requests: cpu: 200m memory: 256Mi limits: cpu: 500m memory: 512Mi https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
  14. Requests 101 Инструкции для планировщика k8s для распределения Pod’ов на

    ноды: Не используются в рантайме* Не учитывают фактическое потребление*, только requests других подов requests: cpu: 200m memory: 256Mi resources: limits: cpu: 500m memory: 512Mi * Используются при настройке OOM, но про это дальше Картинка: Илья Черепанов, внутренняя школа k8s
  15. Limits 101 Реализуются ядром ОС на нодах: cpu настраивает троттлинг

    CPU memory настраивает Out of Memory Killer limits: cpu: 400m memory: 512Mi resources: requests: cpu: 200m memory: 256Mi
  16. Так, что там за milliCPU ещё? В случае limits настраивает

    CPU throttling — долю процессорного времени, которое можно использовать в течение 100мс. Админы, настройте алерт CPUThrottlingHigh ! Не указывайте дробные CPU limits для контейнеров, где важна скорость ответа! ` ` cpu: 400m resources: requests: cpu: 200m memory: 256Mi limits: memory: 512Mi Подробнее: https://engineering.indeedblog.com/blog/2019/12/unthrottled-fixing-cpu-limits-in-the-cloud/
  17. Утилизируем ядра Процесс на языках с GIL (Ruby, Python) не

    может утилизировать процессорное ядро целиком! Максимум на 30-50%. Используйте и процессы и потоки: Запускайте 2-4 рабочих процесса на контейнер (работает CoW 🐮) По 4-6 потоков в каждом ➕ Улучшается утилизация воркеров за счёт раздачи запросов простаивающим воркерам. Подробнее: https://www.speedshop.co/2017/10/12/appserver.html
  18. Requests × Limits = QoS В различных сочетаниях реквестов и

    лимитов поведение контейнера может меняться драматично: 1. Guaranteed — requests = limits гарантированно выдаётся CPU убиваются по OOM последними 2. Burstable — requests ≠ limits могут использовать CPU больше запрошенного убиваются после BestEffort, в порядке «жадности» 3. BestEffort — нет ни requests ни limits CPU выдаётся в последнюю очередь Первыми убиваются OOM-киллером Всегда указывайте и requests и limits! ` ` ` ` ` ` Подробнее: Управление ресурсами в Kubernetes — habr.com/ru/company/flant/blog/459326/
  19. Внимание! Внимание! Спасибо за внимание! @Envek @Envek @Envek @Envek github.com/Envek

    @evilmartians @evilmartians_ru @evil.martians Вакансии: evilmartians.com/jobs Блог: evilmartians.com/chronicles Evil Mar tians: links