2015-07-07 18 views
17

Ich versuche, eine JVM, die im Docker läuft, aus der Ferne zu überwachen. Die Konfiguration sieht wie folgt aus:Wie kann ich von außen auf die JMX-Schnittstelle im Docker zugreifen?

  • Maschine 1: läuft eine JVM (in meinem Fall, läuft kafka) in Docker auf einem Ubuntu-Maschine; Die IP dieser Maschine ist 10.0.1.201; Die Anwendung, die in Docker ausgeführt wird, ist 172.17.0.85.

  • Maschine 2: läuft JMX Überwachung

Beachten Sie, dass, wenn ich JMX Überwachung von 2 Maschine laufen, sie mit einer Version der folgenden Fehler fehlschlägt (Anmerkung: der gleiche Fehler tritt auf, wenn ich jconsole laufen, jvisualvm, jmxtrans und Knoten-JMX/npm: JMX):

der Stack-Trace auf andernfalls sieht etwa wie folgt für jede der JMX-Monitoring-Tools:

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) 

Jetzt ist der interessante Teil, wenn ich die gleichen Werkzeuge (jconsole, jvisualvm, jmxtrans und Knoten-jmx/npm: jmx) auf der gleichen Maschine, die Docker (Maschine 1 von oben) läuft laufen die JMX-Überwachung ordnungsgemäß funktioniert.

Ich denke, dies legt nahe, dass mein JMX-Port aktiv ist und ordnungsgemäß funktioniert, sondern dass, wenn ich ausführen JMX Fernüberwachung (von der Maschine 2) sieht es aus wie das JMX-Tool nicht den internen IP Docker erkennen (172.17.0.85)

im Folgenden sind die relevanten (glaube ich) Netzwerk Konfigurationselemente auf der Maschine 1, wo JMX Überwachung Arbeiten (den docker ip beachten, 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) 

Und das ist die relevanten Netzwerkkonfigurationselemente auf der Fernbedienung Maschine (Maschine 2), von der ich die JMX-Fehler erhalte:

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 

Antwort

19

Der Vollständigkeit halber hat die folgende Lösung funktioniert. Die JVM sollte mit spezifischen Parametern ausgeführt werden eingerichtet Fern Docker JMX-Überwachung zu ermöglichen, wie folgt waren:

-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) 

Sobald dies erledigt ist, sollten Sie JMX-Überwachung ausführen können, (jmxtrans, node-JMX, jconsole, etc.) von entweder eine lokale oder Remote-Maschine.

Dank @Chris-Heald für die Herstellung einer wirklich schnellen und einfachen Lösung!

+4

Das funktionierte, aber ich musste auch ein Docker Container hinzufügen zu verbinden: '-Dcom.sun.management.jmxremote.port = 1098' und schließen stattdessen an diesen Port' rmi.port' – jamming

+1

' -Djava.rmi.server.hostname = 'war der wichtige Teil für mich. Vielen Dank! –

3

Ich fand, dass der Versuch, JMX über RMI einzurichten, ein Schmerz ist, vor allem wegen der -Djava.rmi.server.hostname=<IP>, die Sie beim Start angeben müssen. Wir führen unsere Docker-Bilder in Kubernetes, wo alles dynamisch ist.

Ich endete mit JMXMP anstelle von RMI, da dies nur einen TCP-Port geöffnet und keinen Hostnamen benötigt.

Mein aktuelles Projekt verwendet Spring, die durch Zugabe dieses konfiguriert werden kann:

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

(Outside Frühling Sie benötigen, um Ihre eigene JMXConncetorServer um einzurichten, um diese Arbeit zu machen)

Zusammen mit diesem Abhängigkeit (seit JMXMP ist eine optionale Erweiterung und nicht ein Teil des JDK):

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

und müssen Sie das gleiche Glas Ihren classpath hinzufügen beim Start jvisualvm i n, um über JMXMP zu verbinden:

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

dann mit der folgenden Verbindungszeichenfolge verbinden:

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

(Standardport ist 9875)

1

Ich habe eine GitHub project, die eine fertige enthält Umsetzung gehen von JMX aus einem Docker-Container.

Es enthält eine Dockerfile mit einer ordnungsgemäßen entrypoint.sh und eine docker-compose.yml für die einfache Bereitstellung.