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