Liberty InstantOn を Ubuntu で試してみた

Open Liberty の InstantOn を Ubuntu 環境で試してみました。
InstantOn を利用すると、Open Liberty のコンテナを瞬時に起動できるようです。0.1秒程度で、Java の Web アプリケーションが起動できるというのは、感動ものです。

## 環境の準備
今まで利用していた Ubuntu は、20.04 でしたが、このバージョンではイメージのビルドが失敗してしまうので、22.04 にアップグレードしました。さらに、IP v6 を無効化しておくとビルドが失敗するので、IP v6 を有効化しました。
利用した環境は、以下の通りです。

- Ubuntu 22.04.2 LTS (IP v6 有効化)
- Podman 3.4.2

## ビルドの準備
Open Liberty の InstantOn は beta として公開されていて、逐次更新されています。今回は、2023年2月10日に公開された、以下の blog を参考にしました。

- [New enhancements for Liberty InstantOn in 23.0.0.2-beta](
https://openliberty.io/blog/2023/02/10/instant-on-beta-update.html)

また、アプリはなんでもよいと想定し、Github で公開されている以下のアプリを利用しました。server.xml と war ファイルをコピペまたはダウンロードしてそのまま利用しています。

- [ICpTrial/liberty-test-app](https://github.com/ICpTrial/liberty-test-app/tree/main/SimpleWebTest/JavaEE-8)

ビルドに利用する Dockerfile (以下参照) で注すべき点は、次の２点です。その他は、InstantOn を利用しない場合と同じです。

* FROM で指定するイメージは、InstantOn の beta として公開されいるものを指定
* ビルドの最後のステップとして、`RUN checkpoint.sh afterAppStart` を実行

``` Dockerfile 
FROM icr.io/appcafe/open-liberty:beta
COPY --chown=1001:0 server.xml        /config/
COPY --chown=1001:0 SimpleWebTest.war /config/apps/
RUN configure.sh
RUN checkpoint.sh afterAppStart
```

## イメージをビルドする
準備が整いましたので、イメージをビルドします。
InstantOn 用のビルトでは、-cap-add オプションで必要なケーパビリティ(capability)を追加して、podman build を実行する必要があります。
また、今回は、root ユーザーでビルドを行っています。
ビルドは、以下のコマンドで行いました。

```bash
podman build \
   --cap-add=CHECKPOINT_RESTORE \
   --cap-add=SYS_PTRACE \
   --cap-add=SETPCAP \
   --security-opt seccomp=unconfined \
   -t registry.local:5000/liberty-instant-on .
```

ビルドの最終ステップである `RUN checkpoint.sh afterAppStart` では、Open Liberty が起動され、アプリの起動が完了した時点で InstantOn 用のイメージが作成されます。
ビルド実行時の詳細出力を載せておきます。

<details>
<summary>ビルド実行時の詳細出力</summary>
<div>

```bash
root# podman build \
   --cap-add=CHECKPOINT_RESTORE \
   --cap-add=SYS_PTRACE \
   --cap-add=SETPCAP \
   --security-opt seccomp=unconfined \
   -t registry.local:5000/liberty-instant-on .
STEP 1/5: FROM icr.io/appcafe/open-liberty:beta
Trying to pull icr.io/appcafe/open-liberty:beta...
Getting image source signatures
Checking if image destination supports signatures
Copying blob 1ba1ba8abe7c done
Copying blob c442e356e0cb done
...(省略)...
Copying blob f810e3a2c006 done
Copying config ceb653208d done
Writing manifest to image destination
Storing signatures
STEP 2/5: COPY --chown=1001:0 server.xml        /config/
--> 06a02dc09c5
STEP 3/5: COPY --chown=1001:0 SimpleWebTest.war /config/apps/
--> 806816490b7
STEP 4/5: RUN configure.sh
--> 9e09fd7ee97
STEP 5/5: RUN checkpoint.sh afterAppStart
Performing checkpoint --at=afterAppStart

Launching defaultServer (Open Liberty 23.0.0.7-beta/wlp-1.0.78.cl230620230612-1100) on Eclipse OpenJ9 VM, version 17.0.7+7 (en_US)
CWWKE0953W: This version of Open Liberty is an unsupported early release version.
[AUDIT   ] CWWKE0001I: The server defaultServer has been launched.
[AUDIT   ] CWWKG0093A: Processing configuration drop-ins resource: /opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/keystore.xml
[AUDIT   ] CWWKG0093A: Processing configuration drop-ins resource: /opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/open-default-port.xml
[AUDIT   ] CWWKZ0058I: Monitoring dropins for applications.
[AUDIT   ] CWWKZ0001I: Application SimpleWebTest started in 0.372 seconds.
[AUDIT   ] CWWKC0451I: A server checkpoint "afterAppStart" was requested. When the checkpoint completes, the server stops.
/opt/ol/wlp/bin/server: line 951:   117 Killed                  "${JAVA_CMD}" "$@" >> "${CHECKPOINT_CONSOLE_LOG}" 2>&1 < /dev/null
COMMIT registry.local:5000/liberty-instant-on
--> 1c3483fdd72
Successfully tagged registry.local:5000/liberty-instant-on:latest
1c3483fdd723bc8ae0699fb3f264c2dec112a4003bad54f1c6bd664d712d8697
root# podman images
REPOSITORY                              TAG         IMAGE ID      CREATED             SIZE
registry.local:5000/liberty-instant-on  latest      1c3483fdd723  About a minute ago  1.2 GB
icr.io/appcafe/open-liberty             beta        ceb653208d41  20 hours ago        1.08 GB
root#
```
</div>
</details>

## InstantOn で Liberty を起動
イメージがビルドできましたので、Liberty を InstantOn で起動します。
起動時にも、-cap-add オプションで必要なケーパビリティ(capability)を追加して、podman run を実行する必要があります。
指定する必要があるケーパビリティは、参考にした blog (上記参照) によると、以下の２つとなています。以前は、もっと多くの(強力な)ケーパビリティを指定する必要があったようですが、必要なケーパビリティを減らすように努力されているようです。

- CHECKPOINT_RESTORE
- SETPCAP

しかし、実際にこの２つのケーパビリティだけを追加して起動すると、`Restoring the checkpoint server process failed.` のメッセージが出力され、InstantOn ではなく、通常の起動となってしまいます。

<details>
<summary>通常起動になった場合のコンソール出力</summary>
<div>

```
root# podman run \
   --rm \
   --cap-add=CHECKPOINT_RESTORE \
   --cap-add=SETPCAP \
   -p 9080:9080 \
   -it \
   registry.local:5000/liberty-instant-on
CWWKE0961I: Restoring the checkpoint server process failed. Check the /logs/checkpoint/restore.log log to determine why the checkpoint process was not restored. Launching the server without using the checkpoint image.
Launching defaultServer (Open Liberty 23.0.0.7-beta/wlp-1.0.78.cl230620230612-1100) on Eclipse OpenJ9 VM, version 17.0.7+7 (en_US)
CWWKE0953W: This version of Open Liberty is an unsupported early release version.
[AUDIT   ] CWWKE0001I: The server defaultServer has been launched.
[AUDIT   ] CWWKG0093A: Processing configuration drop-ins resource: /opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/keystore.xml
[AUDIT   ] CWWKG0093A: Processing configuration drop-ins resource: /opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/open-default-port.xml
[AUDIT   ] CWWKZ0058I: Monitoring dropins for applications.
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://ebd4cd3e8c7e:9080/SimpleWebTest/
[AUDIT   ] CWWKZ0001I: Application SimpleWebTest started in 0.446 seconds.
[AUDIT   ] CWWKF0012I: The server installed the following features: [appSecurity-2.0, appSecurity-3.0, beanValidation-2.0, cdi-2.0, distributedMap-1.0, ejbLite-3.2, el-3.0, jaspic-1.1, jaxrs-2.1, jaxrsClient-2.1, jdbc-4.2, jndi-1.0, jpa-2.2, jpaContainer-2.2, jsf-2.3, jsonb-1.0, jsonp-1.1, jsp-2.3, managedBeans-1.0, servlet-4.0, ssl-1.0, transportSecurity-1.0, webProfile-8.0, websocket-1.1].
[AUDIT   ] CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in 3.217 seconds.
```
</div>
</details>

コンテナ内に出力された `/logs/checkpoint/restore.log` を確認すると、`ptrace(PTRACE_TRACEME) failed: Operation not permitted` の出力があり、ケーパビリティ SYS_PTRACE が不足しているように見えました。

<details>
<summary>/logs/checkpoint/restore.log の内容</summary>
<div>

```
bash-4.4$ cat /logs/checkpoint/restore.log
Warn  (criu/kerndat.c:1103): $XDG_RUNTIME_DIR not set. Cannot find location for kerndat file
Error (criu/arch/x86/kerndat.c:178): 28: ptrace(PTRACE_TRACEME) failed: Operation not permitted
Error (criu/arch/x86/kerndat.c:229): Born child is unstoppable! (might be dead)
Error (criu/arch/x86/kerndat.c:248): Failed to kill my own child: No such process
Error (criu/arch/x86/kerndat.c:250): Failed wait for a dead child: No child processes
Error (criu/kerndat.c:901): kdat_x86_has_ptrace_fpu_xsave_bug failed
Error (criu/kerndat.c:1758): kerndat_x86_has_ptrace_fpu_xsave_bug failed when initializing kerndat.
Error (criu/crtools.c:263): Could not initialize kernel features detection.
bash-4.4$
```
</div>
</details>


SYS_PTRACE を追加し、以下の３つのケーパビリティを指定して起動したところ、無事に InstantOn で起動できました。

- CHECKPOINT_RESTORE
- SETPCAP
- SYS_PTRACE

```bash
podman run \
   --rm \
   --cap-add=CHECKPOINT_RESTORE \
   --cap-add=SYS_PTRACE \
   --cap-add=SETPCAP \
   -p 9080:9080 \
   -it \
   registry.local:5000/liberty-instant-on
```

```
[AUDIT   ] Launching defaultServer (Open Liberty 23.0.0.7-beta/wlp-1.0.78.cl230620230612-1100) on Eclipse OpenJ9 VM, version 17.0.7+7 (en_US)
[AUDIT   ] CWWKZ0001I: Application SimpleWebTest started in 0.078 seconds.
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://06eada085613:9080/SimpleWebTest/
[AUDIT   ] CWWKC0452I: The Liberty server process resumed operation from a checkpoint in 0.099 seconds.
[AUDIT   ] CWWKF0012I: The server installed the following features: [appSecurity-2.0, appSecurity-3.0, beanValidation-2.0, cdi-2.0, distributedMap-1.0, ejbLite-3.2, el-3.0, jaspic-1.1, jaxrs-2.1, jaxrsClient-2.1, jdbc-4.2, jndi-1.0, jpa-2.2, jpaContainer-2.2, jsf-2.3, jsonb-1.0, jsonp-1.1, jsp-2.3, managedBeans-1.0, servlet-4.0, ssl-1.0, transportSecurity-1.0, webProfile-8.0, websocket-1.1].
[AUDIT   ] CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in 0.105 seconds.
```

Liberty のコンソール出力では `server started in 0.105 seconds` となっていました。
まさに、爆速で起動します!!!

ちなみに、Liberty は軽量ランタイムなので、通常起動でも２秒程度で起動しました。今回は、小さなアプリを使用したので差が少ないですが、大きなアプリであればより差が開くものと思われます。

# 終わりに
いくつか躓く部分がありましたが、無事に Open Liberty の InstantOn を Ubuntu 環境で確認することができました。
Java の Web アプリケーションが0.1秒程度で起動できるというのは、本当に驚きです。