nekop's blog

OpenShift / JBoss / WildFly / Infinispanの中の人 http://twitter.com/nekop

OpenShiftでファイルをシングルファイルマウントで置き換える

OpenShift 全部俺 Advent Calendar 2017

OpenShiftやKubernetesではConfigMapを使ってファイルを差し替えることができます。今日はJBoss EAPのstandalone-openshift.xmlをConfigMapでカスタマイズしたいなー、と思ってやってみたらストレートに行かなかった話です。

まず普通にJBoss EAPのアプリを放り込みます。

$ oc new-project test-javaee
$ oc policy add-role-to-user view -z default
$ oc new-app eap70-basic-s2i -p APPLICATION_NAME=hello-javaee -p SOURCE_REPOSITORY_URL=https://github.com/nekop/hello-javaee -p SOURCE_REPOSITORY_REF= -p CONTEXT_DIR= -p MAVEN_MIRROR_URL=http://nexus.example.com:8081/nexus/content/groups/mirror/

JBoss EAPのコンテナイメージは/opt/eap/standalone/configuration/standalone-openshift.xmlを利用するようになっているので、まずはファイルの内容はまったく変更しないで、standalone-openshift.xmlをConfigMapに移してConfigMapのsubPath指定でvolume mountして差し替えます。

$ oc create configmap eap-config --from-file=./standalone-openshift.xml
$ oc volumes dc/hello-javaee --add --name=eap-config --configmap-name=eap-config --default-mode=0777 --mount-path=/opt/eap/standalone/configuration/standalone-openshift.xml --sub-path=standalone-openshift.xml

すると、CrashLoopしました。なんでやねん。

$ oc get pod
NAME                    READY     STATUS             RESTARTS   AGE
hello-javaee-1-build    0/1       Completed          0          1m
hello-javaee-2-deploy   1/1       Running            0          33s
hello-javaee-2-p9bcj    0/1       CrashLoopBackOff   1          31s

ログを見るとsedDevice or resource busyで失敗しているログがずらずら出ており、JBoss EAPは設定ファイルが不正で起動できません、という状態になっています。

$ oc logs -p hello-javaee-2-p9bcj
sed: cannot rename /opt/eap/standalone/configuration/sedezxomS: Device or resource busy
sed: cannot rename /opt/eap/standalone/configuration/sedjGz72R: Device or resource busy
sed: cannot rename /opt/eap/standalone/configuration/sedCDOG5Q: Device or resource busy
sed: cannot rename /opt/eap/standalone/configuration/sedBrYC5Q: Device or resource busy
sed: cannot rename /opt/eap/standalone/configuration/sedwG75aV: Device or resource busy
(省略)
07:03:43,188 ERROR [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0055: Caught exception during boot: org.jboss.as.controller.persistence.ConfigurationPersistenceException: WFLYCTL0085: Failed to parse configuration
    at org.jboss.as.controller.persistence.XmlConfigurationPersister.load(XmlConfigurationPersister.java:131) [wildfly-controller-2.1.18.Final-redhat-1.jar:2.1.18.Final-redhat-1]
    at org.jboss.as.server.ServerService.boot(ServerService.java:362) [wildfly-server-2.1.18.Final-redhat-1.jar:2.1.18.Final-redhat-1]
    at org.jboss.as.controller.AbstractControllerService$1.run(AbstractControllerService.java:301) [wildfly-controller-2.1.18.Final-redhat-1.jar:2.1.18.Final-redhat-1]
    at java.lang.Thread.run(Thread.java:748) [rt.jar:1.8.0_151]
Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[131,9]
Message: WFLYCTL0133: Missing required attribute(s): default-job-repository

設定ファイルの内容を変更していないのになぜこのようなエラーになるのでしょうか。

JBoss EAPのコンテナイメージは起動スクリプト環境変数の内容からさまざまな設定をstandalone-openshift.xmlsedコマンドで適用します。ログではsedコマンドがDevice or resource busyで失敗していたので、もうわかりますね。ConfigMapによるファイルの差し替えを行ったので、このファイルはマウントポイントになっています。それをsedで「置き換え」しようとしているのですが、マウントポイントであるため置き換えができず、Device or resource busyというエラーとなっています。結局書き換えられるはずの設定ファイルが書き換えられないまま不完全な状態で起動シーケンスに入ってクラッシュしていたのでした。ちなみにファイルを置き換えるのではなく、編集するのであれば成功します。あとoc debugで起動するとマウントポイントでもファイルの置き換えが可能になる挙動を確認しましたが、今回は深追いしません。

コンテナイメージ作成者は設定ファイルのテンプレートは実際の設定ファイルではなく、別のファイルにしましょう。そうすればテンプレートと出力先ファイルが同一なので置き換えられない、という今回の問題は回避できます。また、記事では触れませんでしたがオリジナルのstandalone-openshift.xmlを取り出すにも一工夫必要となります。というのも、起動したコンテナから取り出すと既に起動スクリプトが設定変更を適用した後のファイルとなってしまうため、oc debugで起動したコンテナから取得しないといけなかったり面倒でした。

というわけで、設定テンプレート元ファイルと実際の設定ファイル、同一のロケーションにするのはやめましょう、というお話でした。

JBoss EAPについてはチケットを作成しましたが、以前のバージョンとの互換性とかも気にしないといけないのですぐには解決できないんじゃないかなー、という雰囲気です。チケットに書いた通り、/opt/eap/standalone/configuration/ディレクトリをまるっとConfigMap化すると大丈夫です。