Slide 1

Slide 1 text

Нюансы запуска приложений в Kubernetes Новиков Андрей, Злые марсиане Trampoline meetup #8 24 февраля 2022

Slide 2

Slide 2 text

Нет войне!

Slide 3

Slide 3 text

Нюансы запуска приложений в Kubernetes Новиков Андрей, Злые марсиане Trampoline meetup #8 24 февраля 2022

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

Марсианский 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

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Kubernetes 101 Шо, какой ещё Kubernetes?

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

…и из чего он состоит Источник: Kubernets’а бояться — в деплой не ходить (слайды)

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

Healthcheck’и зачем их столько и в чём разница?

Slide 15

Slide 15 text

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/

Slide 16

Slide 16 text

Просто (и неправильно) Одинаковые пробы для веб-приложения: 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)

Slide 17

Slide 17 text

А какая разница?

Slide 18

Slide 18 text

Очереди запросов Запросы ждут свободного воркера/бэкенда в Nginx или апп-сервере. Картинка: https://railsautoscale.com/request-queue-time/

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

Картинка: https://knowyourmeme.com/photos/1901279-death-knocking-on-doors

Slide 21

Slide 21 text

Что же делать? Пустить 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)

Slide 22

Slide 22 text

Healthcheck’и: итого 1. Liveness ходит через «чёрный ход» Поднимите listener на отдельном порту, куда будет ходить только проба. Kubernetes не должен прибивать ваши поды под нагрузкой! 2. Readiness ходит вместе с клиентскими запросами Позвольте «забитому» поду выйти из балансировки и «остыть». Таймаут нужно подобрать эмпирически, он не должен быть слишком мал. Следите за наличием неготовых подов в мониторинге! Мораль: делайте стресс-тесты!

Slide 23

Slide 23 text

Следите за очередью запросов! Время ожидания запросов в очереди — это главная метрика, которая показывает, что приложение «на пределе». Выведите её себе в мониторинг. Если она ощутимо больше 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/

Slide 24

Slide 24 text

А как масштабироваться-то? Kubernetes Horizontal Pod Autoscaler! Разбираем автоске Разбираем автоске… … Видео Слайды Используйте USE-метрики для масштабирования! Слайды: https://speakerdeck.com/dragonsmith/razbiraiem-avtoskieilingh-v-kubernetes

Slide 25

Slide 25 text

Requests и limits Как (не)правильно просить ресурсы и у кого.

Slide 26

Slide 26 text

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/

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

Limits 101 Реализуются ядром ОС на нодах: cpu настраивает троттлинг CPU memory настраивает Out of Memory Killer limits: cpu: 400m memory: 512Mi resources: requests: cpu: 200m memory: 256Mi

Slide 29

Slide 29 text

Так, что там за 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/

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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/

Slide 32

Slide 32 text

Ну всё Ну почти.

Slide 33

Slide 33 text

Нам нужны твои мозги! Ищем добровольцев, чтобы причинять добро на всей Земле и за её пределами: evl.ms/jobs

Slide 34

Slide 34 text

Внимание! Внимание! Спасибо за внимание! @Envek @Envek @Envek @Envek github.com/Envek @evilmartians @evilmartians_ru @evil.martians Вакансии: evilmartians.com/jobs Блог: evilmartians.com/chronicles Evil Mar tians: links