OpenShift local と仮想マシンマネージャーのスナップショットを組み合せると便利です

Linux 上の OpenShift local では KVM が利用されているようなので、仮想マシンマネージャーのスナップショット機能が活用できます。


ここではスナップショットを取得後に OpenShift local を起動し、適当なアプリを導入後にスナップショットを戻すことでアプリ導入前に戻ることを確認してみます。


事前作業としてスナップショットを取得

  • 予めスナップショットを取得しておきます
     (補足)crc を開き、[表示] メニューにある [スナップショット] を選択すると目的の画面が表示されます。


(補足)スナップショットについては以下のドキュメントも参考になるかと思います。

access.redhat.com


OpenShift local の作業

  • OpenShift local を起動します
$ crc start
WARN A new version (2.9.0) has been published on https://developers.redhat.com/content-gateway/file/pub/openshift-v4/clients/crc/2.9.0/crc-linux-amd64.tar.xz 
INFO Checking if running as non-root              
INFO Checking if running inside WSL2              
INFO Checking if crc-admin-helper executable is cached 
INFO Checking for obsolete admin-helper executable 
INFO Checking if running on a supported CPU architecture 
INFO Checking minimum RAM requirements            
INFO Checking if crc executable symlink exists    
INFO Checking if Virtualization is enabled        
INFO Checking if KVM is enabled                   
INFO Checking if libvirt is installed             
INFO Checking if user is part of libvirt group    
INFO Checking if active user/process is currently part of the libvirt group 
INFO Checking if libvirt daemon is running        
INFO Checking if a supported libvirt version is installed 
INFO Checking if crc-driver-libvirt is installed  
INFO Checking crc daemon systemd socket units     
INFO Checking if systemd-networkd is running      
INFO Checking if NetworkManager is installed      
INFO Checking if NetworkManager service is running 
INFO Checking if dnsmasq configurations file exist for NetworkManager 
INFO Checking if the systemd-resolved service is running 
INFO Checking if /etc/NetworkManager/dispatcher.d/99-crc.sh exists 
INFO Checking if libvirt 'crc' network is available 
INFO Checking if libvirt 'crc' network is active  
INFO Loading bundle: crc_libvirt_4.10.18_amd64... 
INFO Starting CRC VM for OpenShift 4.10.18...     
INFO CRC instance is running with IP 192.168.130.11 
   -- 省略 --


  • OpenShift local が起動したら、適当なアプリを導入します

ここでは以下のブログを参考にスーパーヒーローを用いた処理性能可視化デモアプリ(意味不明)を導入してみます。

developers.redhat.com


  • 手順は簡単で任意のプロジェクトを作成後に以下のコマンドを順次実行するだけです
oc new-project demo
oc apply -f https://raw.githubusercontent.com/quarkusio/quarkus-super-heroes/main/deploy/k8s/java17-openshift.yml


全てのアプリケーションのアイコンが青色になるまで少し待機します。
(以下は未だ途中です)


全てのアプリケーションのアイコンが青色になったら以下のコマンドを実行し、暫く待機します。

oc apply -f https://raw.githubusercontent.com/quarkusio/quarkus-super-heroes/main/deploy/k8s/monitoring-openshift.yml


全てのアプリケーションが起動したら以下のような感じになります。
(すいません。私の環境ではリソース不足で最後まで行きませんでしたので参考にしたブログの画像を張り付けます)


  • OpenShift local を終了します
     (補足)導入したアプリを動かしたい場合は参考にしたブログの内容をご覧ください。
crc stop


スナップショットを元に戻します

  • 先ほど取得したスナップショットを適用すると元に戻ります


  • 警告がダイアログが表示されますが、[はい] ボタンをクリックして適用します


  • 再度、OpenShift local を起動します
crc start


  • 先程作成した demo プロジェクトが存在しないため、状態が元に戻ったことが分かります


まとめ

OpenShift local で検証する際は適当なタイミングでスナップショットを取得しておくと検証環境が変な状態になっても元に戻すことが可能です。これで無茶な検証も心置きなく試すことができますね。


ここまで記述してなんですが、Red Hat Enterprise Linux 8 以降では仮想マシンマネージャーは非推奨になりましたのでご留意ください。

access.redhat.com

access.redhat.com

DeepL の Chrome 拡張機能でウェブページ全体の翻訳を試してみました

DeepL Pro のユーザーなら Chrome 拡張機能でウェブページ全体の翻訳が可能とのことで試してみました。

www.deepl.com

さらにDeepL Proでは、ページを丸ごと翻訳できます。すべてのサイトまたは特定のサイトを翻訳できるように設定するには、拡張機能でDeepL Proのアカウントにログインしてください。DeepL Proにログインしてご利用の場合、ウェブ上の翻訳ツールとデスクトップアプリと同様に万全のデータセキュリティのもとで翻訳が行われます。接続は暗号化され、テキストはすべて翻訳後に削除されます。無料版でも、近日中にページ全体を翻訳できるようになる予定です。DeepLの各種アプリに続き登場した、スピーディかつ快適に翻訳できるDeepLのChrome拡張機能で、さらに効率よく翻訳を進めていただけますように!


事前準備

まずは DeepL Chrome 拡張機能をインストールしたら、右上のメニューより DeepL Pro へログインします。(スクリーンショットはログイン後の画面です)


ウェブページ全体を翻訳

あとは任意の英語のページで翻訳ボタンをクリックするだけです。


結構良い感じに日本語へ翻訳されている気がします。DeepL Pro なら機密情報の翻訳も大丈夫ですね。


まとめ

Chrome ブラウザでデフォルトで有効になっている Google 翻訳でも良い気がしますが、せっかく、DeepL Pro を利用しているのでウェブページ全体の翻訳にも活用してみました。これで英語の製品情報の理解が捗ると良いのですが。

JSF アプリでセッション生成を抑制する方法

JSF アプリの課題

ソースコードとか仕様とか詳細まで確認はできていないのですが、一般的に JSF はステートフルなサービスであるため、JSF アプリの動作としてはどうしてもセッションが生成されてしまうかと思います。


そのため、JSF を用いた Web アプリでログイン前にアクセス可能な画面(ログイン画面、ヘルスチェック用画面など)にアクセスしただけで内部的にセッションが生成されてしまう動作になるかと思います。


解決案

同じ会社の方から教えていただいた情報なのですが、JSF の EL 式による暗黙オブジェクトを用いて画面が表示されるタイミングでセッションを無効化することが可能です。 具体的には下記のように JSF 画面定義の <head> タグ上に #{session.invalidate()} を指定することで対応できます。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core">
#{session.invalidate()}
    <head>
        <title>Test</title>
    </head>
    <body>
        <h1>invalidate テスト</h1>
    </body>
</html> 


上記のように対応することで、JSF 処理が行われた際に内部的には一旦セッションが生成されてしまいますが、画面を表示する時に #{session.invalidate()} 定義によってセッションが破棄される動作となり、結果的に特定画面へアクセスした際にセッションが生成されることを抑制することができます。(一旦生成されているので抑制できていると言い切ってしまうのは微妙ではありますが…)


まとめ

もう JSF の話ではない気もしますが、検索しても参考となる情報が見つからなかったためちょっとした Tips として整理させていただきました。

OpenShift の Pod を動的に見つけて、Pod 上の JBoss EAP の統計情報を CLI で取得する方法

OpenShift の Pod 名は環境によって異なるため、Pod を動的に見つけてその Pod 上で稼働している JBoss EAP の統計情報を CLI で取得するプチ Tips を整理します。

準備作業

  • Pod 情報を確認します
$ oc get pod
NAME                              READY   STATUS      RESTARTS   AGE
eap-app-1-deploy                  0/1     Completed   0          5d21h
eap-app-1-x77tm                   1/1     Running     4          5d21h
eap-app-2-build                   0/1     Completed   0          5d21h
eap-app-build-artifacts-1-build   0/1     Completed   0          5d21h


  • エンドポイントを確認します
$ oc get endpoints
NAME              ENDPOINTS          AGE
eap-app           10.217.0.14:8080   5d21h
eap-app-metrics   10.217.0.14:9799   5d21h
eap-app-ping      10.217.0.14:8888   5d21h


  • アクティブなセッションを生成するために任意のアプリを一回実行します
    (補足)Pod 名を指定し、Pod の中で curl を用いて取得したエンドポイントを呼び出しています。
$ oc rsh eap-app-1-x77tm curl -kv http://10.217.0.14:8080/index.jsf
*   Trying 10.217.0.14...
* TCP_NODELAY set
* Connected to 10.217.0.14 (10.217.0.14) port 8080 (#0)

   -- 省略 --

</html>


JBoss EAP のセッション数を取得

  • Running 状態の Pod を選んで JBoss EAP のアクティブセッション数(active-sessions)を取得します
    (補足)ROOT.war の箇所は利用するアプリに合わせて適宜読み替えてください。
$ oc rsh `oc get pod | grep Running | awk '{print $1}'` /opt/eap/bin/jboss-cli.sh -c --commands="/deployment=ROOT.war/subsystem=undertow:read-attribute(name=active-sessions)"
{
    "outcome" => "success",
    "result" => 1
}


まとめ

OpenShift や JBoss EAP の機能と言うよりシェルスクリプトでのバッククォート(``)の使い方を説明するようなプチ Tips でした。

podman を用いて Apache Kafka 環境を構築した際のメモ

以下の環境を活用し、podman を用いながら Apache Kafka 環境を構築した際のメモを整理します。

github.com

事前準備


  • サンプル環境をローカルへ Clone します
$ git clone https://github.com/hguerrero/amq-examples.git  
Cloning into 'amq-examples'...
remote: Enumerating objects: 983, done.
remote: Counting objects: 100% (116/116), done.
remote: Compressing objects: 100% (92/92), done.
remote: Total 983 (delta 49), reused 71 (delta 21), pack-reused 867
Receiving objects: 100% (983/983), 2.86 MiB | 2.41 MiB/s, done.
Resolving deltas: 100% (387/387), done.
$ 


$ cd amq-examples/strimzi-all-in-one/ 
$ 
$ ls -la
合計 12
drwxr-xr-x. 1 demo_user demo_user   88  9月 29 11:36 .
drwxr-xr-x. 1 demo_user demo_user  672  9月 29 11:36 ..
-rw-r--r--. 1 demo_user demo_user  499  9月 29 11:36 README.md
-rw-r--r--. 1 demo_user demo_user 2021  9月 29 11:36 docker-compose.yaml
-rw-r--r--. 1 demo_user demo_user  601  9月 29 11:36 log4j.properties
$ 


Apache Kafka の起動

  • podman-compose を実行します(これだけで Apache Kafka が起動します!)
$ podman-compose up
['podman', '--version', '']
using podman version: 4.2.0
** excluding:  set()
['podman', 'network', 'exists', 'strimzi-all-in-one_default']
podman create --name=zookeeper --label io.podman.compose.config-hash=123 --label io.podman.compose.project=strimzi-all-in-one --label io.podman.compose.version=0.0.1 --label com.docker.compose.project=strimzi-all-in-one --label com.docker.compose.project.working_dir=/home/demo_user/opt/training/amq-examples/strimzi-all-in-one --label com.docker.compose.project.config_files=docker-compose.yaml --label com.docker.compose.container-number=1 --label com.docker.compose.service=zookeeper -e LOG_DIR=/tmp/logs --net strimzi-all-in-one_default --network-alias zookeeper -p 2181:2181 strimzi/kafka:0.18.0-kafka-2.5.0 sh -c bin/zookeeper-server-start.sh config/zookeeper.properties
a8da3abb34cc182a4e0f1095027a9633557775e7794b91ab5b6564684e242bdd
exit code: 0
['podman', 'network', 'exists', 'strimzi-all-in-one_default']
podman create --name=kafka --label io.podman.compose.config-hash=123 --label io.podman.compose.project=strimzi-all-in-one --label io.podman.compose.version=0.0.1 --label com.docker.compose.project=strimzi-all-in-one --label com.docker.compose.project.working_dir=/home/demo_user/opt/training/amq-examples/strimzi-all-in-one --label com.docker.compose.project.config_files=docker-compose.yaml --label com.docker.compose.container-number=1 --label com.docker.compose.service=kafka -e LOG_DIR=/tmp/logs -e KAFKA_BROKER_ID=1 -e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT -e KAFKA_LISTENERS=PLAINTEXT://:29092,PLAINTEXT_HOST://:9092 -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 -e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 --net strimzi-all-in-one_default --network-alias kafka -p 9092:9092 strimzi/kafka:0.18.0-kafka-2.5.0 sh -c bin/kafka-server-start.sh config/server.properties --override listener.security.protocol.map=${KAFKA_LISTENER_SECURITY_PROTOCOL_MAP} --override listeners=${KAFKA_LISTENERS} --override advertised.listeners=${KAFKA_ADVERTISED_LISTENERS} --override zookeeper.connect=${KAFKA_ZOOKEEPER_CONNECT}
f297c2f7d54e84da5f04ad5ea434e8a23379d263c5fee51b2894df9f4db59610
exit code: 0
['podman', 'network', 'exists', 'strimzi-all-in-one_default']
podman create --name=registry --label io.podman.compose.config-hash=123 --label io.podman.compose.project=strimzi-all-in-one --label io.podman.compose.version=0.0.1 --label com.docker.compose.project=strimzi-all-in-one --label com.docker.compose.project.working_dir=/home/demo_user/opt/training/amq-examples/strimzi-all-in-one --label com.docker.compose.project.config_files=docker-compose.yaml --label com.docker.compose.container-number=1 --label com.docker.compose.service=registry -e QUARKUS_PROFILE=prod -e KAFKA_BOOTSTRAP_SERVERS=kafka:29092 -e APPLICATION_ID=registry_id -e APPLICATION_SERVER=localhost:9000 --net strimzi-all-in-one_default --network-alias registry -p 8081:8080 apicurio/apicurio-registry-mem:1.2.2.Final
39e7dfe472d5241b896a88378b371f0f38f8fe4330993ced612f9038fd279cb7
exit code: 0
['podman', 'network', 'exists', 'strimzi-all-in-one_default']
podman create --name=bridge --label io.podman.compose.config-hash=123 --label io.podman.compose.project=strimzi-all-in-one --label io.podman.compose.version=0.0.1 --label com.docker.compose.project=strimzi-all-in-one --label com.docker.compose.project.working_dir=/home/demo_user/opt/training/amq-examples/strimzi-all-in-one --label com.docker.compose.project.config_files=docker-compose.yaml --label com.docker.compose.container-number=1 --label com.docker.compose.service=bridge -e KAFKA_BRIDGE_BOOTSTRAP_SERVERS=kafka:29092 -e KAFKA_BRIDGE_ID=bridge1 -e KAFKA_BRIDGE_HTTP_ENABLED=true -e KAFKA_BRIDGE_HTTP_HOST=0.0.0.0 -e KAFKA_BRIDGE_HTTP_PORT=8080 -v /home/demo_user/opt/training/amq-examples/strimzi-all-in-one/log4j.properties:/opt/strimzi/custom-config/log4j.properties --net strimzi-all-in-one_default --network-alias bridge -p 8082:8080 strimzi/kafka-bridge:0.16.0 sh -c /opt/strimzi/bin/docker/kafka_bridge_run.sh
1c54856ff14631532458e1ee9b12d1712a665e5fbfae9b79da152b2119e89122
exit code: 0
podman start -a zookeeper
[2022-09-29 02:36:56,576] INFO Reading configuration from: config/zookeeper.properties (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
[2022-09-29 02:36:56,577] WARN config/zookeeper.properties is relative. Prepend ./ to indicate that you're sure! (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
[2022-09-29 02:36:56,580] INFO clientPortAddress is 0.0.0.0:2181 (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
[2022-09-29 02:36:56,580] INFO secureClientPort is not set (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
[2022-09-29 02:36:56,582] INFO autopurge.snapRetainCount set to 3 (org.apache.zookeeper.server.DatadirCleanupManager)
[2022-09-29 02:36:56,582] INFO autopurge.purgeInterval set to 0 (org.apache.zookeeper.server.DatadirCleanupManager)
[2022-09-29 02:36:56,582] INFO Purge task is not scheduled. (org.apache.zookeeper.server.DatadirCleanupManager)
[2022-09-29 02:36:56,582] WARN Either no config or no quorum defined in config, running  in standalone mode (org.apache.zookeeper.server.quorum.QuorumPeerMain)
[2022-09-29 02:36:56,583] INFO Log4j found with jmx enabled. (org.apache.zookeeper.jmx.ManagedUtil)
[2022-09-29 02:36:56,593] INFO Reading configuration from: config/zookeeper.properties (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
[2022-09-29 02:36:56,593] WARN config/zookeeper.properties is relative. Prepend ./ to indicate that you're sure! (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
[2022-09-29 02:36:56,593] INFO clientPortAddress is 0.0.0.0:2181 (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
[2022-09-29 02:36:56,593] INFO secureClientPort is not set (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
[2022-09-29 02:36:56,593] INFO Starting server (org.apache.zookeeper.server.ZooKeeperServerMain)
[2022-09-29 02:36:56,595] INFO zookeeper.snapshot.trust.empty : false (org.apache.zookeeper.server.persistence.FileTxnSnapLog)
[2022-09-29 02:36:56,604] INFO Server environment:zookeeper.version=3.5.7-f0fdd52973d373ffd9c86b81d99842dc2c7f660e, built on 02/10/2020 11:30 GMT (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,604] INFO Server environment:host.name=a8da3abb34cc (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,604] INFO Server environment:java.version=1.8.0_252 (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,604] INFO Server environment:java.vendor=Oracle Corporation (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,605] INFO Server environment:java.home=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.252.b09-2.el7_8.x86_64/jre (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,605] INFO Server environment:java.class.path=/opt/kafka/bin/../libs/activation-1.1.1.jar:/opt/kafka/bin/../libs/annotations-13.0.jar:/opt/kafka/bin/../libs/aopalliance-repackaged-2.5.0.jar:/opt/kafka/bin/../libs/argparse4j-0.7.0.jar:/opt/kafka/bin/../libs/audience-annotations-0.5.0.jar:/opt/kafka/bin/../libs/bcpkix-jdk15on-1.62.jar:/opt/kafka/bin/../libs/bcprov-jdk15on-1.60.jar:/opt/kafka/bin/../libs/commons-cli-1.4.jar:/opt/kafka/bin/../libs/commons-lang-2.6.jar:/opt/kafka/bin/../libs/commons-lang3-3.8.1.jar:/opt/kafka/bin/../libs/connect-api-2.5.0.jar:/opt/kafka/bin/../libs/connect-basic-auth-extension-2.5.0.jar:/opt/kafka/bin/../libs/connect-file-2.5.0.jar:/opt/kafka/bin/../libs/connect-json-2.5.0.jar:/opt/kafka/bin/../libs/connect-mirror-2.5.0.jar:/opt/kafka/bin/../libs/connect-mirror-client-2.5.0.jar:/opt/kafka/bin/../libs/connect-runtime-2.5.0.jar:/opt/kafka/bin/../libs/connect-transforms-2.5.0.jar:/opt/kafka/bin/../libs/cruise-control-metrics-reporter-2.0.103.jar:/opt/kafka/bin/../libs/gson-2.8.6.jar:/opt/kafka/bin/../libs/hk2-api-2.5.0.jar:/opt/kafka/bin/../libs/hk2-locator-2.5.0.jar:/opt/kafka/bin/../libs/hk2-utils-2.5.0.jar:/opt/kafka/bin/../libs/jackson-annotations-2.10.2.jar:/opt/kafka/bin/../libs/jackson-core-2.10.2.jar:/opt/kafka/bin/../libs/jackson-databind-2.10.2.jar:/opt/kafka/bin/../libs/jackson-dataformat-csv-2.10.2.jar:/opt/kafka/bin/../libs/jackson-datatype-jdk8-2.10.2.jar:/opt/kafka/bin/../libs/jackson-jaxrs-base-2.10.2.jar:/opt/kafka/bin/../libs/jackson-jaxrs-json-provider-2.10.2.jar:/opt/kafka/bin/../libs/jackson-module-jaxb-annotations-2.10.2.jar:/opt/kafka/bin/../libs/jackson-module-paranamer-2.10.2.jar:/opt/kafka/bin/../libs/jackson-module-scala_2.12-2.10.2.jar:/opt/kafka/bin/../libs/jaeger-client-1.1.0.jar:/opt/kafka/bin/../libs/jaeger-core-1.1.0.jar:/opt/kafka/bin/../libs/jaeger-thrift-1.1.0.jar:/opt/kafka/bin/../libs/jaeger-tracerresolver-1.1.0.jar:/opt/kafka/bin/../libs/jakarta.activation-api-1.2.1.jar:/opt/kafka/bin/../libs/jakarta.annotation-api-1.3.4.jar:/opt/kafka/bin/../libs/jakarta.inject-2.5.0.jar:/opt/kafka/bin/../libs/jakarta.ws.rs-api-2.1.5.jar:/opt/kafka/bin/../libs/jakarta.xml.bind-api-2.3.2.jar:/opt/kafka/bin/../libs/javassist-3.22.0-CR2.jar:/opt/kafka/bin/../libs/javassist-3.26.0-GA.jar:/opt/kafka/bin/../libs/javax.servlet-api-3.1.0.jar:/opt/kafka/bin/../libs/javax.ws.rs-api-2.1.1.jar:/opt/kafka/bin/../libs/jaxb-api-2.3.0.jar:/opt/kafka/bin/../libs/jersey-client-2.28.jar:/opt/kafka/bin/../libs/jersey-common-2.28.jar:/opt/kafka/bin/../libs/jersey-container-servlet-2.28.jar:/opt/kafka/bin/../libs/jersey-container-servlet-core-2.28.jar:/opt/kafka/bin/../libs/jersey-hk2-2.28.jar:/opt/kafka/bin/../libs/jersey-media-jaxb-2.28.jar:/opt/kafka/bin/../libs/jersey-server-2.28.jar:/opt/kafka/bin/../libs/jetty-client-9.4.24.v20191120.jar:/opt/kafka/bin/../libs/jetty-continuation-9.4.24.v20191120.jar:/opt/kafka/bin/../libs/jetty-http-9.4.24.v20191120.jar:/opt/kafka/bin/../libs/jetty-io-9.4.24.v20191120.jar:/opt/kafka/bin/../libs/jetty-security-9.4.24.v20191120.jar:/opt/kafka/bin/../libs/jetty-server-9.4.24.v20191120.jar:/opt/kafka/bin/../libs/jetty-servlet-9.4.24.v20191120.jar:/opt/kafka/bin/../libs/jetty-servlets-9.4.24.v20191120.jar:/opt/kafka/bin/../libs/jetty-util-9.4.24.v20191120.jar:/opt/kafka/bin/../libs/jmx_prometheus_javaagent-0.12.0.jar:/opt/kafka/bin/../libs/jopt-simple-5.0.4.jar:/opt/kafka/bin/../libs/json-smart-1.1.1.jar:/opt/kafka/bin/../libs/jsonevent-layout-1.7.jar:/opt/kafka/bin/../libs/kafka-agent.jar:/opt/kafka/bin/../libs/kafka-clients-2.5.0.jar:/opt/kafka/bin/../libs/kafka-log4j-appender-2.5.0.jar:/opt/kafka/bin/../libs/kafka-oauth-client-0.5.0.jar:/opt/kafka/bin/../libs/kafka-oauth-common-0.5.0.jar:/opt/kafka/bin/../libs/kafka-oauth-keycloak-authorizer-0.5.0.jar:/opt/kafka/bin/../libs/kafka-oauth-server-0.5.0.jar:/opt/kafka/bin/../libs/kafka-streams-2.5.0.jar:/opt/kafka/bin/../libs/kafka-streams-examples-2.5.0.jar:/opt/kafka/bin/../libs/kafka-streams-scala_2.12-2.5.0.jar:/opt/kafka/bin/../libs/kafka-streams-test-utils-2.5.0.jar:/opt/kafka/bin/../libs/kafka-tools-2.5.0.jar:/opt/kafka/bin/../libs/kafka_2.12-2.5.0-sources.jar:/opt/kafka/bin/../libs/kafka_2.12-2.5.0.jar:/opt/kafka/bin/../libs/keycloak-common-10.0.0.jar:/opt/kafka/bin/../libs/keycloak-core-10.0.0.jar:/opt/kafka/bin/../libs/kotlin-stdlib-1.3.50.jar:/opt/kafka/bin/../libs/kotlin-stdlib-common-1.3.50.jar:/opt/kafka/bin/../libs/libthrift-0.13.0.jar:/opt/kafka/bin/../libs/log4j-1.2.17.jar:/opt/kafka/bin/../libs/lz4-java-1.7.1.jar:/opt/kafka/bin/../libs/maven-artifact-3.6.3.jar:/opt/kafka/bin/../libs/metrics-core-2.2.0.jar:/opt/kafka/bin/../libs/mirror-maker-agent.jar:/opt/kafka/bin/../libs/netty-buffer-4.1.45.Final.jar:/opt/kafka/bin/../libs/netty-codec-4.1.45.Final.jar:/opt/kafka/bin/../libs/netty-common-4.1.45.Final.jar:/opt/kafka/bin/../libs/netty-handler-4.1.45.Final.jar:/opt/kafka/bin/../libs/netty-resolver-4.1.45.Final.jar:/opt/kafka/bin/../libs/netty-transport-4.1.45.Final.jar:/opt/kafka/bin/../libs/netty-transport-native-epoll-4.1.45.Final.jar:/opt/kafka/bin/../libs/netty-transport-native-unix-common-4.1.45.Final.jar:/opt/kafka/bin/../libs/okhttp-4.2.2.jar:/opt/kafka/bin/../libs/okio-2.2.2.jar:/opt/kafka/bin/../libs/opentracing-api-0.33.0.jar:/opt/kafka/bin/../libs/opentracing-kafka-client-0.1.12.jar:/opt/kafka/bin/../libs/opentracing-noop-0.33.0.jar:/opt/kafka/bin/../libs/opentracing-tracerresolver-0.1.8.jar:/opt/kafka/bin/../libs/opentracing-util-0.33.0.jar:/opt/kafka/bin/../libs/osgi-resource-locator-1.0.1.jar:/opt/kafka/bin/../libs/paranamer-2.8.jar:/opt/kafka/bin/../libs/plexus-utils-3.2.1.jar:/opt/kafka/bin/../libs/reflections-0.9.12.jar:/opt/kafka/bin/../libs/rocksdbjni-5.18.3.jar:/opt/kafka/bin/../libs/scala-collection-compat_2.12-2.1.3.jar:/opt/kafka/bin/../libs/scala-java8-compat_2.12-0.9.0.jar:/opt/kafka/bin/../libs/scala-library-2.12.10.jar:/opt/kafka/bin/../libs/scala-logging_2.12-3.9.2.jar:/opt/kafka/bin/../libs/scala-reflect-2.12.10.jar:/opt/kafka/bin/../libs/slf4j-api-1.7.30.jar:/opt/kafka/bin/../libs/slf4j-log4j12-1.7.30.jar:/opt/kafka/bin/../libs/snappy-java-1.1.7.3.jar:/opt/kafka/bin/../libs/tracing-agent.jar:/opt/kafka/bin/../libs/validation-api-2.0.1.Final.jar:/opt/kafka/bin/../libs/zookeeper-3.5.7.jar:/opt/kafka/bin/../libs/zookeeper-jute-3.5.7.jar:/opt/kafka/bin/../libs/zstd-jni-1.4.4-7.jar (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,605] INFO Server environment:java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,605] INFO Server environment:java.io.tmpdir=/tmp (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,605] INFO Server environment:java.compiler=<NA> (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,605] INFO Server environment:os.name=Linux (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,605] INFO Server environment:os.arch=amd64 (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,605] INFO Server environment:os.version=5.19.10-200.fc36.x86_64 (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,605] INFO Server environment:user.name=kafka (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,606] INFO Server environment:user.home=/home/kafka (org.apache.zookeeper.server.ZooKeeperServer)
[2022-09-29 02:36:56,606] INFO Server environment:user.dir=/opt/kafka (org.apache.zookeeper.server.ZooKeeperServer)

   -- 省略 --

#Apache Kafka Producer

#Apache Kafka Consumer

#HTTP configuration
http.enabled=true
http.host=0.0.0.0
http.port=8080
http.cors.enabled=
http.cors.allowedOrigins=
http.cors.allowedMethods=

cat: /sys/fs/cgroup/memory/memory.limit_in_bytes: No such file or directory
/opt/strimzi/bin/docker/dynamic_resources.sh: line 7: [: : integer expression expected
log4j:ERROR Could not read configuration file from URL [file:/opt/strimzi/custom-config/log4j.properties].
java.io.FileNotFoundException: /opt/strimzi/custom-config/log4j.properties (Permission denied)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90)
    at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188)
    at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:557)
    at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:526)
    at org.apache.log4j.LogManager.<clinit>(LogManager.java:127)
    at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:81)
    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:358)
    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
    at io.strimzi.kafka.bridge.Application.<clinit>(Application.java:34)
log4j:ERROR Ignoring configuration file [file:/opt/strimzi/custom-config/log4j.properties].
log4j:WARN No appenders could be found for logger (io.strimzi.kafka.bridge.Application).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
2022-09-29 02:36:58,878 WARN  [io.qua.config] (main) Unrecognized configuration key "quarkus.datasource.username" was provided; it will be ignored
2022-09-29 02:36:58,879 WARN  [io.qua.config] (main) Unrecognized configuration key "quarkus.datasource.driver" was provided; it will be ignored
2022-09-29 02:36:58,879 WARN  [io.qua.config] (main) Unrecognized configuration key "quarkus.datasource.url" was provided; it will be ignored
2022-09-29 02:36:58,879 WARN  [io.qua.config] (main) Unrecognized configuration key "quarkus.hibernate-orm.database.generation" was provided; it will be ignored
2022-09-29 02:36:58,879 WARN  [io.qua.config] (main) Unrecognized configuration key "quarkus.datasource.password" was provided; it will be ignored
2022-09-29 02:36:59,962 INFO  [io.quarkus] (main) apicurio-registry-app 1.2.2.Final (powered by Quarkus 1.3.3.Final) started in 1.251s. Listening on: http://0.0.0.0:8080
2022-09-29 02:36:59,962 INFO  [io.quarkus] (main) Profile prod activated. 
2022-09-29 02:36:59,963 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy, resteasy-jackson, servlet, smallrye-health, smallrye-metrics, smallrye-openapi]


Apache Kafka の設定

  • 別の端末上で strimzi-all-in-one ディレクトリへ遷移し、以下の手順にて Topic を作成します
    (補足)以下の手順では Topic 名へ demo-topic を指定しています。
$ pwd
/home/demo_user/opt/training/amq-examples/strimzi-all-in-one
$ 
$ podman-compose exec kafka bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic demo-topic
['podman', '--version', '']
using podman version: 4.2.0
podman exec --interactive --tty --env LOG_DIR=/tmp/logs --env KAFKA_BROKER_ID=1 --env KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT --env KAFKA_LISTENERS=PLAINTEXT://:29092,PLAINTEXT_HOST://:9092 --env KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 --env KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 kafka bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic demo-topic
Created topic demo-topic.
exit code: 0
$ 


動作確認

  • 別の端末上で strimzi-all-in-one ディレクトリへ遷移し、以下の手順にてコンシューマー1 を起動し、メッセージ受信を開始します
$ podman-compose exec kafka bin/kafka-console-consumer.sh --topic demo-topic  --bootstrap-server localhost:9092
['podman', '--version', '']
using podman version: 4.2.0
podman exec --interactive --tty --env LOG_DIR=/tmp/logs --env KAFKA_BROKER_ID=1 --env KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT --env KAFKA_LISTENERS=PLAINTEXT://:29092,PLAINTEXT_HOST://:9092 --env KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 --env KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 kafka bin/kafka-console-consumer.sh --topic demo-topic --bootstrap-server localhost:9092


  • 別の端末上で strimzi-all-in-one ディレクトリへ遷移し、以下の手順にてコンシューマー2 を起動し、メッセージ受信を開始します
$ podman-compose exec kafka bin/kafka-console-consumer.sh --topic demo-topic  --bootstrap-server localhost:9092
['podman', '--version', '']
using podman version: 4.2.0
podman exec --interactive --tty --env LOG_DIR=/tmp/logs --env KAFKA_BROKER_ID=1 --env KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT --env KAFKA_LISTENERS=PLAINTEXT://:29092,PLAINTEXT_HOST://:9092 --env KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 --env KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 kafka bin/kafka-console-consumer.sh --topic demo-topic --bootstrap-server localhost:9092


  • 別の端末上で strimzi-all-in-one ディレクトリへ遷移し、以下の手順にてプロデューサーを起動します
$ podman-compose exec kafka bin/kafka-console-producer.sh --topic demo-topic --bootstrap-server localhost:9092
['podman', '--version', '']
using podman version: 4.2.0
podman exec --interactive --tty --env LOG_DIR=/tmp/logs --env KAFKA_BROKER_ID=1 --env KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT --env KAFKA_LISTENERS=PLAINTEXT://:29092,PLAINTEXT_HOST://:9092 --env KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 --env KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 kafka bin/kafka-console-producer.sh --topic demo-topic --bootstrap-server localhost:9092


  • プロデューサーから3つ程メッセージを登録します
{"data" : {"id": 1, "status": "Gold", "score": 200}}
{"data" : {"id": 2, "status": "Red", "score": 5}}       
{"data" : {"id": 3, "status": "Silver", "score": 170}}


  • 各コンシューマーで同じメッセージが受信できることを確認します
{"data" : {"id": 1, "status": "Gold", "score": 200}}
{"data" : {"id": 2, "status": "Red", "score": 5}}
{"data" : {"id": 3, "status": "Silver", "score": 170}}


Apache Kafka の終了

  • 別の端末上で strimzi-all-in-one ディレクトリへ遷移し、以下の手順にて Apache Kafka を終了します
$ podman-compose down
['podman', '--version', '']
using podman version: 4.2.0
** excluding:  set()
podman stop -t 10 bridge
WARN[0010] StopSignal SIGTERM failed to stop container bridge in 10 seconds, resorting to SIGKILL 
bridge
exit code: 0
podman stop -t 10 registry
registry
exit code: 0
podman stop -t 10 kafka
kafka
exit code: 0
podman stop -t 10 zookeeper
zookeeper
exit code: 0
podman rm bridge
1c54856ff14631532458e1ee9b12d1712a665e5fbfae9b79da152b2119e89122
exit code: 0
podman rm registry
39e7dfe472d5241b896a88378b371f0f38f8fe4330993ced612f9038fd279cb7
exit code: 0
podman rm kafka
f297c2f7d54e84da5f04ad5ea434e8a23379d263c5fee51b2894df9f4db59610
exit code: 0
podman rm zookeeper
a8da3abb34cc182a4e0f1095027a9633557775e7794b91ab5b6564684e242bdd
exit code: 0
$ 


まとめ

以上の手順にてあっと言う間に Apache Kafka 環境を構築することができました。 一部のノードがダウンした際の動作などを検証することは難しいかも知れませんが、手っ取り早く Apache Kafka 環境を用意したい場合に便利だと思います。

Windows 上で JBoss EAP を稼働させる際に少し気をつけた方が良いこと

別に JBoss EAP だけの注意点ではないのですが、Windows 環境では稼働しているプログラムが利用しているファイルに対してロックが掛かってしまい、ロックが掛かっている間はファイルの移動/削除などができなくなりますが、Windows 上で JBoss EAP を稼働させる場合も一度 JBoss EAP に読込まれた jar ファイルなどにロックが掛かってしまうため、JBoss EAP が稼働したまま定義を削除するような場合に期待した動作とならない場合があります。


(記憶が曖昧ではありますが、この辺りの話は Oracle WebLogic Server でも同様かなと思います)

上記のような注意点が分かり易いように以下のような JBoss EAPJDBCドライバを登録し、直ぐに削除する検証を実施してみました。


準備作業

  • 以下のページから PostgreSQL JDBC ドライバをダウンロードします。

jdbc.postgresql.org


JBoss EAP の起動

  • 以下のような感じで JBoss EAP を起動します。(環境に応じて適宜読み替えてください)
set JBOSS_HOME=C:\opt\jboss-eap-7.4.6

%JBOSS_HOME%\bin\standalone.bat


  • 管理 CLI を起動し JBoss EAP へ接続します。
%JBOSS_HOME%\bin\jboss-cli.bat -c
[standalone@localhost:9990 /]


JDBC ドライバの登録

  • 現在登録されている JDBC ドライバを確認します。
[standalone@localhost:9990 /] jdbc-driver-info
NAME SOURCE
h2   com.h2database.h2/main

[standalone@localhost:9990 /]


  • PostgreSQLJDBC ドライバをコアモジュールとして導入します。
[standalone@localhost:9990 /] module add --name=org.postgresql --resources="<ダウンロードフォルダ>\postgresql-42.5.0.jar" --dependencies=javax.api,javax.transaction.api
[standalone@localhost:9990 /]


[standalone@localhost:9990 /] /subsystem=datasources/jdbc-driver=postgresql:add(driver-name=postgresql,driver-module-name=org.postgresql,driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource)
{"outcome" => "success"}

[standalone@localhost:9990 /]


  • 現在登録されている JDBC ドライバを再度確認します。
[standalone@localhost:9990 /] jdbc-driver-info
NAME       SOURCE
h2         com.h2database.h2/main
postgresql org.postgresql/main    <= *** JDBC ドライバを登録すると jdbc-driver-info の結果に現れるようになります ***

[standalone@localhost:9990 /]


  • jar ファイルが modules フォルダへコピーされていることを確認します。
dir <<JBOSS_HOME>>\modules\org\postgresql\main\postgresql-42.5.0.jar

 ドライブ C のボリューム ラベルは Windows-SSD です
 ボリューム シリアル番号は xxxx-xxxx です

 C:\opt\jboss-eap-7.4.6\modules\org\postgresql\main のディレクトリ

2022/09/28  19:33         1,046,274 postgresql-42.5.0.jar
               1 個のファイル           1,046,274 バイト
               0 個のディレクトリ  132,541,067,264 バイトの空き領域


検証1:JBoss EAP が稼働したまま JDBC ドライバを削除

  • JBoss EAP が稼働した状態だと jar ファイルがロックされた状態となり削除できないことを確認します。
[standalone@localhost:9990 /] jdbc-driver-info
NAME       SOURCE
h2         com.h2database.h2/main
postgresql org.postgresql/main

[standalone@localhost:9990 /]
[standalone@localhost:9990 /] /subsystem=datasources/jdbc-driver=postgresql:remove()    <= *** JDBC ドライバを削除 ***
{"outcome" => "success"}

[standalone@localhost:9990 /] jdbc-driver-info
NAME SOURCE
h2   com.h2database.h2/main

[standalone@localhost:9990 /] module remove --name=org.postgresql    <= *** コアモジュールを削除 ***
Failed to delete <<JBOSS_HOME>>\modules\org\postgresql\main\postgresql-42.5.0.jar    <= *** JBoss EAP プロセスが jar ファイルをロックしているためモジュールが削除できない ***

[standalone@localhost:9990 /]

(補足)この時、<<JBOSS_HOME>>\modules\org\postgresql\main\postgresql-42.5.0.jar ファイルが残っていて、直接 postgresql-42.5.0.jar ファイルを手動で削除しようとすると Java プロセスが掴んでいることが確認できます。


検証2:JBoss EAP を停止後に JDBC ドライバを削除

  • ここで一度 JBoss EAP を停止します。


  • 再度、JDBC ドライバを削除すると期待通り動作します。
[standalone@localhost:9990 /] module remove --name=org.postgresql    <= *** JBoss EAP 停止後ならモジュールが削除可能 ***
[standalone@localhost:9990 /]

(補足)このタイミングで <<JBOSS_HOME>>\modules\org\postgresql\main\postgresql-42.5.0.jar が存在しないことが確認できます。


まとめ

Windows 環境で稼働している JBoss EAP が読み込んだファイルに対してロックが掛かってしまうことと、JBoss EAP プロセスを停止すればロックが解放されるため、期待通りの操作が可能なことが確認できました。 Windows 環境で JBoss EAP の挙動が変に感じた際は一度この辺りを意識して調査してみると良いかも知れません。

OpenShift 上の JBoss EAP の統計情報をコマンドラインで確認する

前回の続きとなりますが、今回はコマンドラインJBoss EAP の統計情報を確認してみます。

hnamaizawa.hatenadiary.org


手順としては以下のドキュメントで記載されている通りではあります。

docs.openshift.com

ちなみに、個人的に通常は tcsh(古い)を利用してますが、OpenShift 関連に触れる際は bash に切り替えて利用しています。(すっかり csh 系がすたれてしまったな…)



事前準備

  • TOKEN の取得
oc_project="$(oc project -q)"

SECRET=`oc get secret -n openshift-user-workload-monitoring | grep  prometheus-user-workload-token | head -n 1 | awk '{print $1 }'`

TOKEN=`echo $(oc get secret $SECRET -n openshift-user-workload-monitoring -o json | jq -r '.data.token') | base64 -d`


  • Prometheus 情報のアクセス先を取得
THANOS_QUERIER_HOST=`oc get route thanos-querier -n openshift-monitoring -o json | jq -r '.spec.host'`


  • 対象となる Namespace を指定
NAMESPACE=$oc_project 


統計情報の取得

curl -X GET -kG "https://$THANOS_QUERIER_HOST/api/v1/query?" --data-urlencode "query=jboss_undertow_active_sessions{namespace='$NAMESPACE'}" -H "Authorization: Bearer $TOKEN" | jq
  • 実行例
$ curl -X GET -kG "https://$THANOS_QUERIER_HOST/api/v1/query?" --data-urlencode "query=jboss_undertow_active_sessions{namespace='$NAMESPACE'}" -H "Authorization: Bearer $TOKEN" | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   411  100   411    0     0  37596      0 --:--:-- --:--:-- --:--:-- 41100
{
  "status": "success",
  "data": {
    "resultType": "vector",
    "result": [
      {
        "metric": {
          "__name__": "jboss_undertow_active_sessions",
          "deployment": "ROOT.war",
          "endpoint": "metrics",
          "instance": "10.217.0.2:9799",
          "job": "eap-app-metrics",
          "namespace": "eapdemo",
          "pod": "eap-app-1-x77tm",
          "prometheus": "openshift-user-workload-monitoring/user-workload",
          "service": "eap-app-metrics",
          "subdeployment": "ROOT.war"
        },
        "value": [
          1664269215.69,
          "2"
        ]
      }
    ]
  }
}

(補足)上記は 2セッションが存在する状態でアクティブセッション数を取得した結果です。


まとめ

以上のような手順でコマンドラインから JBoss EAP の統計情報を確認することができます。あとは jq などで CSV データなどへ整形し、ファイルへリダイレクトするような対応を実施すると Excel などで統計情報を可視化することが可能になるかと思います。