JMX в Kubernetes
JMX (Java Management Extensions) — технология, с помощью которой можно подключится к java-процессу через сокет и посмотреть использование ресурсов, снять дамп памяти или даже поменять какие-нибудь значения в памяти через управляемые ресурсы (MBeans). Есть два плюс-минус стандартных инструмента для этого: jconsole
и jvisualvm
.
Но сейчас нельзя просто так взять и подключиться к чему-то по сокету — все в кубере лежит. А поды еще и со сгенерированными айдишниками. Сначала надо получить id пода от желаемого сервиса:
POD=`kubectl -n $NAMESPACE get pods -l app=$APPNAME -o name`
флаг -l
фильтрует по метке пода, -o
— оставляет в выводе только имя.
Потом получаем случайный порт (можно заморочиться и проверить, что он свободен):
PORT=`echo $(( $RANDOM % (65550 - 15000) + 15000))`
# или
PORT=`shuf -i 15000-65550 -n 1`
Перенаправляем порт ($JMX_PORT
— номер порта, через который JMX выставлен локально в поде):
kubectl -n $NAMESPACE port-forward $POD $PORT:$JMX_PORT &
процесс запускается в фоне, и перенаправление будет работать только пока он запущен.
Наконец, запускаем jconsole
или jvisualvm
… и получаем облом из-за того, что удаленный порт-то не настоящий: нужно больше одного порта для подключения через RMI. Это можно вылечить работой через JMXMP-протокол, но нужно будет добавить его jar и в приложение, и в клиент. А после этого запустить так:
jvisualvm -cp:a jmxremote_optional.jar --openjmx "service:jmx:jmxmp://localhost:$PORT"
Или можно просто добавить в настройки приложения -Djava.rmi.server.hostname=127.0.0.1
и подключаться так:
jvisualvm --openjmx "localhost:$PORT"
PROFIT! Все это, разумеется, можно накидать в баш-скрипт, чтобы не запоминать, а указывать только namespace и имя сервиса.