bit

NATなKVMとJava JPDAデバッグ

技術ネタとしては基本レベルの話ではあるのだが、知らない人は本当に知らなくてちょっと萎えるので、今後の私の負荷を下げるために、NAT経由でのJPDAデバッグの話を書いておく。
# 文章の分かりにくい部分を修正。(2/15)

開発用 Windows PCと試験用 Linux サーバの2台があるとする。
f:id:iwsttty:20140215171050p:plain
図の右のLinux サーバ内には、本番を模したサーバ群が KVM 上に構築されていて、アドレスなど最大限本番環境に揃えるために、NAT経由でオフィスのネットワークにつながっている。NATはLinuxホストOSのiptables で設定している。

それで、開発PCからアプリサーバにつながらない時にチェックポイントは四つ:

  1. Linuxサーバのポートフォワーディング(NAT)設定
  2. アプリサーバの iptables 穴開け
  3. Tomcat JPDA設定
  4. Eclipseの「リモートJavaデバッグ」設定

一つ目のNAT設定はつながらない場合の原因第1位なんだろうけど、全部書くと疲れるので要点を書いておく。

  • LinuxサーバのホストOSの iptables が起動していること。
  • 上図 Linuxサーバホストの eth0 に来たパケットに対し、二つの NAT が入っているか確認。
    • DNAT: 送信先アドレスを、宛先ポート番号に応じて KVM上各サーバのアドレスとポートに変換
    • SNAT: 送信元アドレスを 192.168.0.1 (KVM 内ネットワークのゲートウェイアドレス) に変換

このSNAT設定がないと、KVM上のサーバたちは飛んできたパケットの返し先が分からなくなる。
設定内容はこんな感じ↓。ちなみに iptables のコマンドラインオプションなんか覚えてないので、/etc/sysconfig/iptables を編集して再起動(servie iptables reload)している。

# cat /etc/sysconfig/iptables
# (前略)
*nat
# (中略)
-A PREROUTING -i eth0 -p tcp -m tcp --dport 22101 -j DNAT --to-destination 192.168.0.101:22
-A PREROUTING -i eth0 -p tcp -m tcp --dport  8111 -j DNAT --to-destination 192.168.0.101:80
-A PREROUTING -i eth0 -p tcp -m tcp --dport  9111 -j DNAT --to-destination 192.168.0.101:9000
-A POSTROUTING -d 192.168.0.0/24 -p tcp -m tcp -j SNAT --to-source 192.168.0.1
# (後略)
COMMIT

# service iptables restart

二つ目のアプリサーバの穴開けは、忘れないでねというだけのこと。JPDA ポートはディフォルトは塞がっているはず。

三つ目の JPDA 設定は、agentlib のところが以下のようになるよう頑張るだけ。

# ps -ef |grep java
root    28341    1   1 18:24 ttyS0   00:00:12 /usr/bin/java
   -Djava.util.logging.config.file=/opt/apache-tomcat/conf/logging.properties
   -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
   -agentlib:jdwp=transport=dt_socket,address=9000,server=y,suspend=n
   -Djava.endorsed.dirs=/opt/apache-tomcat/endorsed
   -classpath /opt/apache-tomcat/bin/bootstrap.jar:/opt/apache-tomcat/bin/tomcat-juli.jar
   -Dcatalina.base=/opt/apache-tomcat
   -Dcatalina.home=/opt/apache-tomcat
   -Djava.io.tmpdir=/opt/apache-tomcat/temp org.apache.catalina.startup.Bootstrap start

ちなみにポート番号9000は単に都合で変えているだけなので、必要がないならば変える必要はない。
変える場合は Tomcat の setenv.sh に以下のように書いて、JPDA を開始する。

JPDA_ADDRESS=9000

起動時は catalina.sh jpda start するだけ。catalina.sh start は不要。javaプロセスは一つ。

# netstat -nap | grep 9000
tcp    0    0 0.0.0.0:9000    0.0.0.0:*    LISTEN    28341/java


最後はクライアント側。Eclipseの「デバッグの構成」という設定で、「リモートJavaアプリケーション」を設定する。見れば分かると思うので省略。