はじめに
AzureのOpenShift/Kubernetesサービスでは、Open Libertyオペレーターと連携してコンテナ化したアプリケーションをデプロイすることができるようです。
この記事では、「Red Hat OpenShift on IBM Cloud(バージョン4.8.18)」でOpen Libertyオペレーターを使用してみます。
Azureのようにクラウド管理画面との連携まではできません。
なお、名称こそ「Open Libertyオペレーター」ですが、WebSphere Libertyにも対応しています。
The Open Liberty Operator can be used to deploy and manage applications running on either Open Liberty or WebSphere Liberty into Kubernetes-based platforms, such as Red Hat OpenShift.
1. 事前準備
1.1. Open Libertyオペレーターの導入
OpenShiftコンソールからOpen Libertyオペレーターを導入します。
2. Open Libertyオペレーターの使用
2.1. コンテナイメージのビルド
OpenShiftでコンテナイメージをビルドします。結果としてイメージストリームが作成されます。
ls -l
### 標準出力
-rw-r--r--. 1 root root 139 8月 7 10:22 Dockerfile
-rw-r--r--. 1 root root 737 9月 18 10:36 server.xml
-rw-r--r--. 1 root root 13139005 9月 18 16:40 spring-liberty-plain.war
oc new-project spring-liberty
oc new-build --name=spring-liberty --strategy=docker --binary
oc start-build spring-liberty --from-dir=. --follow
### 標準出力↓
Uploading directory "." as binary input for the build ...
.
Uploading finished
build.build.openshift.io/spring-liberty-1 started
Receiving source from STDIN as archive ...
Caching blobs under "/var/cache/blobs".
Pulling image open-liberty:21.0.0.7-full-java11-openj9 ...
・・・
STEP 1: FROM open-liberty:21.0.0.7-full-java11-openj9
STEP 2: COPY server.xml /config/
--> 1ce86755aaa
STEP 3: COPY spring-liberty-plain.war /config/apps/
--> 0ebeedd7a1d
STEP 4: USER 1001
--> 8f1a193ebf3
STEP 5: EXPOSE 9080
--> 2fcad284cea
・・・
Successfully pushed image-registry.openshift-image-registry.svc:5000/spring-liberty/spring-liberty@sha256:62bffa1c6839eec7c69a2c7bd187999a84597191b572
b3a4a76e4ec862ec4cc8
Push successful
oc get is
### 標準出力↓
NAME IMAGE REPOSITORY TAGS UPDATED
spring-liberty image-registry.openshift-image-registry.svc:5000/spring-liberty/spring-liberty latest 25 seconds ago
Dockerfile等資材に関しては以下の記事を参照ください。
2.2. コンテナのデプロイ(Deployment)
「OpenLibertyApplication」のマニフェストによりコンテナをデプロイします。
Open LibertyオペレーターによりDeployment、Service、Routeが作成されます。
oc apply -f spring-liberty-deploy.yaml
oc get pod,deploy
### 標準出力↓
NAME READY STATUS RESTARTS AGE
pod/spring-liberty-1-build 0/1 Completed 0 8m19s
pod/spring-liberty-56c54596f5-hprkg 1/1 Running 0 46s
pod/spring-liberty-56c54596f5-ncf6w 1/1 Running 0 46s
pod/spring-liberty-56c54596f5-zr9gq 1/1 Running 0 46s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/spring-liberty 3/3 3 3 46s
oc get svc,route
### 標準出力↓
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/spring-liberty ClusterIP 172.21.26.32 <none> 9080/TCP 61s
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
route.route.openshift.io/spring-liberty spring-liberty.apps.ocp.cloud.vpc spring-liberty 9080-tcp None
apiVersion: openliberty.io/v1beta1
kind: OpenLibertyApplication
metadata:
name: spring-liberty
spec:
applicationImage: image-registry.openshift-image-registry.svc:5000/spring-liberty/spring-liberty:latest
replicas: 3
readinessProbe:
httpGet:
path: /healthz
port: 9080
service:
type: ClusterIP
port: 9080
expose: true
route:
host: spring-liberty.apps.ocp.cloud.vpc
以下の記事では、Deployment、Service、Ingressのマニフェストを個別に用意していました。
2.3. コンテナのデプロイ(StatefulSet)
「OpenLibertyApplication」のマニフェストで『storage』を指定すると、DeploymentではなくStatefulSetとしてデプロイされます。StorageClassは指定していないため、Persistent Volumeは「Red Hat OpenShift on IBM Cloud」デフォルトのStorageClassから作成されています。
oc apply -f spring-liberty-sts.yaml
oc get pod,sts
### 標準出力↓
NAME READY STATUS RESTARTS AGE
pod/spring-liberty-0 1/1 Running 0 5m9s
pod/spring-liberty-1 1/1 Running 0 4m19s
pod/spring-liberty-1-build 0/1 Completed 0 16m
pod/spring-liberty-2 1/1 Running 0 2m35s
NAME READY AGE
statefulset.apps/spring-liberty 3/3 5m9s
oc get pv,pvc,sc
### 標準出力↓
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM
STORAGECLASS REASON AGE
persistentvolume/pvc-2f92b7d3-c64f-4ae9-8804-506497a03df1 10Gi RWO Delete Bound spring-liberty/pvc-spring-liberty-2
ibmc-vpc-block-10iops-tier 2m21s
persistentvolume/pvc-b7d1512c-8fff-43b6-b0be-ca2ca2b3c083 10Gi RWO Delete Bound spring-liberty/pvc-spring-liberty-1
ibmc-vpc-block-10iops-tier 4m16s
persistentvolume/pvc-d48f7511-ebb3-49ca-9859-ecf0196b2090 10Gi RWO Delete Bound spring-liberty/pvc-spring-liberty-0
ibmc-vpc-block-10iops-tier 6m13s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS
AGE
persistentvolumeclaim/pvc-spring-liberty-0 Bound pvc-d48f7511-ebb3-49ca-9859-ecf0196b2090 10Gi RWO ibmc-vpc-block-10iops-tier
6m38s
persistentvolumeclaim/pvc-spring-liberty-1 Bound pvc-b7d1512c-8fff-43b6-b0be-ca2ca2b3c083 10Gi RWO ibmc-vpc-block-10iops-tier
4m35s
persistentvolumeclaim/pvc-spring-liberty-2 Bound pvc-2f92b7d3-c64f-4ae9-8804-506497a03df1 10Gi RWO ibmc-vpc-block-10iops-tier
2m51s
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXP
ANSION AGE
storageclass.storage.k8s.io/ibmc-vpc-block-10iops-tier (default) vpc.block.csi.ibm.io Delete Immediate false
21d
…
apiVersion: openliberty.io/v1beta1
kind: OpenLibertyApplication
metadata:
name: spring-liberty
spec:
applicationImage: image-registry.openshift-image-registry.svc:5000/spring-liberty/spring-liberty:latest
replicas: 3
readinessProbe:
httpGet:
path: /healthz
port: 9080
service:
type: ClusterIP
port: 9080
expose: true
route:
host: spring-liberty.apps.ocp.cloud.vpc
storage:
size: 2Gi
mountPath: "/logs"
3. Javaダンプ
3.1. コンテナイメージ再作成とコンテナ再デプロイ(Deployment)
「OpenLibertyDump」のマニフェストによりJavaダンプを出力することが可能です。
DockerfileにJavaダンプ出力先ディレクトリ/serviceabilityを追加してコンテナイメージを再作成後、「OpenLibertyApplication」のマニフェストにannotationsを追加してコンテナを再デプロイしました。
※ /serviceability用PVを設定可能ですが、複数Podから読み書きできる(ReadWriteMany)必要があります。
oc start-build spring-liberty --from-dir=. --follow
oc apply -f spring-liberty-dump.yaml
oc get pod
### 標準出力↓
NAME READY STATUS RESTARTS AGE
spring-liberty-1-build 0/1 Completed 0 21m
spring-liberty-2-build 0/1 Completed 0 109s
spring-liberty-76f56dbc7-7w9gb 1/1 Running 0 30s
spring-liberty-76f56dbc7-9tk46 1/1 Running 0 31s
spring-liberty-76f56dbc7-gszv5 1/1 Running 0 30s
FROM open-liberty:21.0.0.7-full-java11-openj9
COPY server.xml /config/
COPY spring-liberty-plain.war /config/apps/
USER root
RUN mkdir /serviceability \
&& chmod 775 /serviceability
USER 1001
EXPOSE 9080
apiVersion: openliberty.io/v1beta1
kind: OpenLibertyApplication
metadata:
name: spring-liberty
annotations:
openliberty.io/day2operations: OpenLibertyTrace,OpenLibertyDump
spec:
applicationImage: image-registry.openshift-image-registry.svc:5000/spring-liberty/spring-liberty:latest
replicas: 3
readinessProbe:
httpGet:
path: /healthz
port: 9080
service:
type: ClusterIP
port: 9080
expose: true
route:
host: spring-liberty.apps.ocp.cloud.vpc
# serviceability:
# size: 2G
3.2. Javaダンプ出力
「OpenLibertyDump」のマニフェストを適用してJavaダンプを出力します。
oc apply -f liberty-dump.yaml
oc get OpenLibertyDump
### 標準出力↓
NAME STARTED COMPLETED DUMP FILE
liberty-dump True True /serviceability/spring-liberty/spring-liberty-76f56dbc7-7w9gb/2021-11-23_09:55:07.zip
apiVersion: openliberty.io/v1beta1
kind: OpenLibertyDump
metadata:
name: liberty-dump
spec:
podName: spring-liberty-76f56dbc7-7w9gb
include:
- thread
- heap
3.3. Javaダンプ内容確認
zipファイルを展開すると、Javaダンプ(heapdump/javacore)だけでなく、Open Libertyの構成ファイルも含まれていました。なお、「apps」ディレクトリは存在しますが、アプリケーションのクラスファイルは含まれません。
oc cp spring-liberty-76f56dbc7-7w9gb:serviceability/spring-liberty/spring-liberty-76f56dbc7-7w9gb/2021-11-23_09:55:07.zip liberty-dump.zip
unzip liberty-dump.zip
ls -l
### 標準出力↓
合計 20172
drwxr-xr-x. 3 root root 4096 11月 23 18:45 apps
drwxr-x---. 3 root root 4096 11月 23 09:55 autopdzip
drwxr-xr-x. 4 root root 4096 11月 23 18:45 configDropins
drwxr-x---. 5 root root 4096 11月 23 09:55 dump_21.11.23_09.55.08
-rw-r-----. 1 root root 12439816 11月 23 09:55 heapdump.20211123.095508.1.0002.phd
-rw-r-----. 1 root root 1567866 11月 23 09:55 javacore.20211123.095508.1.0001.txt
-rw-r--r--. 1 root root 6609454 11月 23 18:45 liberty-dump.zip
drwxrwx---. 3 root root 4096 11月 23 09:54 logs
-rw-rw----. 1 root root 41 7月 8 19:25 server.env
-rw-------. 1 root root 737 11月 23 09:55 server.xml
drwxrwx---. 5 root root 4096 11月 23 09:54 workarea
4. Open Libertyトレース
4.1. トレース出力
「OpenLibertyTrace」のマニフェストにより動的にトレースを開始することも可能です。
oc apply -f liberty-trace.yaml
oc get OpenLibertyTrace
### 標準出力↓
NAME PODNAME TRACING
liberty-trace spring-liberty-7694cd676c-74gcn True
apiVersion: openliberty.io/v1beta1
kind: OpenLibertyTrace
metadata:
name: liberty-trace
spec:
podName: spring-liberty-76f56dbc7-7w9gb
traceSpecification: "*=info:com.ibm.ws.webcontainer*=all"
maxFileSize: 20
maxFiles: 5
4.2. トレース内容確認
トレースもJavaダンプと同じディレクトリ/serviceability以下に作成されます。
トレース出力中だったためか、「oc cp」コマンド実行時に『unexpected EOF』エラーが発生しました。
oc rsh spring-liberty-76f56dbc7-7w9gb ls -l /serviceability/spring-liberty/spring-liberty-76f56dbc7-7w9gb
### 標準出力↓
total 6912
-rw-r-----. 1 1000670000 root 6609454 Nov 23 09:55 2021-11-23_09:55:07.zip
-rw-r-----. 1 1000670000 root 682 Nov 23 09:59 messages.log
-rw-r-----. 1 1000670000 root 443086 Nov 23 10:00 trace.log
oc cp spring-liberty-76f56dbc7-7w9gb:serviceability/spring-liberty/spring-liberty-76f56dbc7-7w9gb/messages.log messages.log
oc cp spring-liberty-76f56dbc7-7w9gb:serviceability/spring-liberty/spring-liberty-76f56dbc7-7w9gb/trace.log trace.log
cat messages.log
### 標準出力
cat messages.log
********************************************************************************
product = Open Liberty 21.0.0.7 (wlp-1.0.54.cl210720210629-1900)
wlp.install.dir = /opt/ol/wlp/
server.output.dir = /opt/ol/wlp/output/defaultServer/
java.home = /opt/java/openjdk
java.version = 11.0.11
java.runtime = OpenJDK Runtime Environment (11.0.11+9)
os = Linux (3.10.0-1160.45.1.el7.x86_64; amd64) (en_US)
process = 1@172.17.57.140
********************************************************************************
[11/23/21, 9:59:43:656 GMT] 00000031 com.ibm.ws.config.xml.internal.ConfigRefresher A CWWKG0017I: The server configuration was successfu
lly updated in 2.160 seconds.
head trace.log
### 標準出力↓
********************************************************************************
product = Open Liberty 21.0.0.7 (wlp-1.0.54.cl210720210629-1900)
wlp.install.dir = /opt/ol/wlp/
server.output.dir = /opt/ol/wlp/output/defaultServer/
java.home = /opt/java/openjdk
java.version = 11.0.11
java.runtime = OpenJDK Runtime Environment (11.0.11+9)
os = Linux (3.10.0-1160.45.1.el7.x86_64; amd64) (en_US)
process = 1@172.17.35.184
trace.specification = *=info:com.ibm.ws.webcontainer*=all
5. その他
特徴的な挙動として、コンテナイメージを再作成したときに、Open Libertyオペレーターがコンテナを自動的に再デプロイしていました。「IMAGE REFERENCE」を参照しているようです。DeploymentでもStatefulSetでも同様の挙動でした。
"msg":"Updating status.imageReference" ~
oc logs open-liberty-operator-67cf5884d9-lnlq2 -n openshift-operators
### 標準出力↓
{"level":"info","ts":1637661932.6835837,"logger":"controller_openlibertyapplication","msg":"Reconcile OpenLibertyApplication - starting","Request.Namespace":"spring-liberty","Request.Name":"spring-liberty"}
{"level":"info","ts":1637661932.7600996,"logger":"controller_openlibertyapplication","msg":"Updating status.imageReference","Request.Namespace":"spring-liberty","Request.Name":"spring-liberty","status.imageReference":"image-registry.openshift-image-registry.svc:5000/spring-liberty/spring-liberty@sha256:c0782b52a2f5b632f5f48be4c70a692c4f5825a606a90e986169f50a9c8e22fb"}
{"level":"info","ts":1637661932.8776283,"logger":"utils","msg":"Reconciled","Kind":"ServiceAccount","Namespace":"spring-liberty","Name":"spring-liberty","Status":"updated"}
{"level":"info","ts":1637661932.9335113,"logger":"utils","msg":"Reconciled","Kind":"Service","Namespace":"spring-liberty","Name":"spring-liberty","Status":"updated"}
{"level":"info","ts":1637661932.9897504,"logger":"utils","msg":"Reconciled","Kind":"Deployment","Namespace":"spring-liberty","Name":"spring-liberty","Status":"updated"}
{"level":"info","ts":1637661933.0669138,"logger":"utils","msg":"Reconciled","Kind":"Route","Namespace":"spring-liberty","Name":"spring-liberty","Status":"updated"}
{"level":"info","ts":1637661933.0883825,"logger":"controller_openlibertyapplication","msg":"Reconcile OpenLibertyApplication - completed","Request.Namespace":"spring-liberty","Request.Name":"spring-liberty"}
{"level":"info","ts":1637661933.1198273,"logger":"controller_openlibertyapplication","msg":"Reconcile OpenLibertyApplication - starting","Request.Namespace":"spring-liberty","Request.Name":"spring-liberty"}
{"level":"info","ts":1637661933.265982,"logger":"utils","msg":"Reconciled","Kind":"ServiceAccount","Namespace":"spring-liberty","Name":"spring-liberty","Status":"updated"}
{"level":"info","ts":1637661933.3053844,"logger":"utils","msg":"Reconciled","Kind":"Service","Namespace":"spring-liberty","Name":"spring-liberty","Status":"updated"}
{"level":"info","ts":1637661933.3651812,"logger":"utils","msg":"Reconciled","Kind":"Deployment","Namespace":"spring-liberty","Name":"spring-liberty","Status":"updated"}
{"level":"info","ts":1637661933.416343,"logger":"utils","msg":"Reconciled","Kind":"Route","Namespace":"spring-liberty","Name":"spring-liberty","Status":"updated"}
{"level":"info","ts":1637661933.4378707,"logger":"controller_openlibertyapplication","msg":"Reconcile OpenLibertyApplication - completed","Request.Namespace":"spring-liberty","Request.Name":"spring-liberty"}
oc get istag
### 標準出力↓
NAME IMAGE REFERENCE UPDATED
spring-liberty:latest image-registry.openshift-image-registry.svc:5000/spring-liberty/spring-liberty@sha256:c0782b52a2f5b632f5f48be4c70a692c4f5825a606a90e986169f50a9c8e22fb About a minute ago
OpenShift独自のDeploymentConfigであれば、イメージストリーム更新をトリガーに自動更新できることは認識していました。今回、DeploymentやStatefulSetであってもオペレーターで同様の機能を実現可能なことが分かりました。ソースコードも公開されているので、そのような要件がある場合は参考になりそうです。