Мониторинг Java JVM в Kubernetes с использованием JMXMP (серия из 2 частей)
В дополнение к мониторингу на основе журналов или агентов, иногда необходимо в интерактивном режиме проверять поведение Java-приложения, в частности, использование его памяти или процессора. В экосистеме Java часто используются бесплатные инструменты VisualVM или jconsole. Эти инструменты также позволяют просматривать использование потоков и интерактивно детализировать/фильтровать.
В этом сообщении объясняются шаги, необходимые для ручной проверки Java-приложения с использованием протокола JMXMP в кластере Kubernetes. Часть 1 посвящена тому, как сделать приложение, подлежащее мониторингу, видимым с помощью JMXMP. В части 2 обсуждается, как добавить VisualVM в набор (аналогичные методы применяются к другим инструментам мониторинга)
А как насчет RMI?
Раскрытие протокола RMI по умолчанию чрезвычайно болезненно из-за того, как он обрабатывает порты и требует обратного канала. Общее мнение таково: не беспокойтесь. Потратив впустую пару дней, я от всего сердца соглашаюсь.
Включение мониторинга JMXMP
Самый простой способ включить мониторинг – это создать порт мониторинга самостоятельно. Например, в веб-интерфейсе добавьте следующее, чтобы открыть порт 1098 для мониторинга JMXMP:
try { // Get the MBean server for monitoring/controlling the JVM MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // Create a JMXMP connector server JMXServiceURL url = new JMXServiceURL("jmxmp", "localhost", 1098); JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); cs.start(); } catch (Exception e) { e.printStackTrace(); }
Для компиляции этого кода вам потребуется включить реализацию JMXMP. Если вы используете Maven, добавьте следующее в свой pom.xml
org.glassfish.external opendmk_jmxremote_optional_jar 1.0-b01-ea
В реальной жизни,
- скорее всего, вы будете использовать переменную среды, чтобы настроить номер порта с помощью карты конфигурации или секрета, и, возможно, не запускать соединитель, если такой переменной нет.
- Возможно, вы захотите обезопасить соединение. Для своих собственных целей я использовал белый список IP-адресов моей рабочей станции разработки в сетевой политике k8s, поэтому я не изучал эту тему дальше. См. https://interlok.adaptris.net/interlok-docs/advanced-jmx.html для примеров того, как это включить.
Особые соображения по созданию контейнера
По умолчанию KubeSail использует IPv6. В процессе отладки этого рецепта мы сочли необходимым добавить следующие флаги Java в команду точки входа Java контейнера Docker.
-Djava.net.preferIPv4Stack=true -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
(Примечание редактора – Мы будем проверять, по-прежнему ли они необходимы.)
Предоставление порта в Kubernetes для рабочего стола Docker
Следующие инструкции были протестированы с новым бэкэндом докера WSL 2, который работает непосредственно в Linux.
Для рабочего стола Docker самый простой способ предоставить доступ к порту – использовать службу балансировки нагрузки. Это позволяет избежать необходимости использовать kubectl на каждом сеансе.
kind: Service apiVersion: v1 metadata: name: myapp spec: selector: app: myapp ports: - protocol: TCP name: http port: 80 targetPort: 8080 - protocol: TCP name: jmx port: 1098 targetPort: 1098 type: LoadBalancer
Это позволяет открыть веб-приложение на http://localhost несмотря на то, что контейнер осуществляет связь через порт 8080, а также открывает канал мониторинга JMX на порту 1098. Вы можете изменить порт в соответствии с вашими потребностями, но targetPort
должен соответствовать тому, что используется отслеживаемым приложением (см. Java выше).
Открытие порта с помощью Kubesail Kubernetes
KubeSail – это доступный управляемый PaaS для запуска приложений Kubernetes. По умолчанию только трафик, поступающий через вход (NGINX), может идти дальше. Поэтому необходимо
- создайте сетевую политику, которая позволяет потоку трафика поступать в контейнер отслеживаемого приложения
- предоставьте порт для мониторинга
Создание сетевой политики
Следующее открывает порт 1098 в приложении для доступа извне и ограничивает внешний доступ к определенному адресу (очевидно, вы бы использовали свой собственный).
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: myapp-allow-jmx spec: podSelector: matchLabels: app: myapp policyTypes: - Ingress ingress: - from: - ipBlock: cidr: 208.77.188.166/32 ports: - protocol: TCP port: 1098
Более сложные темы обсуждаются на этой странице https://www.magalix.com/blog/kubernetes-network-policies-101
Предоставление доступа к порту мониторинга
Самый простой способ – использовать порт узла, который заставляет виртуальную машину открывать порт и предоставлять его внешнему миру. В случае общей службы, такой как Cubesail, существует вероятность того, что выбранный порт конфликтует с другими, и вам потребуется его изменить. Последняя строка (Политика внешнего трафика) необходима для предотвращения выполнения Kubernetes NAT (преобразование сетевых адресов)
kind: Service apiVersion: v1 metadata: name: jmx spec: selector: app: myapp ports: - protocol: TCP port: 1098 targetPort: 1098 nodePort: 30098 type: NodePort externalTrafficPolicy: Local
Получение адреса узла
- Для того чтобы узнать адрес узла, вы можете использовать
kubectl get pod -o wide
- Вы также можете установить инструмент
jq
JSON для запросов и использовать следующий однострочный
kubectl get pod -o json -l 'app=myapp' | jq -r '.items[0].spec.nodeName'
который выведет ip-адрес (54.151.3.??) в примере
- Чтобы проверить, все ли хорошо, вы можете использовать команду.
telnet 54.151.3.?? 300??
Вы получите мусор обратно, но с узнаваемым javax.management.remote.сообщением. Рукопожатие Начать сообщение
строка в начале.
Мониторинг Java JVM в Kubernetes с использованием JMXMP (серия из 2 частей)
Оригинал: “https://dev.to/jflamy/interactive-java-jvm-monitoring-on-kubernetes-part-1-exposing-jmxmp-5c3f”