OpenShiftの再現環境作成のコツ - 第2回
こんにちは、Red Hat Partner Technical Account Managerのイアンです。
シリーズの前回では、JBoss EAP Quickstartsを使ってOpenShiftへのサンプルアプリのデプロイと修正方法を説明しました。 また、JBoss EAP OpenShift Templatesも使って、アプリに必要なリソースをすぐ作成できました。
当記事では、テンプレートを使わずにローカルのソースコードのOpenShiftへのデプロイ方法を紹介します。
当シリーズ
- OpenShiftの再現環境作成のコツ - 第1回 Quickstarts紹介
- OpenShiftの再現環境作成のコツ - 第2回 一からビルド
- OpenShiftの再現環境作成のコツ - 第3回 ランタイムイメージの利用
目次
事前準備
サンプルアプリ
事前準備として、JBoss EAP Quickstartsをローカルへクローンします。
$ git clone https://github.com/jboss-developer/jboss-eap-quickstarts.git
今回も helloworld-rs を利用しますが、 pom.xml を修正し、jboss-eap-quickstartsから切り抜きます1。
helloworld-rs/pom.xml に対して、以下の変更を行ってください。 変更は、quickstart-parentの依存関係を無くし、JBoss EAPのBOMとリポジトリの定義を追加し、ビルド時のプラグインを定義します。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.jboss.eap.quickstarts</groupId>
- <artifactId>quickstart-parent</artifactId>
- <!--
- Maintain separation between the artifact id and the version to help prevent
- merge conflicts between commits changing the GA and those changing the V.
- -->
- <version>7.4.0.GA</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
+ <groupId>org.jboss.eap.quickstarts</groupId>
<artifactId>helloworld-rs</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>Quickstart: helloworld-rs</name>
<description>A simple Hello World project that uses JAX-RS</description>
+ <properties>
+ <maven.compiler.source>11</maven.compiler.source>
+ <maven.compiler.target>11</maven.compiler.target>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.bom</groupId>
+ <artifactId>jboss-eap-jakartaee8-with-tools</artifactId>
+ <version>7.4.0.GA</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <repositories>
+ <repository>
+ <releases>
+ <enabled>true</enabled>
+ <updatePolicy>never</updatePolicy>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ <updatePolicy>never</updatePolicy>
+ </snapshots>
+ <id>jboss-public-repository-group</id>
+ <name>JBoss Public Repository Group</name>
+ <url>https://repository.jboss.org/nexus/content/groups/public/</url>
+ <layout>default</layout>
+ </repository>
+ <repository>
+ <releases>
+ <enabled>true</enabled>
+ <updatePolicy>never</updatePolicy>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ <updatePolicy>never</updatePolicy>
+ </snapshots>
+ <id>jboss-enterprise-maven-repository</id>
+ <name>JBoss Enterprise Maven Repository</name>
+ <url>https://maven.repository.redhat.com/ga/</url>
+ <layout>default</layout>
+ </repository>
+ </repositories>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ <id>jboss-public-repository-group</id>
+ <name>JBoss Public Repository Group</name>
+ <url>https://repository.jboss.org/nexus/content/groups/public/</url>
+ </pluginRepository>
+ <pluginRepository>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ <id>jboss-enterprise-maven-repository</id>
+ <name>JBoss Enterprise Maven Repository</name>
+ <url>https://maven.repository.redhat.com/ga/</url>
+ </pluginRepository>
+ </pluginRepositories>
+
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -65,6 +115,34 @@
</dependency>
</dependencies>
-
-
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>3.2.3</version>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>openshift</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>3.2.3</version>
+ <configuration>
+ <warName>ROOT</warName>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
</project>
OpenShiftの準備
リソースを作る前に、新しいプロジェクトを作ります。
今回は、sandboxという名前を利用します。
$ oc new-project sandbox
次のコマンドで最新版のJBoss EAPのImageStreamをsandboxにインポートします。
oc create -f \ https://raw.githubusercontent.com/jboss-container-images/jboss-eap-openshift-templates/eap74/eap74-openjdk11-image-stream.json
アプリに必要なリソース
OpenShiftでアプリをビルドとデプロイするために、以下のリソースがよく使われています:
- BuildConfig (
bc): アプリのビルドとイメージ作成を管理する - ImageStream (
is): アプリのイメージを管理する - DeploymentConfig (
dc): ビルドしたアプリのデプロイ定義
3つが揃えば、アプリをビルドし、デプロイすることは可能ですが、OpenShiftの外からはアクセスできません。 アプリにアクセスするためには、更に次のリソースも必要です:
- Service (
svc): アプリをアクセスするためのサービス定義 - Route (
route): 外部からアプリをアクセスするためのルーティング定義
デプロイの流れ
大まかな流れは次です:
- ImageStreamとBuildConfigを作成する
- ビルドを行う
- DeploymentConfigを作成する
- ServiceとRouteを作成し、アプリを公開する
それぞれの手順を見てみましょう。
ImageStreamの作成
oc create imagestream eap-app コマンドを用いてアプリ用のImageStreamを作成します。
必須ではありませんが、全てのリソースに分かりやすいラベルを付けると、表示や削除するときが楽になります。
$ oc label is/eap-app application=eap-app
BuildConfigの作成
アプリのビルドを管理するBuildConfigを作成します。
次のYAML定義を buildconfig.yaml に保存し、oc create -f buildconfig.yamlコマンドでBuildConfigを作成します。
kind: BuildConfig apiVersion: build.openshift.io/v1 metadata: name: eap-app labels: application: eap-app spec: runPolicy: Serial source: type: Binary strategy: sourceStrategy: env: - name: GALLEON_PROVISION_LAYERS value: jaxrs-server from: kind: ImageStreamTag name: jboss-eap74-openjdk11-openshift:latest namespace: sandbox type: Source output: to: kind: ImageStreamTag name: eap-app:latest
BuildConfigは、jboss-eap74-openjdk11-openshift:latestのイメージを使って、アプリのソースをビルドします。
ビルドしたイメージをeap-app:latestのImageStreamに保存します。
ビルド時には、$GALLEON_PROVISION_LAYERSの環境変数を定義しています。
利用可能なレイヤーの詳細は5.2. 利用可能な JBoss EAP レイヤーをご参照ください。
もし、YAMLが苦手な場合は、ocコマンドで必要なリソースを作成することも可能ですが、リソースによってYAMLほど定義できる項目が限られています。
当記事では、YAMLの定義を利用します。
ocコマンドでBuildConfigの定義は次です:
$ oc new-build --name eap-app \
--binary \
--strategy source \
--image-stream jboss-eap74-openjdk11-openshift:latest \
-l application=eap-app \
-e GALLEON_PROVISION_LAYERS=jaxrs-server
ビルド開始
BuildConfigとImageStreamができたら、ビルドを開始できます。
helloworld-rs ディレクトリに入り、以下のoc start-buildコマンドを実行します。
$ oc start-build eap-app --from-dir=. -F Uploading directory "." as binary input for the build ... Uploading finished build.build.openshift.io/eap-app-1 started Receiving source from STDIN as archive ... ... Writing manifest to image destination Storing signatures Successfully pushed image-registry.openshift-image-registry.svc:5000/sandbox/eap-app@sha256:c2886f188bf30e9909ad7b2055640050f0e7ed42aa44a467fcdec9435131de51 Push successful
ローカルディレクトリのソースコードを圧縮し、OpenShiftへ転送してから、ビルドを開始します。
ビルドが成功したら、出来上がったイメージをImageStreamにプッシュします。
oc get is/eap-appコマンドでImageStreamの状態を確認できます。
$ oc get is/eap-app NAME IMAGE REPOSITORY TAGS UPDATED eap-app default-route-openshift-image-registry.apps-crc.testing/sandbox/eap-app latest 6 seconds ago
DeploymentConfig作成
ビルドが完了したら、コンテナイメージが出来上がりますが、デプロイされていません。
イメージをデプロイするためには、Deployment、もしくはDeploymentConfigを用意する必要があります2。
当記事では、triggersが使えるDeploymentConfigを利用します。
次のYAMLを dc.yaml に保存し、oc create -f dc.yamlコマンドでDeploymentConfigを作成します。
kind: DeploymentConfig apiVersion: apps.openshift.io/v1 metadata: name: eap-app labels: application: eap-app spec: replicas: 1 selector: deploymentconfig: eap-app template: metadata: labels: application: eap-app deploymentconfig: eap-app spec: containers: - env: - name: ENABLE_ACCESS_LOG value: "true" image: sandbox/eap-app imagePullPolicy: Always name: eap-app ports: - containerPort: 8080 protocol: TCP resources: {} restartPolicy: Always securityContext: {} terminationGracePeriodSeconds: 30 triggers: - type: ConfigChange - imageChangeParams: automatic: true containerNames: - eap-app from: kind: ImageStreamTag name: eap-app:latest type: ImageChange
デプロイの確認
DeploymentConfigが作成されたら、すぐアプリのデプロイが開始され、Podが起動されます。
$ oc get pods -l deploymentconfig=eap-app NAME READY STATUS RESTARTS AGE eap-app-1-5dktn 1/1 Running 0 54s
よくできました! 無事にアプリをビルドし、デプロイできました。
Pod上の稼働確認
EAPアプリのPodが動いていますが、まだ公開していない状態です。 この状態でも、アプリの動作を確認できます。
oc rsh <pod name>コマンドを使って、対象のPodに対してシェルを起動します。
次は、curlを使って、Podの中のEAPにアクセスします。
$ oc rsh eap-app-1-5dktn
sh-4.4$ curl -w "\n" http://localhost:8080/rest/json
{"result":"Hello World!"}
sh-4.4$ exit
$
アプリの公開
Serviceの作成
コンテナ内のJBoss EAPは8080ポートを利用しますので、そのポートを使っているServiceを定義します。
次のYAMLを service.yaml に保存し、oc create -f service.yamlコマンドでServiceを作成します。
kind: Service apiVersion: v1 metadata: name: eap-app labels: app: eap-app spec: ports: - name: http port: 8080 protocol: TCP targetPort: 8080 selector: deploymentconfig: eap-app type: ClusterIP
サービス対象は、deploymentconfig: eap-appのラベルが付いているPodになります。
上のDeploymentConfigで定義しました。
Routeの作成
外からアクセスするためには、先に作成したServiceをexposeする必要があります。
$ oc expose service/eap-app route.route.openshift.io/eap-app exposed
稼働確認
アプリを公開しましたので、稼働確認を行います。
oc get route/eap-app -o jsonpath='{.spec.host}' コマンドでアプリのホスト名を取得します。
curlを使って、httpでアプリにアクセスします。
$ curl -w '\n' http://<host>/rest/json
{"result":"Hello World!"}
再デプロイ
アプリを再デプロイしたい場合は、start-buildをします。
DeploymentConfigにイメージ変更時のTriggerを設定したため、ビルド完了したら、自動的に再デプロイが走ります。
まとめと次回の予告
テンプレートを使わずにローカルのソースコードをすぐOpenShiftへデプロイする方法を紹介しました。
でも、終わりではありません。
今回紹介したやり方だと、JBoss EAP Builder Imageをそのまま利用しています。
ビルダーイメージには、ビルドツール(Maven, s2i)などが含まれていて、最終イメージのサイズが大きいです。
作ったeap-appイメージのサイズは 680MB ほどになります3。
サンプルアプリのテストのためですので、そんなに重要な問題ではありませんが、よりお客様の環境に近づきたい場合は、JBoss EAP Runtime Imageを利用する必要があるかと思います。 ランタイムイメージを利用することによって、最終イメージのサイズが 440MB ほどになります。
次回は、ランタイムイメージの使い方を説明します。
- 各Quickstartは親の pom.xml を参照しているため、 helloworld-rs だけをOpenShiftへ転送したら、親のPOMが見つからず、エラーになります。対応としては、 helloworld-rs のPOMを修正し、親の依存を無くし、スタンドアローンにすることです。↩
-
DeploymentとDeploymentConfigの違いについては、Understanding Deployments and DeploymentConfigsを参照ください。↩ -
ocとskopeoコマンドを使って、作ったイメージのサイズを確認できます。OpenShift Local (CRC)の場合は、
oc registry login --insecure=trueを実行し、コンテナレジストリの認証情報を取得します。skopeoとjqコマンドを組み合わせて、イメージの中の各レイヤーのサイズを合計します。
↩$ skopeo inspect --tls-verify=false docker://default-route-openshift-image-registry.apps-crc.testing/sandbox/eap-app | jq '[.LayersData[]|.Size]|add' 683122420