Tomcatで動作するJavaアプリケーションをS2Iでコンテナ化してOpenShiftで動作させる方法の備忘録です。
手元にTomcatアプリケーションはあるけど、コンテナ化やOpenShift/k8sの設定が面倒だなというモチベーションで調査した結果を書き残します。
環境情報
アプリケーションの準備
この記事ではコンテナ化してOpenShift上で動作させることを最速で実現するため、 mvn archetype:generate
で生成したシンプルなServlet/JSPアプリケーションを題材とします。
$ mvn archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-webapp \
-DarchetypeVersion=1.4 \
-DgroupId=com.example \
-DartifactId=jws-sample-webapp \
-Dversion=1.0.0 \
-DinteractiveMode=false
$ cd jws-sample-webapp
$ tree .
.
├── pom.xml
└── src
└── main
└── webapp
├── WEB-INF
│ └── web.xml
└── index.jsp
手元のJDKのバージョンと合わせるため、pom.xmlではJavaバージョンを1.7から11に変更します。
<project ...>
<properties>
<mavencompilersource>11</mavencompilersource>
<mavencompilertarget>11</mavencompilertarget>
</properties>
</project>
S2Iでコンテナ化する前に、MavenコマンドでWARファイルを生成できることを確認しておきます。
$ mvn clean package -DskipTests -B -ntp
[INFO] Scanning for projects...
...
[INFO] BUILD SUCCESS
$ ls target/*.war
target/jws-sample-webapp.war
S2IでTomcatアプリケーションをコンテナ化
それでは手元のソースコードをS2IでTomcatアプリケーションでコンテナ化します。
OpenShift CLIの操作例をいくつか例示しますが、 oc login
コマンドでOpenShiftにログイン済みの状態を前提とします。
ビルダーイメージの選択
OpenShiftではTomcatアプリケーションをコンテナ化するビルダーイメージが用意されています。
openshift
プロジェクトのImageStreamから最新のビルダーイメージを検索します。
本記事執筆時点で最新のImageStreamTagであるJBoss Web Server 5.6.2を使用します。
$ # JWSのImageStreamを検索
$ oc get is -n openshift | grep '^jboss-webserver' | cut -d ' ' -f 1 | grep 'openjdk11'
jboss-webserver53-openjdk11-tomcat9-openshift
jboss-webserver54-openjdk11-tomcat9-openshift-rhel7
jboss-webserver54-openjdk11-tomcat9-openshift-ubi8
jboss-webserver56-openjdk11-tomcat9-openshift-ubi8 # これを使う
$ # JWS 5.6のImageStreamからImageStreamTagを検索
$ oc get istag -n openshift | grep 'jboss-webserver56-openjdk11-tomcat9-openshift-ubi8' | cut -d ' ' -f 1
jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:5.6.0
jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:5.6.1
jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:5.6.2 # これを使う
jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:latest
S2Iによるコンテナイメージのビルド
oc
コマンドでBuildConfigリソースを作成し、先ほど検索したImageStreamTagを指定します。
Dockerfileを使わずソースコードからコンテナイメージを作成するため、バイナリビルドのフラグ --binary=true
をコマンドに付与します。
$ oc new-build --name=tomcat-sample-app \
--image-stream=jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:5.6.2 \
--binary=true
--> Found image af8501c (4 months old) in image stream "openshift/jboss-webserver56-openjdk11-tomcat9-openshift-ubi8" under tag "5.6.2" for "jboss-webserver56-openjdk11-tomcat9-openshift-ubi8:5.6.2"
JBoss Web Server 5.6 OpenJDK11
------------------------------
Platform for building and running web applications on JBoss Web Server 5.6 with OpenJDK11 - Tomcat v9
Tags: builder, java, tomcat9
* A source build using binary input will be created
* The resulting image will be pushed to image stream tag "tomcat-sample-app:latest"
* A binary build was created, use 'oc start-build --from-dir' to trigger a new build
--> Creating resources with label build=tomcat-sample-app ...
imagestream.image.openshift.io "tomcat-sample-app" created
buildconfig.build.openshift.io "tomcat-sample-app" created
--> Success
BuildConfigリソースの作成に成功したら、ソースコードのディレクトリを指定してS2Iを実行します。
ビルダーイメージ内のS2Iスクリプトが実行され、コンテナイメージ生成のログが出力されます。
Push successful
と表示されたらコンテナイメージのビルドは成功です。
コンテナイメージはOpenShiftの内部レジストリに格納されます。
$ oc start-build tomcat-sample-app --from-dir=. --follow
Uploading directory "." as binary input for the build ...
(...omit...)
Push successful
アプリケーションのデプロイ
コンテナイメージのビルドが無事完了したら、いよいよOpenShiftにアプリケーションをデプロイ (=コンテナを起動) します。
oc new-app
コマンドで先ほどビルドしたコンテナイメージ名を指定してデプロイします。
ビルダーイメージからビルドしたTomcat (JWS) アプリケーションは、環境変数 ENABLE_ACCESS_LOG
を指定することでアクセスログを出力する Access Log Valve が有効化されます。
$ oc new-app tomcat-sample-app --env=ENABLE_ACCESS_LOG=true
...
--> Creating resources ...
deployment.apps "tomcat-sample-app" created
service "tomcat-sample-app" created
--> Success
出力されたログから、コンテナを起動するDeploymentリソースとServiceリソースが作成されていることがわかります。
OpenShift Webコンソールのトポロジービューで参照すると、Deployment管理下のPodがRunningステータスで実行されているはずです。
(スクリーンショットで表示されているヘルスチェックの設定は別記事で取り上げる予定)
さらに外部からもアクセスできるようにRouteリソースも追加で作成します。
oc get route
で外部からアクセス可能なホスト名を取得できます。
$ oc expose svc/tomcat-sample-app
$ oc get route tomcat-sample-app -o jsonpath='{.spec.host}'
<サンプルアプリのホスト名>
http://<ホスト名>/jws-sample-webapp
にWebブラウザでアクセスするとJSPのページが表示されます。
ホスト名以降のパス (コンテキストルート) はデフォルトでWARファイル名です。
Podのログを参照するとTomcatやJavaのバージョン、そしてアクセスログが出力されています。
$ oc logs tomcat-sample-app-aaaaaa
...
Server version name: Apache Tomcat/9.0.50.redhat-00007
JVM Version: 11.0.16+8-LTS
JVM Vendor: Red Hat, Inc.
CATALINA_BASE: /opt/jws-5.6/tomcat
CATALINA_HOME: /opt/jws-5.6/tomcat
...
<接続元IPアドレス> - - [20/Jan/2023:04:56:27 +0000] <ホスト名> "GET /jws-sample-webapp/ HTTP/1.1" 200 52
参考
以上。