OpenShiftの再現環境作成のコツ - 第2回 一からビルド

OpenShiftの再現環境作成のコツ - 第2回

こんにちは、Red Hat Partner Technical Account Managerのイアンです。

シリーズの前回では、JBoss EAP Quickstartsを使ってOpenShiftへのサンプルアプリのデプロイと修正方法を説明しました。 また、JBoss EAP OpenShift Templatesも使って、アプリに必要なリソースをすぐ作成できました。

当記事では、テンプレートを使わずにローカルのソースコードのOpenShiftへのデプロイ方法を紹介します。

当シリーズ

目次

事前準備

サンプルアプリ

事前準備として、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): 外部からアプリをアクセスするためのルーティング定義

デプロイの流れ

大まかな流れは次です:

  1. ImageStreamとBuildConfigを作成する
  2. ビルドを行う
  3. DeploymentConfigを作成する
  4. 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:latestImageStreamに保存します。

ビルド時には、$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

ビルド開始

BuildConfigImageStreamができたら、ビルドを開始できます。

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の作成

外からアクセスするためには、先に作成したServiceexposeする必要があります。

$ 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 ほどになります。

次回は、ランタイムイメージの使い方を説明します。


  1. 各Quickstartは親の pom.xml を参照しているため、 helloworld-rs だけをOpenShiftへ転送したら、親のPOMが見つからず、エラーになります。対応としては、 helloworld-rs のPOMを修正し、親の依存を無くし、スタンドアローンにすることです。
  2. DeploymentDeploymentConfigの違いについては、Understanding Deployments and DeploymentConfigsを参照ください。
  3. ocskopeoコマンドを使って、作ったイメージのサイズを確認できます。

    OpenShift Local (CRC)の場合は、oc registry login --insecure=trueを実行し、コンテナレジストリの認証情報を取得します。

    skopeojqコマンドを組み合わせて、イメージの中の各レイヤーのサイズを合計します。

    $ skopeo inspect --tls-verify=false docker://default-route-openshift-image-registry.apps-crc.testing/sandbox/eap-app | jq '[.LayersData[]|.Size]|add'
    683122420
    

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。