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

Java в контейнере - особенности эксплуатации

aragozin
October 14, 2023

Java в контейнере - особенности эксплуатации

Java и контейнеры Linux - технологии совсем не новые, да и использовать их вместе начали отнюдь не вчера. Многие и нас имеют такой стек в промышленной эксплуатации, и вроде бы даже всё работает ...
Но, если что то может пойти не так, надо ставить вопрос не "если", а "когда".
Что же может пойти не так в контейнеризованной JVM? Чтобы дать некоторые ответы на этот вопрос капнуть придётся глубоко.
Доклад будут освещены нюансы работы Linux, контейнеризации и JVM друг с другом.
Специалисты Linux смогут узнать новое о JVM, а джависты и Linux.

aragozin

October 14, 2023
Tweet

More Decks by aragozin

Other Decks in Technology

Transcript

  1. Алексей Рагозин
    JAVA В КОНТЕЙНЕРЕ
    ОСОБЕННОСТИ
    ЭКСПЛУАТАЦИИ

    View full-size slide

  2. Кто есть кто в виртуализации?
    Гипервизор – среда выполнения машинного кода в эмулируемой
    среде, включая эмуляцию периферийных устройств.
    Виртуальная машина – формальное описание
    взаимодействия прикладной программы со средой выполнения.
    Что же такое Lunix контейнер?
    docker, runc, podman, crun, lxc, …
    1

    View full-size slide

  3. Мечта всех времён
    Write
    Once
    Run
    Anywhere
    2

    View full-size slide

  4. Мечта всех времён
    Write Build
    Once
    Run
    Anywhere
    On any Linux
    (with same arch and kernel version)
    2

    View full-size slide

  5. JVM в контейнере
    JVM
    Ядро Linux
    Управлению памятью (heap)
    Много-поточность
    Кросс-платформенный API
    Управлению памятью (virtual
    memory)
    Вытесняющая многозадачность
    Сеть, файлы и прочие API
    namespaces – изоляция сети,
    файловой системы и пр.
    3

    View full-size slide

  6. В докладе
    Память
    ЦПУ
    Файловая система
    Диагностика JVM в условиях контейнеризации
    4

    View full-size slide

  7. Память

    View full-size slide

  8. Память Linux
     “Плоское” адресное пространство процесса
     Память организована в страницы (4k)
    (Есть ещё “huge” страницы, но это другая история)
     Может быть включён файл подкачки (swap)
    5

    View full-size slide

  9. Память Linux процесса
    С точки зрения процесса, диапазон адресов может быть
    - Reserved (SEGFAULT при попытке доступа) -
    - Committed (доступ не приведён к ошибке)
     Страница ещё не привязана (выделение при первом обращении)
     Страница привязана
     Страница в вытеснена в swap (загрузка при обращении)
     Страница в copy on write режиме (копирование при попытки записи)
    - File mapped
    6

    View full-size slide

  10. Память в контейнере Linux
    Всё то же самое + cgroups
    • Лимиты по памяти, CPU и другим ресурсам
    Лимиты на память контейнера
    • Resident memory (Включая отображаемые в память файлы)
    • Resident + Swap memory
    7

    View full-size slide

  11. Память JVM
    Куча (Heap) – основная часть
    Стеки потоков – растут с числом потоков
    NIO Buffers
    Память “нативных” библиотек
    Метаданные и JIT – проблема маленьких JVM
    Накладные расходы JVM
    Специфика
    приложения
    8

    View full-size slide

  12. Память JVM в деталях
    Java Heap
    Young Gen
    Old Gen
    Non-Heap
    JVM Memory
    Native JVM Memory
    Non-JVM Memory (native libraries)
    -Xms/-Xmx
    -Xmn
    Java Process Memory
    Thread Stacks -XX:ThreadStackSize per thread
    NIO Direct Buffers -XX:MaxDirectMemorySize
    Metaspace -XX:MaxMetaspaceSize
    Compressed Class Space-XX:CompressedClassSpaceSize
    Code Cache -XX:ReservedCodeCacheSize
    9

    View full-size slide

  13. Память JVM/Linux
    JVM Memory
    Young Gen -Xmn
    Java Heap
    Old Gen
    -Xms/-Xmx
    Native JVM Memory
    Thread Stacks
    -XX:ThreadStackSize per thread
    NIO
    Direct Buffers -XX:MaxDirectMemorySize
    Metaspace
    -XX:MaxMetaspaceSize
    Compressed Class Space-XX:CompressedClassSpaceSize
    Code Cache
    -XX:ReservedCodeCacheSize
    Non-Heap
    Non-JVM Memory
    (native libraries)
    Linux process memory
    Resident
    Commited
    Virtual
    Untouched
    Swapped out
    10

    View full-size slide

  14. Out of Memory in Linux
    Недостаток ресурсов памяти решается OОMKiller`ом!
    11

    View full-size slide

  15. JVM в контейнере
    JVM детектирует контейнер и лимиты*
    Размер кучи устанавливается по лимиту на память
    -XX:MaxRAMPercentage (по-умолчанию 25%)
    Максимальное число GC потоков выставляется по лимиту CPU
    -XX:ParallelGCThreads
    * - cgroups v2 поддерживаются начиная с Java 17
    12

    View full-size slide

  16. Опция -XshowSettings
    Команда
    java -XshowSettings:system –version
    Показывает информацию о лимитах доступную JVM
    Operating System Metrics:
    Provider: cgroupv1
    Effective CPU Count: 2
    CPU Period: 100000us
    CPU Quota: 150000us
    CPU Shares: -1
    List of Processors, 4 total:
    0 1 2 3
    List of Effective Processors, 4 total:
    0 1 2 3
    List of Memory Nodes, 1 total:
    0
    List of Available Memory Nodes, 1 total:
    0
    Memory Limit: 1.00G
    Memory Soft Limit: Unlimited
    Memory & Swap Limit: 1.50G
    openjdk version "17" 2021-09-14 LTS
    OpenJDK Runtime Environment (build 17+35-LTS)
    OpenJDK 64-Bit Server VM (build 17+35-LTS,
    mixed mode)
    13

    View full-size slide

  17. Сайзинг JVM для контейнера
    Типовое Java приложение
    не требует настроек.
    14

    View full-size slide

  18. Сайзинг JVM для контейнера
    Типовое Java приложение
    не требует настроек.
    (Можно выставить -XX:MaxRAMPercentage побольше)
    14

    View full-size slide

  19. Нужна ли вам память вне хипа?
    Использует ли ваше приложение диск?
    • Да – оставляйте запас для кэша
     Нет – можно оставить настройки по-умолчанию
    15

    View full-size slide

  20. Swap или Resident memory
    Управляйте лимитом на swap
    Ставьте лимит на swap чуть больше чем лимит на память
     При недостатке памяти приложение начнёт страдать, но
     Вы увидите, что проблема с память
     Если это был временный фактор у приложения есть шанс прийти в норму
     Альтернатива – перезагрузка контейнера OMM killer
    16

    View full-size slide

  21. ЦПУ лимиты контейнера
    CPU Limit – верхняя граница использования ЦПУ
    CPU Shares – вес контейнера для планировщика в условиях недостатка ЦПУ
    CPU Set – фиксированные CPU для выполнения
    и прочее опции планировщика
     CPU Limit может быть не целым
     Лимит ЦПУ для контейнера ограничивает GC потоки
    –> что ведёт к увеличение GC пауз
    17

    View full-size slide

  22. Нюансы малых лимитов ЦПУ
    При лимитах меньше 1 CPU приложение может выработать ресурсы ЦПУ в “долг”
    (особенно если хост не нагружен), в следствии чего контейнер будет лишён ЦПУ до
    тех пор, пока среднее использование ЦПУ не уложиться в квоту.
    https://github.com/robusta-dev/alert-explanations/wiki/CPUThrottlingHigh-(Prometheus-Alert)
    18
    T
    200ms
    Over quota
    600ms
    CPU 0.25

    View full-size slide

  23. Файловая система

    View full-size slide

  24. Контейнер и файловая система
    “Linux контейнер – chroot на стероидах.”
    Корневая системы контейнера – overlayfs или аналог
    • Как правило есть лимит на размер
    • Идеосинхрозии posix семантики (например переименование файлов)
    Используйте “точки монтирования” для рабочих директорий и /tmp
    • Более эффективное IO
    • Совместное использование между контейнерами
    • Простой доступ с хоста (например к дампам кучи)
    19

    View full-size slide

  25. Временные файлы JVM
    -Djava.io.tmpdir=… - позволяет использовать альтернативный
    путь для временных файлов
    -XX:PerfDataSaveFile=… - альтернативный путь
    для hsperfdata файла
    20

    View full-size slide

  26. Диагностика JVM

    View full-size slide

  27. Работа с локальным контейнером
    Типовые операции доступны из коробки
     Дамп потоков – jcmd Thread.print
     Дамп памяти – jcmd GC.heap_dump *
     Профилирование – JDK Flight Recorder с использованием jcmd *
    Графические инструменты Visual VM, Mission Control и т.п.
    требуют JMX для полноценной работы!
    * - Путь к дампу указывается в файловой системе контейнера!
    21

    View full-size slide

  28. Особенности JMX
    JVM стандартный протокол
    мониторинга/диагностики JVM.
    Включается опциями
    -Dcom.sun.management.jmxremote
    -Dcom.sun.management.jmxremote.authenticate=
    -Dcom.sun.management.jmxremote.ssl=
    -Dcom.sun.management.jmxremote.port=
    -Dcom.sun.management.jmxremote.rmi.port=
    -Djava.rmi.server.hostname=
    Порт должен быть проброшен из контейнера
    Адрес RMI хоста должен совпадать с внешним
    адресом контейнера
    22

    View full-size slide

  29. Что делать с JMX?
    Стратегии настройки JMX
    Настройка JMX на публичный IP
    необходимо знать IP
    Настройка IP на туннельный доступ
    необходимо уметь доступ к туннелю
    прямой доступ к JMX работать не будет
    https://blog.ragozin.info/2023/09/curse-of-jmx.html
    Радикальные решения
    Jolokia – JVM over HTTP
    https://jolokia.org/
    SJK JMX proxy
    https://github.com/aragozin/jvm-tools/
    (позволяет включать JMX без рестарта,
    через консоль контейнера)
    23

    View full-size slide

  30. Диагностика JMX
    SJK – https://github.com/aragozin/jvm-tools
    sjk.jar mxping -s …
    Детальная диагностика JMX хендшейка с распечаткой адресов
    > java -jar sjk.jar mxping -s 127.0.0.1:34000
    SJK is running on: OpenJDK 64-Bit Server VM 25.275-b01 (BellSoft)
    Java home: C:\Java\jdk1.8.0_275+1_bellsoft_x64\jre
    Try to connect via TLS
    Establishing connection to 127.0.0.1:34000
    Failed to connect using TLS: java.rmi.ConnectIOException: error during JRMP connection establishment;
    nested exception is:
    javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
    Try to use plain socket
    Establishing connection to 127.0.0.1:34000
    Establishing connection to 192.168.100.1:34000
    Remote VM: OpenJDK 64-Bit Server VM 25.275-b01 (BellSoft)
    24

    View full-size slide

  31. Стоит ли JMX этой боли? 25
    Мониторинг
     Не стоит
     Prometheus JMX Exporter, Sprinf Micrometer и п.р.
    Диагностика/профилирование
     Да, если вы хотите использовать VisualVM, MisssionControl и п.р.

    View full-size slide

  32. Заключение

    View full-size slide

  33. Заключение
    Позитив
     Современная JVM неплохо адаптировалась к реалиям контейнеров
     -XX:MaxRAMPercentage – удобный способ сайзинга кучи относительно
    лимитов контейнера
     jcmd позволяет работать с локально запущенными контейнерами
    Негатив
     JMX и диагностика – очень сложна в настройке
     Новые сценарии отказов (превышение лимитов)
     Когнитивный барьер: нужно учить cgroup и очередные диалекты yaml
    26

    View full-size slide

  34. Ссылки
    Доклад JVM и Linux - особенности эксплуатации
    https://habr.com/en/companies/oleg-bunin/articles/358520/
    Поисковик по опциям JVM
    https://chriswhocodes.com/
    Гайд по JMX в контейнере
    https://blog.ragozin.info/2023/09/curse-of-jmx.html
    Статься по тротлингу ЦПУ
    https://github.com/robusta-dev/alert-explanations/wiki/CPUThrottlingHigh-(Prometheus-Alert)
    Jolokia – JMX over HTTP
    https://jolokia.org/
    Моя статья “JVM in Linux containers, surviving the isolation”
    https://bell-sw.com/announcements/2020/10/28/JVM-in-Linux-containers-surviving-the-isolation/
    27

    View full-size slide

  35. Спасибо!
    Алексей Рагозин
    Email: [email protected]
    Блог: blog.ragozin.info
    Github: https://github.com/aragozin
    Митапы: https://aragozin.timepad.ru

    View full-size slide