2019年5月27日月曜日

Windows の Docker Desktop(with Kubernetes)に Eclipse Che をデプロイした

とりあえず、Eclipse Che が何かとか、アーキテクチャーとか、細かい用語とかは後回しにして、 Eclipse Che をローカル PC 上で動かす。

ワークスペース作成画面の表示まで確認できたので作業記録をのこす。

環境

  • OS: Windows 10 Pro
  • Docker: Docker version 18.09.2, build 6247962
  • Docker Desktop の Kubernetes を使う感じで

Docker Desktop の設定

Docker Desktop のタスクトレイアイコンを右クリック -> Settings で、 Docker Desktop の設定を行う。

マシン性能の設定

マシン性能を求められるので、それなりの性能に設定。

  1. Advanced タブ内の以下の項目を設定
    • CPUs: 4
    • Memory: 10240MB
    • Swap: 1024MB
    • Disk image max size: 64GB

Deploying single-user Che to Kubernetes | Eclipse Che Documentation では CPU 2, RAM 4 GB に設定されている。今回は倍程度に設定した。

Kubernetes の設定

Kubernetes の有効化

  1. Kubernetes タブ内の Enable Kubernetes のチェックを入れる
  2. Apply ボタンを押下すると Kubernetes cluster installation のダイアログが表示されるので Install ボタンを押す

...けーっこう時間かかりますね。

インストールと起動が成功すると、こんな感じで Kubernetes is running と表示される。

コンテキストの確認

Kubernetes のコンテキストが docker-for-desktop になっていることを確認する。

Kubernetes の動作確認

PowerShell で kubectl get services と入力して以下のように出力されていれば OK.

> kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   11m

Che の環境構築

Deploying single-user Che to Kubernetes | Eclipse Che Documentation の通りに進めて、 Minikube の変わりに docker-for-desktop を使うようにする。

role binding のデプロイ

正直何やっているのかわかんない。

kubectl create clusterrolebinding add-on-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default

Helm のインストール

今回は Chocolatey でインストールした。PowerShell を管理者で開いて下記コマンドを実行。

choco install kubernetes-helm

ユーザーコンテキストの設定

今回はデフォルトコンテキスト(docker-for-desktop)でいいから何もしない。

クラスターに tiller をインストール

この辺りも何やっているのかわかんない...。

kubectl create serviceaccount tiller --namespace kube-system
wget https://raw.githubusercontent.com/eclipse/che/0ce04088634d979b4f6372dceb970b35b910a7e1/deploy/kubernetes/helm/che/tiller-rbac.yaml -OutFile ./tiller-rbac.yaml
kubectl apply -f ./tiller-rbac.yaml
helm init --service-account tiller --wait

デプロイ

ソース取得

設定ファイル類(yaml) が必要なので、ソース一式を clone する。

git clone https://github.com/eclipse/che.git

デプロイコマンドを実行

cd CHE_ROOT/deploy/kubernetes/helm/che
helm dependency update
helm upgrade --install che --namespace che ./

helm upgrade の時点で次のエラーが発生した。

Release "che" does not exist. Installing it now.
Error: validation failed: error validating "": error validating data: [unknown object type "nil" in ConfigMap.data.CHE_INFRA_KUBERNETES_NAMESPACE, unknown object type "nil" in ConfigMap.data.CHE_LOGGER_CONFIG, unknown object type "nil" in ConfigMap.data.CHE_OAUTH_GITHUB_CLIENTID, unknown object type "nil" in ConfigMap.data.CHE_OAUTH_GITHUB_CLIENTSECRET, unknown object type "nil" in ConfigMap.data.CHE_WORKSPACE_HTTPS__PROXY, unknown object type "nil" in ConfigMap.data.CHE_WORKSPACE_HTTP__PROXY, unknown object type "nil" in ConfigMap.data.CHE_WORKSPACE_NO__PROXY]

エラーメッセージで検索したら、Helm 2.14.0 から空文字列が invalid になるらしい issue が見つかった。 (Helm install v2.14.0 "validation failed" error when using a template variable with value "" - helm/helm)

Helm をダウングレードする。

choco upgrade kubernetes-helm --version 2.13.1 --allow-downgrade

サーバー側の Helm はまだ 2.14.0 のままだから入れ直し。

helm reset --force
helm init --service-account tiller --wait

もういちどデプロイに挑戦。

helm upgrade --install che --namespace che ./

上手く言ったっぽい。 以下のような出力が得られた。

> helm upgrade --install che --namespace che .
Release "che" does not exist. Installing it now.
NAME:   che
LAST DEPLOYED: Mon May 27 04:29:16 2019
NAMESPACE: che
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME  DATA  AGE
che   52    0s

==> v1/PersistentVolumeClaim
NAME             STATUS   VOLUME    CAPACITY  ACCESS MODES  STORAGECLASS  AGE
che-data-volume  Pending  hostpath  0s

==> v1/Pod(related)
NAME                 READY  STATUS       RESTARTS  AGE
che-865f8c767-dpxff  0/1    Terminating  0         11m
che-865f8c767-fn8n5  0/1    Pending      0         0s

==> v1/Service
NAME      TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)            AGE
che-host  ClusterIP  10.106.203.150  <none>       8080/TCP,8087/TCP  0s

==> v1/ServiceAccount
NAME  SECRETS  AGE
che   1        0s

==> v1beta1/ClusterRoleBinding
NAME                         AGE
che-che-clusterrole-binding  0s

==> v1beta1/Deployment
NAME  READY  UP-TO-DATE  AVAILABLE  AGE
che   0/1    1           0          0s

==> v1beta1/Ingress
NAME         HOSTS                          ADDRESS  PORTS  AGE
che-ingress  che-che.192.168.99.100.nip.io  80       0s

...ここからどうやって Che サーバーに接続すればいいのかわからない。

再挑戦

Running Eclipse Che on Kubernetes using Docker Desktop for mac あたりを真似すればいけそうなのでやってみる。

ingress-nginx をインストール

helm で ingress-nginx をインストール。

helm install stable/nginx-ingress --name ingress-nginx --namespace ingress-nginx --set rbac.create=true

ループバックアドレスを登録

ingress-nginx の LoadBalancer の CLUSTER-IP を確認する。

> kubectl get services --namespace ingress-nginx
NAME       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
ingress-nginx-nginx-ingress-controller        LoadBalancer   10.100.110.35   localhost     80:30627/TCP,443:31390/TCP   29s
ingress-nginx-nginx-ingress-default-backend   ClusterIP      10.109.12.145   <none>        80/TCP                       29s

Windows のループバックアドレス設定。

netsh interface ip add address Loopback 10.100.110.35 255.255.255.255

※ 10.106.203.150 は、 kubectl get services ... で確認した CLUSTER-IP を指定。

Che の構成情報(?)更新

value.yaml を書き直して che を入れなおす

cd CHE_ROOT/deploy/kubernetes/helm/che
sed.exe -i -e 's/  cheNamespace: \"\"/  cheNamespace: ""che""/' .\values.yaml
sed.exe -i -e 's/  cheWorkspacesNamespace: \"\"/  cheWorkspacesNamespace: ""che""/' .\values.yaml
sed.exe -i -e 's/  ingressDomain: 192.168.99.100.nip.io/  ingressDomain: 10.100.110.35.nip.io/' .\values.yaml
helm dependency update
helm upgrade --install che --namespace che .

http://<cheNamespace>-<cheWorkspacesNamespace>.<ingressDomain> でアクセス可能になるようだ。

Che へ接続

start http://che-che.10.100.110.35.nip.io

Che のワークスペース作成画面が表示された。

とりあえず、今日はここまで。

参考資料

2019年4月2日火曜日

Maven で Java プロジェクト作成から jdb デバッグするまで

環境

  • OS: Windows 10 Pro
  • シェル: Windows PowerShell
  • Java: java version "1.8.0_201"
  • Maven: Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T03:41:47+09:00)

プロジェクト作成

mvn archetype:generate -DarchetypeArtifactId=maven -archetype-quickstart -DarchetypeVersion="1.4" を実行することで、対話的にプロジェクト情報を設定できる。

> mvn archetype:generate -DarchetypeArtifactId=maven -archetype-quickstart -DarchetypeVersion="1.4"
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.0.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.0.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
Define value for property 'groupId': jp.dip.oyasirazu.study.maven
Define value for property 'artifactId': firststep
Define value for property 'version' 1.0-SNAPSHOT: :
Define value for property 'package' jp.dip.oyasirazu.study.maven: : jp.dip.oyasirazu.study.maven.firststep
Confirm properties configuration:
groupId: jp.dip.oyasirazu.study.maven
artifactId: firststep
version: 1.0-SNAPSHOT
package: jp.dip.oyasirazu.study.maven.firststep
 Y: : y
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: maven-archetype-quickstart:1.4
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: jp.dip.oyasirazu.study.maven
[INFO] Parameter: artifactId, Value: firststep
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: jp.dip.oyasirazu.study.maven.firststep
[INFO] Parameter: packageInPathFormat, Value: jp/dip/oyasirazu/study/maven/firststep
[INFO] Parameter: package, Value: jp.dip.oyasirazu.study.maven.firststep
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: groupId, Value: jp.dip.oyasirazu.study.maven
[INFO] Parameter: artifactId, Value: firststep
[INFO] Project created from Archetype in dir: C:\Users\mikoto\project\MiscellaneousStudy\java\Maven\first_step\firststep
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  40.167 s
[INFO] Finished at: 2019-04-02T05:32:01+09:00
[INFO] ------------------------------------------------------------------------

ビルド

作成したプロジェクトディレクトリで mvn package を実行すると、コンパイル・テスト・jar 作成までやってくれる。

> cd \PATH\TO\firststep
> mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------< jp.dip.oyasirazu.study.maven:firststep >---------------
[INFO] Building firststep 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ firststep ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\Users\mikoto\project\MiscellaneousStudy\java\Maven\first_step\firststep\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ firststep ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\Users\mikoto\project\MiscellaneousStudy\java\Maven\first_step\firststep\target\classes
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ firststep ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\Users\mikoto\project\MiscellaneousStudy\java\Maven\first_step\firststep\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ firststep ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\Users\mikoto\project\MiscellaneousStudy\java\Maven\first_step\firststep\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ firststep ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running jp.dip.oyasirazu.study.maven.firststep.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.02 s - in jp.dip.oyasirazu.study.maven.firststep.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ firststep ---
[INFO] Building jar: C:\Users\mikoto\project\MiscellaneousStudy\java\Maven\first_step\firststep\target\firststep-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.104 s
[INFO] Finished at: 2019-04-02T05:46:55+09:00
[INFO] ------------------------------------------------------------------------

デバッグ

テストでデバッグしたい場合は、 mvn "-Dmaven.surefire.debug" test を実行する。

> cd \PATH\TO\firststep
> mvn "-Dmaven.surefire.debug" test
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------< jp.dip.oyasirazu.study.maven:firststep >---------------
[INFO] Building firststep 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ firststep ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\Users\mikoto\project\MiscellaneousStudy\java\Maven\first_step\firststep\s
rc\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ firststep ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ firststep ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\Users\mikoto\project\MiscellaneousStudy\java\Maven\first_step\firststep\s
rc\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ firststep ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ firststep ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Listening for transport dt_socket at address: 5005

localhost:5005 で待ち受けるので、 jdb で接続する。

> cd \PATH\TO\firststep
> jdb -sourcepath .\src\test\java -connect com.sun.jdi.SocketAttach:hostname=localhost,port=5005
捕捉されないjava.lang.Throwableの設定
遅延した捕捉されないjava.lang.Throwableの設定
jdbの初期化中...
>
VMが開始されました: 現在のコール・スタックにフレームがありません

main[1] stop in jp.dip.oyasirazu.study.maven.firststep.AppTest.shouldAnswerWithTrue
遅延したブレークポイントjp.dip.oyasirazu.study.maven.firststep.AppTest.shouldAnswerWithTrue。
クラスがロードされた後に設定されます。
main[1] run
> 遅延したブレークポイントjp.dip.oyasirazu.study.maven.firststep.AppTest.shouldAnswerWithTrueの設定

ヒットしたブレークポイント: "スレッド=main", jp.dip.oyasirazu.study.maven.firststep.AppTest.shouldAnswerWithTrue()、行=18 bci=0
18            assertTrue( true );

main[1] list
14         */
15        @Test
16        public void shouldAnswerWithTrue()
17        {
18 =>         assertTrue( true );
19        }
20    }
main[1] cont
>
アプリケーションが終了しました

以上。

参考資料

2019年3月31日日曜日

jdb でリモートデバッグを行う

貰った Java プログラムが不可解な動きをするので、それを追うために jdb を使うことにした。

幸いにも今までそのレベルの問題に遭遇したことが無かったため、 jdb の使い方自体知らない。

勉強したのでその内容を記す。

環境

  • OS: Windows 10 Pro
  • Java: java version "1.8.0_201"

Java プログラム

テスト用にこんなプログラムを用意。

/**
 * Main
 */
public class Main {
    public static void main(String[] args) {
        String message = getMessage();
        System.out.printf("Hello, %s!\n", message);
    }

    private static String getMessage() {
        return "mikoto2000";
    }
}

コンパイル

-g オプションを付けてコンパイル。

javac -g .\Main.java

Main.class が生成される。

デバッグ

jdb から対象プログラムを直接実行する方法と、 jdb 接続まちしているプログラムに jdb で接続する方法(リモートデバッグ)がある。

jdb から直接実行

jdb の引数にクラスパスとクラス名を渡して実行。

> jdb -classpath . Main
jdbの初期化中...
> stop in Main.main
遅延したブレークポイントMain.main。
クラスがロードされた後に設定されます。
> run
Mainの実行
捕捉されないjava.lang.Throwableの設定
遅延した捕捉されないjava.lang.Throwableの設定
>
VMが開始されました: 遅延したブレークポイントMain.mainの設定

ヒットしたブレークポイント: "スレッド=main", Main.main()、行=6 bci=0
6            String message = getMessage();

main[1] next
>
ステップが完了しました: "スレッド=main", Main.main()、行=7 bci=4
7            System.out.printf("Hello, %s!\n", message);

main[1] cont
> Hello, mikoto2000!

アプリケーションが終了しました

リモートデバッグ

「TCP ポート 1234 で jdb を待ち受けて、 jdb が接続されるまでプログラムをスタートしない」 としようとする場合、次のような手順を実施。

デバッグ対象プログラム実行

以下コマンドでデバッグ対象プログラムを実行する。

java -cp . -agentlib:jdwp=transport=dt_socket,server=y,address=1234 Main
  • agentlib:jdwp: Java Debug Wire Protocol を使用してデバッグしますよと宣言
  • transport=dt_socket: トランスポートに使うライブラリの指定
  • server=y: サーバーを起動して待ち受けますよという宣言
  • address=1234: 1234 番ポートで待ち受けますよと宣言

デバッガ実行

以下コマンドでデバッガを実行する。

jdb -attach 1234

Windows の場合は、 SocketAttach コネクタで接続する必要がある。

jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=1234

あとは、直接プログラムを起動するのと同じですね。

以上。

細かい使い方は参考資料を参照のこと。

参考資料