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. Нюансы
    запуска приложений в
    Kubernetes
    Новиков Андрей, Злые марсиане
    Trampoline meetup #8
    24 февраля 2022

    View full-size slide

  2. Нет войне!

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    Вечерняя школа Kubernetes для разработчиков от Slurm.io
    Урок 1: Введение в
    Урок 1: Введение в …

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  12. 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/

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    5. На время перезапуска на другие поды приходит больше запросов.
    6. GOTO 1
    🤡
    Неправильно настроенная liveness-проба под нагрузкой убьёт
    приложение, под за подом!

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  21. А как масштабироваться-то?
    Kubernetes Horizontal Pod Autoscaler!
    Разбираем автоске
    Разбираем автоске…

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

    View full-size slide

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

    View full-size slide

  23. 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/

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  28. 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/

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide