Jak uzyskać dostęp do interfejsu JMX w dockerze z zewnątrz?

Próbuję zdalnie monitorować JVM w dockerze. Konfiguracja wygląda tak:

  • Maszyna 1: uruchamia JVM (w moim przypadku działa kafka) w dockerze na maszynie ubuntu; IP tej maszyny to 10.0.1.201; aplikacja uruchomiona w dockerze to 172.17.0.85.

  • Maszyna 2: uruchamia monitorowanie JMX

Zauważ, że gdy uruchamiam monitorowanie JMX z maszyny 2, to nie działa z wersją następującego błędu (uwaga: ten sam błąd występuje, gdy uruchamiam jconsole, jvisualvm, jmxtrans i node-jmx/npm: jmx):

Ślad stosu po awarii wygląda jak poniżej dla każdego z narzędzi monitorujących JMX:

java.rmi.ConnectException: Connection refused to host: 172.17.0.85; nested exception is
    java.net.ConnectException: Operation timed out
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
    (followed by a large stack trace)

Teraz interesujące jest to, że gdy uruchamiam te same narzędzia (jconsole, jvisualvm, jmxtrans i node-jmx/npm:jmx) na tej samej maszynie, na której działa docker (maszyna 1 od góry), monitorowanie JMX działa poprawnie.

Myślę, że to sugeruje, że mój port JMX jest aktywny i działa poprawnie, ale kiedy wykonuję monitorowanie JMX zdalnie (z maszyny 2), wygląda na to, że narzędzie JMX nie rozpoznaje wewnętrznego IP Dockera (172.17.0.85)

Poniżej znajdują się odpowiednie (jak sądzę) elementy konfiguracji sieci na maszynie 1, na której działa monitoring JMX (zwróć uwagę na Docker ip, 172.17.42.1):

docker0   Link encap:Ethernet  HWaddr ...
      inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
      inet6 addr:... Scope:Link
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:6787941 errors:0 dropped:0 overruns:0 frame:0
      TX packets:4875190 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0
      RX bytes:1907319636 (1.9 GB)  TX bytes:639691630 (639.6 MB)

wlan0     Link encap:Ethernet  HWaddr ... 
      inet addr:10.0.1.201  Bcast:10.0.1.255  Mask:255.255.255.0
      inet6 addr:... Scope:Link
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:4054252 errors:0 dropped:66 overruns:0 frame:0
      TX packets:2447230 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1000
      RX bytes:2421399498 (2.4 GB)  TX bytes:1672522315 (1.6 GB)

I to są odpowiednie elementy konfiguracji sieci na zdalnej maszynie (maszyna 2), z której dostaję błędy JMX:

lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    options=3<RXCSUM,TXCSUM>
    inet6 ::1 prefixlen 128 
    inet 127.0.0.1 netmask 0xff000000 
    inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 
    nd6 options=1<PERFORMNUD>

en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    ether .... 
    inet6 ....%en1 prefixlen 64 scopeid 0x5 
    inet 10.0.1.203 netmask 0xffffff00 broadcast 10.0.1.255
    nd6 options=1<PERFORMNUD>
    media: autoselect
    status: active
Author: Jacek Laskowski, 2015-07-07

4 answers

Dla kompletności zadziałało następujące rozwiązanie. JVM powinien być uruchomiony z określonymi parametrami ustalonymi w celu umożliwienia zdalnego monitorowania docker JMX były następujące:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.rmi.port=<PORT>
-Djava.rmi.server.hostname=<IP>

where:

<IP> is the IP address of the host that where you executed 'docker run'
<PORT> is the port that must be published from docker where the JVM's JMX port is configured (docker run --publish 7203:7203, for example where PORT is 7203)

Gdy to zrobisz, powinieneś być w stanie wykonać monitorowanie JMX (jmxtrans, node-jmx, jconsole, itp.) z lokalnej lub zdalnej maszyny.

Podziękowania dla@Chris-Heald za bardzo szybką i prostą naprawę!

 26
Author: Eric Broda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:06

Stwierdziłem, że próba skonfigurowania JMX przez RMI jest bolesna, zwłaszcza z powodu -Djava.rmi.server.hostname=<IP>, które musisz określić przy starcie. Nasze obrazy Dockera uruchamiamy w aplikacji Kubernetes, gdzie wszystko jest dynamiczne.

Skończyłem używając JMXMP zamiast RMI, ponieważ wymaga to tylko jednego otwartego portu TCP i no hostname.

Mój obecny projekt używa sprężyny, którą można skonfigurować dodając to:

<bean id="serverConnector"
    class="org.springframework.jmx.support.ConnectorServerFactoryBean"/>

(poza Springiem musisz skonfigurować własny serwer JMXConncetorServer, aby to zrobić praca)

Wraz z tą zależnością (ponieważ JMXMP jest opcjonalnym rozszerzeniem, a nie częścią JDK):

<dependency>
    <groupId>org.glassfish.main.external</groupId>
    <artifactId>jmxremote_optional-repackaged</artifactId>
    <version>4.1.1</version>
</dependency>

I musisz dodać ten sam jar swojej ścieżki klasowej podczas uruchamiania JVisualVM, aby połączyć się przez JMXMP:

jvisualvm -cp "$JAVA_HOME/lib/tools.jar:<your_path>/jmxremote_optional-repackaged-4.1.1.jar"

Następnie połącz za pomocą następującego ciągu połączeń:

service:jmx:jmxmp://<url:port>

(domyślny port to 9875)

 5
Author: Morten Berg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-19 19:57:01

Stworzyłem Projekt GitHub, który zawiera gotową implementację JMX z kontenera Dockera.

Zawiera Dockerfile z odpowiednim entrypoint.sh i docker-compose.yml dla łatwego wdrożenia.

 3
Author: cstroe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-23 10:47:35

Dla środowiska dev możesz ustawić java.rmi.server.hostname na catch-all adres IP 0.0.0.0

Przykład:

 -Djava.rmi.server.hostname=0.0.0.0 \
                -Dcom.sun.management.jmxremote \
                -Dcom.sun.management.jmxremote.port=${JMX_PORT} \
                -Dcom.sun.management.jmxremote.rmi.port=${JMX_PORT} \
                -Dcom.sun.management.jmxremote.local.only=false \
                -Dcom.sun.management.jmxremote.authenticate=false \
                -Dcom.sun.management.jmxremote.ssl=false
 3
Author: Serge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-17 09:03:59