2018年9月17日月曜日

CentOS 7.3 上の Docker 1.31.1 が SELinux のエラーで起動できない

CentOS 7 上に docker を yum でデフォルトインストールし、サービス起動しようとしたところ以下のエラーで起動できません。

-----
[root@mycentos7 takeda]# systemctl start docker
Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.

[root@mycentos7 takeda]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since 月 2018-09-17 00:56:24 JST; 1min 9s ago
     Docs: http://docs.docker.com
  Process: 10824 ExecStart=/usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --init-path=/usr/libexec/docker/docker-init-current --seccomp-profile=/etc/docker/seccomp.json $OPTIONS $DOCKER_STORAGE_OPTIONS $DOCKER_NETWORK_OPTIONS $ADD_REGISTRY $BLOCK_REGISTRY $INSECURE_REGISTRY $REGISTRIES (code=exited, status=1/FAILURE)
 Main PID: 10824 (code=exited, status=1/FAILURE)

 9月 17 00:56:22 mycentos7 systemd[1]: Starting Docker Application Container Engine...
 9月 17 00:56:22 mycentos7 dockerd-current[10824]: time="2018-09-17T00:56:22.915287681+09:00" level=warning...und"
 9月 17 00:56:22 mycentos7 dockerd-current[10824]: time="2018-09-17T00:56:22.927551156+09:00" level=info ms...829"
 9月 17 00:56:24 mycentos7 dockerd-current[10824]: Error starting daemon: SELinux is not supported with the...lse)
 9月 17 00:56:24 mycentos7 systemd[1]: docker.service: main process exited, code=exited, status=1/FAILURE
 9月 17 00:56:24 mycentos7 systemd[1]: Failed to start Docker Application Container Engine.
 9月 17 00:56:24 mycentos7 systemd[1]: Unit docker.service entered failed state.
 9月 17 00:56:24 mycentos7 systemd[1]: docker.service failed.
Hint: Some lines were ellipsized, use -l to show in full.
-----

STORAGE_DRIVER をデフォルトで設定される overlay2 から、devicemappr に変更すると起動できました。
-----
デフォルト
[root@mycentos7 takeda]# cat /etc/sysconfig/docker-storage-setup
STORAGE_DRIVER=overlay2
[root@mycentos7 takeda]# cat /etc/sysconfig/docker-storage
DOCKER_STORAGE_OPTIONS="--storage-driver overlay2 "
→変更
[root@mycentos7 takeda]# echo STORAGE_DRIVER=devicemappr > /etc/sysconfig/docker-storage-setup
[root@mycentos7 takeda]# echo DOCKER_STORAGE_OPTIONS="--storage-driver devicemapper " > /etc/sysconfig/docker-storage
→変更後
[root@mycentos7 takeda]# cat /etc/sysconfig/docker-storage-setup
STORAGE_DRIVER=devicemappr
[root@mycentos7 takeda]# cat /etc/sysconfig/docker-storage
DOCKER_STORAGE_OPTIONS=--storage-driver devicemapper
 (DOCKER_STORAGE_OPTIONS のみ変更で起動できましたが、一応両方 devicemappr に変更しています。)
-----
-----
[root@mycentos7 takeda]# systemctl start docker

[root@mycentos7 takeda]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
   Active: active (running) since 月 2018-09-17 01:14:58 JST; 6s ago
     Docs: http://docs.docker.com
 Main PID: 11778 (dockerd-current)
   CGroup: /system.slice/docker.service
           tq11778 /usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --...
           mq11782 /usr/bin/docker-containerd-current -l unix:///var/run/docker/libcontainerd/docker-containerd....

 9月 17 01:14:57 mycentos7 dockerd-current[11778]: time="2018-09-17T01:14:57.433343640+09:00" level=warning...ed."
 9月 17 01:14:57 mycentos7 dockerd-current[11778]: time="2018-09-17T01:14:57.597673721+09:00" level=info ms...nds"
 9月 17 01:14:57 mycentos7 dockerd-current[11778]: time="2018-09-17T01:14:57.600587978+09:00" level=info ms...rt."
 9月 17 01:14:57 mycentos7 dockerd-current[11778]: time="2018-09-17T01:14:57.634389495+09:00" level=info ms...rue"
 9月 17 01:14:58 mycentos7 dockerd-current[11778]: time="2018-09-17T01:14:58.405195396+09:00" level=info ms...ess"
 9月 17 01:14:58 mycentos7 dockerd-current[11778]: time="2018-09-17T01:14:58.788143620+09:00" level=info ms...ne."
 9月 17 01:14:58 mycentos7 dockerd-current[11778]: time="2018-09-17T01:14:58.936721690+09:00" level=info ms...ion"
 9月 17 01:14:58 mycentos7 dockerd-current[11778]: time="2018-09-17T01:14:58.936809926+09:00" level=info ms...13.1
 9月 17 01:14:58 mycentos7 systemd[1]: Started Docker Application Container Engine.
 9月 17 01:14:58 mycentos7 dockerd-current[11778]: time="2018-09-17T01:14:58.958821424+09:00" level=info ms...ock"
Hint: Some lines were ellipsized, use -l to show in full.

以下の情報の通りです

 『CentOS 7:Docker App Container Engineの起動に失敗しました - graphdriverの初期化エラー:ドライバがサポートされていません #32』

 『SELinux is not supported with the overlay graph driver』

■環境は以下の通り。
 Docker:Docker version 1.13.1, build 6e3bb8e/1.13.1
 ゲストOS: CentOS Linux release 7.3.1611 (Core)
 ホストOS: Windows 10 1803
 VM:Virtual BOX 5.2.18 r124319 (Qt5.6.2)

■ overlay2 ドライバが SELinux で正しく動作しないことがエラーの理由のため、SELinuxのほうを無効化しても対処可能な模様です。

 『Dockerのボリュームプラグインとストレージドライバ(Dockerの最新機能を使ってみよう:第2回)』
 https://knowledge.sakura.ad.jp/5021/
   > overlayドライバを利用してみる

 ■参考サイト
 『Docker CE 構築 on CentOS7』
 https://qiita.com/sugimount/items/0b14b8d544ab1d95e219

2017年11月8日水曜日

Byteman traceln()やtraceStack()を標準出力ではなくファイルに出力する

JavaプロセスをWindowsサービスとして稼働したり、バックグラウンド起動してターミナルは終了した場合に、Byteman の トレース関数(traceln()やtraceStack())の出力先となる標準出力が無くデバッグが困難となるケースがあります。

このようなケースでは、以下のように traceOpen()でトレース出力先をファイルに向けることで対処できます。

----- sample.btm -----
# トレースを別ファイルに出力
RULE outFile
CLASS sample.SimpleImpl
METHOD getCount
AT ENTRY
IF TRUE
  DO
  traceOpen("myIdentifier01", "C:\dev\myByteman\myByteman.trc");
  traceln("myIdentifier01","---mytrace---"+new java.util.Date());
  traceStack(null,"myIdentifier01");
  traceClose("myIdentifier01");
ENDRULE
-----

$ cat myByteman.trc

---mytrace---Wed Nov 08 00:06:55 JST 2017
Stack trace for thread main
sample.SimpleImpl.getCount(SimpleImpl.java:-1)
sample.MainClass.execute(MainClass.java:15)
sample.MainClass.main(MainClass.java:7)
---mytrace---Wed Nov 08 00:06:58 JST 2017
Stack trace for thread main
sample.SimpleImpl.getCount(SimpleImpl.java:-1)
sample.MainClass.execute(MainClass.java:15)
sample.MainClass.main(MainClass.java:7)
---mytrace---Wed Nov 08 00:07:01 JST 2017
Stack trace for thread main
sample.SimpleImpl.getCount(SimpleImpl.java:-1)
sample.MainClass.execute(MainClass.java:15)
sample.MainClass.main(MainClass.java:7)
(・・・)
----

public boolean traceOpen(Object identifier, String filename)
identifire はトレース出力先を示す識別子になります。

public void traceStack(String prefix, Object key)
prefix に null を指定すると、“Stack trace for thread <current>\n”がスタックトレースの先頭に表示され、<current> には Thread.currentThread().getName() が代入されます。

2017年5月6日土曜日

WebLogic 12.2.1.2.0 管理対象サーバをリモートOSで起動したところ BEA-141149 となる

■WLS 12.2.1.2.0 にて管理対象サーバをリモートで起動しようとした際、以下のエラーが発生しました。

---
####<2017/04/03, 2:13:20,253 午後 JST> <Critical> <WebLogicServer> <xxxx> <Server-0> <main> <<WLS Kernel>> <> <> <1491196400253> 
<[severity-value: 4] [partition-id: 0] [partition-name: DOMAIN] > 
<BEA-000386> <サーバー・サブシステムに障害が発生しました。理由: A MultiException has 2 exceptions.  They are:
1. weblogic.ldap.EmbeddedLDAPException: Empty initial replica
2. java.lang.IllegalStateException: Unable to perform operation: post construct on weblogic.ldap.PreEmbeddedLDAPService

A MultiException has 2 exceptions.  They are:

1. weblogic.ldap.EmbeddedLDAPException: Empty initial replica
2. java.lang.IllegalStateException: Unable to perform operation: post construct on weblogic.ldap.PreEmbeddedLDAPService

        at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:391)

        ・・・
-----

■Linux側のOS時刻を合わせることで解消しました。
       
■発生した環境は以下の通り
 管理サーバ:Windows10
 管理対象サーバ: Linux(centOS 7)

以下の操作で発生しました。
1. Windows10 、Linux 双方に WLS 12c をインストール
2. Windows10 側にてWLSドメインを作成。管理サーバ、管理対象サーバ(Server-0)を構成
3. Windows10 側にて WLSドメインを pack -managed=true でパック後、Linux 側で unpack。
4. Windows10 側で管理サーバを起動
5. Linux にて $DOMAIN_HOME/bin/startManagedWebLogic.sh Server-0 で起動するとエラー

管理サーバ側には BEA-141149 が出力されます。
----
<2017/05/06, 12:11:49,316 午前 JST> <Error> <Management> <BEA-141149>
<salt m67t55TnLIR/hoG8KV9hvg==、シグネチャRwbmB0APaH95Hr9Y14INaAjBKNP1wm3Sv5FvS/TaOms=の
管理サーバーへ接続しようとする無効な試みが行われました。
おそらく、秘密鍵が一致していないことが原因です。>
----

■原因は筐体間の時刻に著しいずれがあることでした。以下の ディスカッションの通りです。
<BEA-141149> <An invalid attempt was made to connect to the
https://community.oracle.com/thread/3894372

====
14. Re: <BEA-141149> <An invalid attempt was made to connect to the
 ksunil
Newbie
ksunil 2016/02/17 13:22 (ksunil への返信)
This is now resolved. There was nothing wrong with the scripts.
Apparently, the clocks on these 2 Linux boxes were apart (4 minutes) and that triggers something internally. Suggestion came from Oracle support
====

2017年1月29日日曜日

Bytemanチュートリアル(日本語意訳)
稼働中に Byteman エージェントをあとからインストールする方法は?

Byteman (http://byteman.jboss.org/docs.html)のチュートリアルを日本語意訳したものです。

実行中のプログラムをチェックするために Byteman を利用する際、Byteman エージェントをロードせずに実行していたことに気づくことがあります。例えば JBoss アプリケーションサーバのようなプログラムを長時間稼働中、何か問題だ生じたことがログに出力されていた場合などです。
少なくとも Hotspot、JRockit、OpenJDK JVM で実行してたなら、Byteman を使用するために稼働中のプログラムを再起動する必要はありません。これらのJVM の場合、稼働中のプログラムにByteman エージェントを動的に追加インストールすることができます。

Linux なら bminstall.sh スクリプトを利用します。
-----
> bminstall.sh 13101
>
-----

すべての JVM で、動的なエージェントのロードができるわけではありません。
Linux では、Oracle JVM 、OpenJDK、JRockit が、macOSX では OracleJVM と OpenJDK ならできます。
IBM JVM や Windows 上でのその他 JVM で可能かは不明です。

Windows も bminstall.bat を利用します。(リリース 2.0.1 以降)
2.0.1 以前の場合 Install.main() を必要な引数を指定して実行します。
-----
> java -classpath %BYTEMAN_HOME%\lib\byteman-install.jar org.jboss.byteman.agent.install.Install 13101
>
-----

上記の数値(13101)の箇所には、Byteman エージェントをインストールする JVM のプロセスIDを指定します。
チェックしたい稼働中の Java プログラムのその時点の PID を指定する必要があります。(PIDの確認は $JAVAHOME/bin/jps を使うと便利です。)

また、稼働中のJavaプログラムの main クラス名を指定することもできます。(jar コマンド($java -jar myapp.jar)のように起動した場合は、jar名を指定することもできます。)

bminstall.sh は、稼働中の JBoss アプリケーション・サーバ・インスタンスに Byteman エージェントをインストールするのに非常に便利です。AppMain3 を -javaagent オプションなしで再度実行し、稼働後に Byteman エージェントとルール・スクリプトを読み込ませてみましょう。
-javaagent オプションなしで起動しておきます。
    -----
    > java org.my.AppMain3
    foo
    foo
    bar
    bar
    -----

別のコマンドシェルでエージェントをインストールします。
<Linux>
    -----
    > bminstall.sh -b -Dorg.jboss.byteman.transform.all org.my.AppMain3
    >
    -----

bminstall コマンドはルール・スクリプトのロードはできませんが、エージェント・リスナーを自動的に有効にでき、さらに bmsubmt.sh でルールを送信できます。再度 bmsubmit コマンドで thread.btm ルールを送信すると AppMain3 の動作が途中から変更されたことが確認できます。

Bytemanチュートリアル(日本語意訳)
ルールのアンロード方法

Byteman (http://byteman.jboss.org/docs.html)のチュートリアルを日本語意訳したものです。

bmsubmit.sh でルールをアンロードして、AppMain3 の Thread.start() メソッドをオリジナルの動作に戻すことができます。

    -----
    > bmsubmit.sh -u thread.btm
    uninstall RULE trace thread start

    > bmsubmit.sh
    no rules installed
    -----

-u オプションの後にルール・スクリプト名を指定します。指定したルールスクリプト内のすべてのルールがアンロードされ、メソッドに注入されたコードが削除されます。
AppMain3 が、入力テキストを繰り返すのみの最初の動作に戻りました。

    -----
    . . .
    mumble
    *** start for thread: mumble
    mumble
    grumble
    grumble
    bletch
    bletch
    end
    >
    -----

ルール・スクリプトの注入コードのみ変更したいなら、ルールのアンロード、リロードは必要ありません。ルール・スクリプトを修正して再度 submit すれば、Byteman は既存の注入コードを削除し新しいコードを再注入します。

Bytemanチュートリアル(日本語意訳)
どのルールがロードされコンパイルされたか確認したいんですが?

Byteman (http://byteman.jboss.org/docs.html)のチュートリアルを日本語意訳したものです。

bmsubmit.sh を再度実行するとルールが正常にコンパイルされていることが確認できます。

    -----
    > bmsubmit.sh
    # File thread.btm line 4
    RULE trace thread start
    CLASS java.lang.Thread
    METHOD start()
    AT ENTRY
    IF true
    DO traceln("*** start for thread: "+ $0.getName())
    ENDRULE
    Transformed in:
    loader: sun.misc.Launcher$AppClassLoader@5acac268
    trigger method: java.lang.Thread.start() void
   
    compiled successfully
    >
    -----

「compiled successfully.」と出力されています。これはルールの型チェックに成功し適用されたことを意味します。

ルールが最初にトリガーされたときに型チェックを行った場合([baz]を含む行をタイプした後)は、
型チェック失敗するとコード注入は実行されずに失敗した詳細が出力されます。
注入されたコードはルールがアンロードされたときのみ削除されます。

Bytemanチュートリアル(日本語意訳)
実行中のプログラムにルールを動的適用する方法は?

Byteman (http://byteman.jboss.org/docs.html)のチュートリアルを日本語意訳したものです。

長時間動くプログラムの場合、プログラム実行後にルールをロードしたり、ルールの再ロードをしたいことがあります。これらは Byteman にエージェント・リスナーを起動されば可能になります。エージェント・リスナーはルールのロード状況の確認もできます。

AppMain3 を使って、リスナーの動作を確認しましょう。

    ----- AppMain3.java -----
    package org.my;
    import java.io.DataInputStream;
 
    class AppMain3  {
        public static void main(String[] args) {
            try {
                DataInputStream in = new DataInputStream(System.in);
                String next = in.readLine();
                while (next != null && next.length() > 0 && !next.contains("end")) {
                    final String arg = next;
                    Thread thread = new Thread(arg) {
                        public void run() {
                        System.out.println(arg);
                        }
                    };

                    thread.start();

                    try {
                        thread.join();
                    } catch (Exception e){ }

                    next = in.readLine();
                }
            } catch (Exception e) {}
        }
    }
    -----

AppMain3 は入力されたテキストをそのまま出力します。"end" 文字列、または EOF が入力されると止まります。Byteman エージェント・リスナーと一緒に AppMain3 を起動すると、AppMain3 の読み込み待機中にルールのロード/アンロードができます。またプログラムに解析され注入されたルールの型チェックや実行された状態チェックもできます。

エージェント・リスナーを有効にするには、エージェント・オプション「listener:true」を使います。

<Linux>
 -----
 $ java -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=listener:true,boot:${BYTEMAN_HOME}/lib/byteman.jar -Dorg.jboss.byteman.transform.all org.my.AppMain3
-----

<Windows>
-----
> java -javaagent:%BYTEMAN_HOME%\lib\byteman.jar=listener:true,boot:%BYTEMAN_HOME%\lib\byteman.jar -Dorg.jboss.byteman.transform.all org.my.AppMain3
-----

エージェント・リスナーは通信口(サーバー・ソケット)を開いてコマンド入力を待ちます。エージェント・オプションにルールスクリプトが指定しなかったので、まずは入力内容が繰り返されるのみです(★)。

----- 実行例 ---
> java  -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=listener:true,boot:${BYTEMAN_HOME}/lib/byteman.jar -Dorg.jboss.byteman.transform.all org.my.AppMain3
    foo
    foo  --★
    bar
    bar  --★
-----

<Linux>
エージェント・リスナーに処理させる際は bmsubmit.sh を使います。bmsubmit.sh を引数なしで実行すると、インストールされているルールをすべて表示します。

-----
> bmsubmit.sh
 no rules installed  
>
(※現在、ルール未インストール)
-----

※ bmsubmit.sh は別シェルを立ち上げ実行してください。また、AppMain3 は先に起動すして、 bmsubmit.sh と Byteman エージェントがサーバーソケットを経由して対話できるようしておきます。

<Windows>
bmsubmit.bat を実行します。(Byteman リリース 2.0.1 以降)

-----
> bmsubmit
  no rules installed
>
(※現在、ルール未インストール)
-----

(2.0.1 以前のリリースは、リスナーにコマンドを送信するために Java コマンドで Submit クラスを呼び出す必要があります。)
-----
> java -classpath %BYTEMAN_HOME%\lib\byteman-submit.jar org.jboss.byteman.agent.submit.Submit
  no rules installed
>
-----

次に bmsubmit.sh を使って実行中のプログラムにルール・スクリプトをロードします。

<Linux>
-----
> bmsubmit.sh -l thread.btm
 install rule trace thread start
>
(※ルール・スクリプト trace がインストールされました。)
-----

<Windows>
bmsubmit.bat を使います。
 
(リリース 2.0.1 以前は、Submitクラスに -l 引数を付与して実行します。
-----
> java -classpath %BYTEMAN_HOME%\lib\byteman-submit.jar org.jboss.byteman.agent.submit.Submit -l thread.btm
  install rule trace thread start
>
(※ルール・スクリプト trace がインストールされました。)
-----

インストールされたルールのステータスを再確認すれば、ルールがロードされ解析されて Thread.start() メソッドに注入されていることが確認できます。もしルールの完全な解析に失敗した場合は、注入が阻止されたことと詳細を含む解析エラーが出力されます。
-----解析エラー-----
> bmsubmit.sh
  # File thread.btm line 4
  RULE trace thread start
  CLASS java.lang.Thread
  METHOD start()
  AT ENTRY
  IF true
  DO traceln("*** start for thread: "+ $0.getName())
  ENDRULE
  Transformed in:
  loader: sun.misc.Launcher$AppClassLoader@5acac268
  trigger method: java.lang.Thread.start() void
>
-----

実行中のAppMain3で入力を進めるとルールが実行されたことが確認できます。
    -----
    . . .
    bar
    bar
    baz
    *** start for thread: baz
    baz
    mumble
    *** start for thread: mumble
    mumble
    -----