はじめに
今回は k8s で動いている Java アプリに VisualVM で接続しようと思います。
Java アプリケーションの監視や解析の際に利用するかと思います。
コンテナなので Prometheus でのメトリクス収集が一般的だと思いますが、今回は Java 開発者に使い慣れたツールということで Java 側で用意されているツールを利用します。
※今回は Java アプリケーションを用意せず Jenkins のコンテナに対して実施しました
※JMX や Jenkins は Prometheus でメトリクス収集も可能です
環境情報
Kubernetes:1.18
helm:v3.2
※https://helm.sh/docs/intro/quickstart/
Java:1.8
Jenkins:2.235
Jenkins コンテナ準備
helm で Jenkins コンテナをデプロイします。
まずはデプロイ用にパラメータファイルを作成します。
※Pod への接続は NodePort を利用します
※jmx で接続するポートを今回は 32000 で指定しています
※hostname で指定する IP アドレスは k8s の worker ノードの IP です。以下のコマンドで確認できます。
$ kubectl get nodes --namespace jenkins -o jsonpath="{.items[0].status.addresses[0].address}"
master:
serviceType: NodePort
javaOpts: >
-Djava.rmi.server.hostname=0.0.0.0
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=32000
-Dcom.Sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.rmi.port=32000
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Djava.rmi.server.hostname=192.168.10.51
jmxPort: 32000
また、JMX アクセス用として Service を定義する yaml ファイルを作成します。
apiVersion: v1
kind: Service
metadata:
name: jenkins-jmx
namespace: jenkins
spec:
ports:
- name: jmx
nodePort: 32000
port: 32000
protocol: TCP
targetPort: 32000
selector:
app.kubernetes.io/component: jenkins-master
app.kubernetes.io/instance: jenkins
type: NodePort
早速デプロイします。
※helm pull stable/jenkins
で helm で利用するファイル一式がダウンロードできます
# jenkins namespace 作成
$ kc create ns jenkins
# k8s 接続設定(context)確認
$ kc config current-context
sandbox
# k8s 接続設定(context)の namespace 設定
$ kc config set-context sandbox --namespace jenkins
# k8s 接続先 namespace 確認
$ kc config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* sandbox sandbox sandbox jenkins
# helm repository 追加・レポジトリ情報アップデート
$ helm repo add stable https://kubernetes-charts.storage.googleapis.com
"stable" has been added to your repositories
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. ? Happy Helming!?
# Jenkins コンテナデプロイ
# helm install <リリース名> <Chart 名> -f <parameter file> --namespace <デプロイ先 namespace>
# リリース名:デプロイに対する helm での管理上の名前
# Chart 名:利用するテンプレート名的なもの
$ helm install jenkins stable/jenkins -f values.yaml --namespace jenkins
NAME: jenkins
LAST DEPLOYED: Sat Jul 25 hh:mm:ss 2020
NAMESPACE: jenkins
STATUS: deployed
REVISION: 1
NOTES:
1. Get your 'admin' user password by running:
printf $(kubectl get secret --namespace jenkins jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
2. Get the Jenkins URL to visit by running these commands in the same shell:
export NODE_PORT=$(kubectl get --namespace jenkins -o jsonpath="{.spec.ports[0].nodePort}" services jenkins)
export NODE_IP=$(kubectl get nodes --namespace jenkins -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT/login
3. Login with the password from step 1 and the username: admin
・・・
# デプロイの確認
$ helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
jenkins jenkins 1 2020-MM-DD hh:mm:ss.950509962 +0900 JST deployed jenkins-2.4.1 lts
helm で作成したコンテナには JMX 接続する Service の定義がないため、Service を別途デプロイします。
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jenkins NodePort 10.43.173.89 <none> 8080:31036/TCP 12m
jenkins-agent ClusterIP 10.43.130.60 <none> 50000/TCP 12m
$ kubectl apply -f svc.yaml
service/jenkins-jmx created
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jenkins NodePort 10.43.173.89 <none> 8080:31036/TCP 12m
jenkins-agent ClusterIP 10.43.130.60 <none> 50000/TCP 12m
jenkins-jmx NodePort 10.43.97.82 <none> 32000:32000/TCP 19s
Java VisualVMで接続
さて、起動した Jenkins コンテナに JMX 接続します。
Java VisualVM を起動して、Jenkinsコンテナに接続しましょう。
JDK などにも付属されていますが、今回は pleiades(all in one eclipse) に付属している 1.8 の Java VisualVM で接続します。
https://mergedoc.osdn.jp/
※pleiades 解凍後 java\8\bin\jvisualvm.exe
で起動できます。
- 左メニューの「リモート」を右クリック⇒「リモートホストの追加」をクリック
- 「ホスト名」にjavaOptsで指定したホスト名(IP アドレス)を入力して「了解」をクリック
- 左メニューにリモートマシンが追加されていることを確認
- 左メニューの登録したマシンを右クリック⇒「JMX 接続を追加」をクリック
- 「接続」にホスト名が入力されているので、:(コロン)の後ろに続けてポート番号(今回の場合は 32000)を入力
- 「SSL 接続を使用しない」にチェックを入れて、「了解」をクリック
- 左メニューの登録したリモートマシン配下に接続が追加されていることを確認
- 追加された接続をダブルクリックしてメイン画面に情報が表示されることを確認
接続後の画面
監視タブ
スレッドタブ
おまけに jconsole で接続してみるとこんな感じです。
※jconsole も VisualVM と同じフォルダにバイナリファイルがあります
※接続先は VisualVM で設定した際の接続先と一緒です
まとめ
k8s 上で動作しているコンテナへの VisualVM や jconsole で接続する方法を今回は試してみました。
よくあるポートを開けて接続する方法ではできなかったので以下を追加して設定しています。
- java の起動オプション(javaOpts)に hostname を追加し、Worker ノードの IP アドレスを設定
- jmx で接続するポートと Nodeport で開放するポートを同じ値にする
Prometheus ではなく使い慣れたツールでの接続を行う際の参考にしてください。