LibertyコンテナのJVM引数にPod名を渡す

LibertyのJVM引数に、`-Xdump:java:file=/tmp/javacore.%Y%m%d.%H%M%S.<Pod名>.%seq.txt`のようにPod名を設定したい場合のメモ。各Podが同じPersistentVolumeをマウントしていてそこにコアを出力したいが、ファイル名にPod名を入れたいような場合を想定。`jvm.options`ファイルは`server.xml`のように`${env.hogehoge}`みたいな書き方ができない。2通りのやり方がありそう。

- Libertyコンテナの`CMD`を書き換える
- 環境変数`JVM_ARGS`と[Downward API](https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/)を使ってマニフェストで設定

## LibertyコンテナのCMDを書き換える

- [Libertyコンテナでumaskを変える](https://qiita.com/sotoiwa/items/0a78e392fad1cadb50b0)

上記記事に書いたのと同じような方法で、起動コマンドを上書きし、事前にコンテナに配置したテンプレートから起動時に`jvm.options`ファイルを生成する。

```jvm.options
-Xdump:java:file=/tmp/javacore.%Y%m%d.%H%M%S.MY_POD_NAME.%seq.txt
```

```start.sh
#!/bin/bash
sed -i -e s/MY_POD_NAME/${HOSTNAME}/g /config/jvm.options
exec /opt/ibm/wlp/bin/server run defaultServer
```

↑実行権限をつけること

```dockerfile:Dockerfile
FROM websphere-liberty:18.0.0.3-kernel
COPY jvm.options /config/jvm.options
COPY start.sh /
CMD ["/start.sh"]
```

なお、`start.sh`をコンテナの中に入れなくても、マニフェストに記述することもできる。`jvm.options`のテンプレートはConfigMapで注入し、スクリプトはマニフェスト内に記載する。

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: jvm-config
data:
  jvm.options: -Xdump:java:file=/tmp/javacore.%Y%m%d.%H%M%S.MY_POD_NAME.%seq.txt
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: liberty
  name: liberty
spec:
  replicas: 1
  selector:
    matchLabels:
      run: liberty
  template:
    metadata:
      labels:
        run: liberty
    spec:
      containers:
      - image: websphere-liberty:18.0.0.3-kernel
        name: liberty
        args:
        - bash
        - -c
        - |-
          sed -e s/MY_POD_NAME/${HOSTNAME}/g /tmp/jvm-config/jvm.options > /config/jvm.options
          exec /opt/ibm/wlp/bin/server run defaultServer
        volumeMounts:
        - name: jvm-config-volume
          mountPath: /tmp/jvm-config
      volumes:
        - name: jvm-config-volume
          configMap:
            name: jvm-config
```

## 環境変数`JVM_ARGS`とDownward APIを使ってマニフェストで設定

`JVM_ARGS`という環境変数でもJVMに引数を渡すことができる。Downward APIでPod名を環境変数として定義しつつ、その環境変数を使って`JVM_ARGS`環境変数を定義する。

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: liberty
  name: liberty
spec:
  replicas: 1
  selector:
    matchLabels:
      run: liberty
  template:
    metadata:
      labels:
        run: liberty
    spec:
      containers:
      - image: websphere-liberty:18.0.0.3-kernel
        name: liberty
        env:
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: JVM_ARGS
          value: -Xdump:java:file=/tmp/javacore.%Y%m%d.%H%M%S.$(MY_POD_NAME).%seq.txt
```

`${MY_POD_NAME}`ではなく`$(MY_POD_NAME)`とする必要があることに注意。`${MY_POD_NAME}`だとそれがそのまま文字列として渡されてしまう。`$(MY_POD_NAME)`を使うことで、このyamlファイル内で定義された変数のみが参照でき、展開されて設定される。


```:${MY_POD_NAME}の場合
$ kubectl exec -it liberty-88d46548f-4l4ht env | grep JVM_ARGS
JVM_ARGS=-Xdump:java:file=/tmp/javacore.%Y%m%d.%H%M%S.${MY_POD_NAME}.%seq.txt
$
```

```:$(MY_POD_NAME)の場合
$ kubectl exec -it liberty-7fb5688bc6-j8lz7 env | grep JVM_ARGS
JVM_ARGS=-Xdump:java:file=/tmp/javacore.%Y%m%d.%H%M%S.liberty-7fb5688bc6-j8lz7.%seq.txt
$
```