web-dev-qa-db-ja.com

外部からdockerのJMXインターフェイスにアクセスする方法は?

Dockerで実行されているJVMをリモートで監視しようとしています。設定は次のようになります。

  • マシン1:UbuntuマシンのdockerでJVM(私の場合はkafkaを実行)を実行します。このマシンのIPは10.0.1.201です。 dockerで実行されているアプリケーションは172.17.0.85です。

  • マシン2:JMXモニタリングを実行します

マシン2からJMXモニタリングを実行すると、次のバージョンのエラーで失敗することに注意してください(注:jconsole、jvisualvm、jmxtrans、およびnode-jmx/npm:jmxを実行すると同じエラーが発生します)。

失敗時のスタックトレースは、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)

ここで興味深いのは、同じツール(jconsole、jvisualvm、jmxtrans、およびnode-jmx/npm:jmx)をdocker(上からのマシン1)を実行している同じマシンで実行すると、JMXモニタリングが正しく機能することです。

これは、JMXポートがアクティブで正常に動作していることを示唆しているが、JMXモニタリングをリモートで実行すると(マシン2から)、JMXツールが内部ドッカーIP(172.17.0.85)を認識しないように見える

以下は、JMX監視が機能するマシン1の関連する(と思う)ネットワーク構成要素です(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)

これは、JMXエラーが発生するリモートマシン(マシン2)の関連するネットワーク構成要素です。

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
25
Eric Broda

完全を期すために、次のソリューションが機能しました。 JVMは、リモートDocker JMXモニタリングを有効にするために確立された特定のパラメーターを使用して実行する必要がありました。

-Dcom.Sun.management.jmxremote
-Dcom.Sun.management.jmxremote.authenticate=false
-Dcom.Sun.management.jmxremote.ssl=false
-Dcom.Sun.management.jmxremote.port=<PORT>
-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). Both `port` and `rmi.port` can be the same. 

これが完了すると、ローカルマシンまたはリモートマシンからJMXモニタリング(jmxtrans、node-jmx、jconsoleなど)を実行できるようになります。

@ Chris-Heald に感謝します。

34
Eric Broda

開発環境では、Java.rmi.server.hostnameキャッチオールIPアドレス 0.0.0.0

例:

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

RMIを介してJMXをセットアップしようとすると、特に-Djava.rmi.server.hostname=<IP>起動時に指定する必要があります。すべてが動的なKubernetesでdockerイメージを実行しています。

これは、RMIの代わりにJMXMPを使用することになりました。これは、1つだけTCPポートを開き、ホスト名を必要としないためです。

私の現在のプロジェクトではSpringを使用していますが、これを追加することで構成できます。

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

(Spring以外では、この機能を使用するには独自のJMXConncetorServerをセットアップする必要があります)

この依存関係とともに(JMXMPはオプションの拡張機能であり、JDKの一部ではないため):

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

また、JMXMP経由で接続するには、JVisualVMを起動するときに同じjarをクラスパスに追加する必要があります。

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

次に、次の接続文字列で接続します。

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

(デフォルトのポートは9875です)

5
Morten Berg

かなり掘り下げた後、私はこの構成を見つけました

-Dcom.Sun.management.jmxremote.ssl=false 
-Dcom.Sun.management.jmxremote.authenticate=false 
-Dcom.Sun.management.jmxremote.port=1098
-Dcom.Sun.management.jmxremote.rmi.port=1098
-Djava.rmi.server.hostname=localhost
-Dcom.Sun.management.jmxremote.local.only=false

上記の他との違いは、Java.rmi.server.hostname0.0.0.0の代わりにlocalhostに設定されることです。

0
snovelli