LoginSignup
2
1

More than 5 years have passed since last update.

Minishift環境でWildFlyとMySQL構成のmaven-webappをデプロイする

Last updated at Posted at 2019-02-02

これまで作成したMavenのwebappを、今度はMinishift上のOpenShiftコンテナオーケストレーション環境で動かしてみる、という内容です。

Minishiftのインストール・構築についてはこちら
Minishiftを使ってVirtualBox上にOpenShift環境をつくる - Qiita

※「Minishiftってなに?」「OpenShiftってなに??」「コンテナオーケストレーションっておいしいの?」「コンテナってなんや?」あたりの説明はすっ飛ばしています。

プロジェクトの作成

まず作業用のプロジェクトを作る。
デフォルトでmyprojectが割り当てられているが、せっかくなので別途プロジェクト(ネームスペース)を作る。

OpenShiftでは基本的にシステム単位でネームスペースを分ける感じにするとよさそう。(ネームスペース横断してPod間通信を行うには工夫が必要)

oc new-appでプロジェクトを作成すると、自動でそのプロジェクトが選択された状態になる。

zaki@mascarpone% oc new-project samplepj
Now using project "samplepj" on server "https://192.168.99.100:8443".

You can add applications to this project with the 'new-app' command. For example, try:

    oc new-app centos/ruby-25-centos7~https://github.com/sclorg/ruby-ex.git

to build a new example application in Ruby.
zaki@mascarpone% 

ネーミングセンスの無さよ…

MySQL

MinishiftではMySQLは標準で使用できる状態で構築される。
標準で使用できるイメージについては、openshiftというネームスペースに配置されている

zaki@mascarpone% oc get is -n openshift mysql
NAME      DOCKER REPO                       TAGS                         UPDATED
mysql     172.30.1.1:5000/openshift/mysql   latest,5.5,5.6 + 1 more...   3 weeks ago

また、アプリケーションによってはパラメタなどの指定やPVの設定などが簡単にできるようにTemplateも含まれている。MinishiftのMySQLではmysql-persistentというPV設定を含むTemplateが最初から準備されている。

zaki@mascarpone% oc get template -n openshift mysql-persistent
NAME               DESCRIPTION                                                                        PARAMETERS        OBJECTS
mysql-persistent   MySQL database service, with persistent storage. For more information about u...   9 (3 generated)   4
zaki@mascarpone% 

パラメタ(と省略時のデフォルト値)については、describeコマンドで確認できる。

zaki@mascarpone% oc describe template -n openshift mysql-persistent

...snip...

Parameters:              
    Name:               MEMORY_LIMIT
    Display Name:       Memory Limit
    Description:        Maximum amount of memory the container can use.
    Required:           true
    Value:              512Mi

    Name:               NAMESPACE
    Display Name:       Namespace
    Description:        The OpenShift Namespace where the ImageStream resides.
    Required:           false
    Value:              openshift

    Name:               DATABASE_SERVICE_NAME
    Display Name:       Database Service Name
    Description:        The name of the OpenShift Service exposed for the database.
    Required:           true
    Value:              mysql

    Name:               MYSQL_USER
    Display Name:       MySQL Connection Username
    Description:        Username for MySQL user that will be used for accessing the database.
    Required:           true
    Generated:          expression
    From:               user[A-Z0-9]{3}

    Name:               MYSQL_PASSWORD
    Display Name:       MySQL Connection Password
    Description:        Password for the MySQL connection user.
    Required:           true
    Generated:          expression
    From:               [a-zA-Z0-9]{16}

    Name:               MYSQL_ROOT_PASSWORD
    Display Name:       MySQL root user Password
    Description:        Password for the MySQL root user.
    Required:           true
    Generated:          expression
    From:               [a-zA-Z0-9]{16}

    Name:               MYSQL_DATABASE
    Display Name:       MySQL Database Name
    Description:        Name of the MySQL database accessed.
    Required:           true
    Value:              sampledb

    Name:               VOLUME_CAPACITY
    Display Name:       Volume Capacity
    Description:        Volume space available for data, e.g. 512Mi, 2Gi.
    Required:           true
    Value:              1Gi

    Name:               MYSQL_VERSION
    Display Name:       Version of MySQL Image
    Description:        Version of MySQL image to be used (5.7, or latest).
    Required:           true
    Value:              5.7

とにかく動かすのであれば、

項目 内容
DATABASE_SERVICE_NAME クラスタ環境上でのサービス名
MYSQL_USER デプロイ時に作成するDBユーザ
MYSQL_PASSWORD 作成するユーザのパスワード
MYSQL_DATABASE デプロイ時に作成するDB

を指定しておけば最低限動作する。
サービス名は、ほかのPodからの名前解決にも使用される。

デプロイ

ユーザ名・パスワード・DB名を、作成済みアプリケーションに合わせて、以下の設定でMySQLをデプロイする。

項目
DATABASE_SERVICE_NAME memoapp-db
MYSQL_USER memoapp
MYSQL_PASSWORD memoapp
MYSQL_DATABASE memoapp_db
zaki@mascarpone% oc new-app mysql-persistent -p DATABASE_SERVICE_NAME=memoapp-db -p MYSQL_USER=memoapp -p MYSQL_PASSWORD=memoapp -p MYSQL_DATABASE=memoapp_db
--> Deploying template "openshift/mysql-persistent" to project samplepj

     MySQL
     ---------
     MySQL database service, with persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/mysql-container/blob/master/5.7/root/usr/share/container-scripts/mysql/README.md.

     NOTE: Scaling to more than one replica is not supported. You must have persistent volumes available in your cluster to use this template.

     The following service(s) have been created in your project: memoapp-db.

            Username: memoapp
            Password: memoapp
       Database Name: memoapp_db
      Connection URL: mysql://memoapp-db:3306/

     For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/mysql-container/blob/master/5.7/root/usr/share/container-scripts/mysql/README.md.

     * With parameters:
        * Memory Limit=512Mi
        * Namespace=openshift
        * Database Service Name=memoapp-db
        * MySQL Connection Username=memoapp
        * MySQL Connection Password=memoapp
        * MySQL root user Password=2f044g2TyeVyxt3o # generated
        * MySQL Database Name=memoapp_db
        * Volume Capacity=1Gi
        * Version of MySQL Image=5.7

--> Creating resources ...
    secret "memoapp-db" created
    service "memoapp-db" created
    persistentvolumeclaim "memoapp-db" created
    deploymentconfig.apps.openshift.io "memoapp-db" created
--> Success
    Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
     'oc expose svc/memoapp-db' 
    Run 'oc status' to view your app.

これでDBは動作する。簡単ですね。

Connection URL: mysql://memoapp-db:3306/と表示されている通り、 このネームスペースのほかのPodからであれば このURLでDBアクセスができる。

MySQLのPodが起動できたかどうかはoc get podREADYの状態が1/1STATUSRunningになっていればOK

zaki@mascarpone% oc get pod
NAME                 READY     STATUS    RESTARTS   AGE
memoapp-db-1-2lsjj   1/1       Running   0          27s

まぁできれば、ほかにはoc logsコマンドでPod内のログを確認もするとより良い。

webapp

minishiftってTomcatはデフォルトで入ってないのかーっていろいろチェックしたら、WildFlyというAPサーバが標準で使用できる状態になっていた。

わいるどふらい(WildFly)って何?から学ぶEJB - ponsuke_tarou’s blog

WildFlyという存在を知らなかった…(JavaEE方面は疎いので)

というわけで、このAPサーバを使用してみます。
(Tomcatを使えるようにしたり、DockerHubでなくRed HatのコンテナレジストリからAPサーバのイメージを取得する、という方法もある。が、今回はWildFlyを使用)

Red Hat Container Catalog (RHCC) を使ってみよう! | RED HAT OPENEYE -レッドハットの情報ポータル

Tomcat→WildFly対応

APサーバをTomcatからWildFly v13.0に変更するにあたり、そのままだと動かないので修正を行う。
※ これはコンテナ化による修正・変更でなく、APサーバの変更に伴う修正。

14:12:17,627 ERROR [stderr] (default task-2) javax.naming.NameNotFoundException: comp/env -- service jboss.naming.context.java.comp.env
14:12:17,632 ERROR [stderr] (default task-2)    at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:106)
14:12:17,632 ERROR [stderr] (default task-2)    at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:207)
14:12:17,632 ERROR [stderr] (default task-2)    at org.jboss.as.naming.InitialContext$DefaultInitialContext.lookup(InitialContext.java:237)

変更点はJNDIデータソース周りの設定

  • (XML)JDBCによるDBサーバの定義の仕方の変更

  • (Javaコード)名前空間の参照方法の変更

    • Tomcatだと例え<GlobalNamingResources>でグローバルな設定を行っても、グローバルな名前空間でJNDIアクセスするわけではなかった。
    • Apache Tomcat 8 (8.5.37) - JNDI Resources HOW-TO / Using resources

      All configured entries and resources are placed in the java:comp/env portion of the JNDI namespace

      Tomcatでは全てのリソースはjava:com/envでアクセスするようになっているが、ほかのAPサーバはそでもない。

    • JNDIをさらっと振り返る - nekop's blog

    • 変更点はこちら

      src/main/java/jp/example/www/dao/MemoappDaoImpl.java
      --- a/src/main/java/jp/example/www/dao/MemoappDaoImpl.java
      +++ b/src/main/java/jp/example/www/dao/MemoappDaoImpl.java
      @@ -27,6 +27,5 @@ public class MemoappDaoImpl implements MemoappDao {
                  //con = DriverManager.getConnection(url, user, pass);
                  Context initContext = new InitialContext();
      -           Context envContext  = (Context)initContext.lookup("java:/comp/env");
      -           DataSource ds = (DataSource)envContext.lookup("jdbc/memoapp_db");
      +           DataSource ds = (DataSource)initContext.lookup("jdbc/memoapp_db");
                  con = ds.getConnection();
                  System.out.println("con: " + con);
      @@ -71,6 +70,5 @@ public class MemoappDaoImpl implements MemoappDao {
                  //con = DriverManager.getConnection(url, user, pass);
                  Context initContext = new InitialContext();
      -           Context envContext  = (Context)initContext.lookup("java:/comp/env");
      -           DataSource ds = (DataSource)envContext.lookup("jdbc/memoapp_db");
      +           DataSource ds = (DataSource)initContext.lookup("jdbc/memoapp_db");
                  con = ds.getConnection();
                  smt = con.createStatement();
      

DBアクセスの日本語設定

前述のJNDI周りの変更を行うことで、APからDBへアクセス可能になるが、デフォルトのMySQL設定だとエンコード設定が日本語対応していないため、Java側から日本語アクセス可能な設定を行う。
※ これもコンテナ化による修正・変更でなく、DBサーバのエンコード設定をサーバ側で設定するのではなくクライアント側で対処する、という内容。

<connection-url>に指定するJDBCのURIに、エンコーディング設定を付加する。
こんな感じ

<connection-url>jdbc:mysql://memoapp-db:3306/memoapp_db?useUnicode=yes&amp;characterEncoding=utf8</connection-url>

また、テーブル作成時にエンコード情報を付与してcreate tableする

src/main/java/jp/example/www/dao/MemoappDaoImpl.java
--- a/src/main/java/jp/example/www/dao/MemoappDaoImpl.java
+++ b/src/main/java/jp/example/www/dao/MemoappDaoImpl.java
@@ -99,5 +99,6 @@ public class MemoappDaoImpl implements MemoappDao {
                     "create_date DATETIME comment '作成日'," +
                     "modified_date DATETIME comment '更新日'," +
-                    "primary key (memo_id)" + ")";
+                    "primary key (memo_id)" + ") " +
+                    "engine=InnoDB default charset=utf8";
             // create table
             smt.executeUpdate(create_table);

今回はMySQLは標準のものをそのまま使用しDBサーバ側の設定で日本語対応していないので、アプリケーション側で可能な日本語設定を行っている。
DBサーバ側で対応するには、日本語設定を含んだDBのイメージを作成すればよいはず。(未確認)
対応の内容は基本的にVMの場合と同じはず。(未確認)

また、DockerHubにあるMySQL公式イメージであれば、--character-set-serverという起動パラメタがあるみたいなので、これでエンコード設定ができると思われ。(Minishiftで用意してあるイメージはこのパラメタがなさそう)

S2Iを使ったビルドとデプロイ

コンテナ環境でアプリケーションをデプロイするには通常は

  1. アプリケーションのビルド(コンパイルが必要な言語であれば)
  2. コンテナイメージのビルド
    • VM環境であればこの手順がない
    • が、この手順があることで「構築済みの初期状態」のイメージを作ることでいつでも初期状態の環境を作り直すことができる
  3. コンテナのデプロイ
    • 前段で作ったコンテナイメージを「実行」するだけ
    • VM環境であればwarを配置したりの手順に相当かな
    • コンテナ環境でも「(Tomcatとかの)ミドルウェアのコンテナをデプロイ」して、その中にあとからアプリを手動デプロイとかできなくもないけど、オーケストレーション環境でそれをするメリットはあまりないかも…(Podのスケールができないとか)

という手順になるけど、OpenShiftの機能であるS2I(source-to-image)を使うことで、コマンド一発で全部完了することができる。(ついでに言うと、GitのリポジトリURLを指定することで、ソースコードのcloneから全自動)

JavaEEであれば、pom.xmlが含まれていれば認識する模様 (つまりMavenプロジェクトとして作っていればOK)
Creating New Applications - Application Life Cycle Management | Developer Guide | OKD Latest

前置きが長くなったけど、以下のコマンドを実行

zaki@mascarpone% oc new-app openshift/wildfly~https://github.com/zaki-lknr/javaee-memoapp2.git
--> Found image 4dea579 (3 weeks old) in image stream "openshift/wildfly" under tag "13.0" for "openshift/wildfly"

    WildFly 13.0.0.Final 
    -------------------- 
    Platform for building and running JEE applications on WildFly 13.0.0.Final

    Tags: builder, wildfly, wildfly13

    * A source build using source code from https://github.com/zaki-lknr/javaee-memoapp2.git will be created
      * The resulting image will be pushed to image stream tag "javaee-memoapp2:latest"
      * Use 'start-build' to trigger a new build
    * This image will be deployed in deployment config "javaee-memoapp2"
    * Port 8080/tcp will be load balanced by service "javaee-memoapp2"
      * Other containers can access this service through the hostname "javaee-memoapp2"

--> Creating resources ...
    imagestream.image.openshift.io "javaee-memoapp2" created
    buildconfig.build.openshift.io "javaee-memoapp2" created
    deploymentconfig.apps.openshift.io "javaee-memoapp2" created
    service "javaee-memoapp2" created
--> Success
    Build scheduled, use 'oc logs -f bc/javaee-memoapp2' to track its progress.
    Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
     'oc expose svc/javaee-memoapp2' 
    Run 'oc status' to view your app.

oc new-appのコマンド自体はすぐに完了し、裏でbuilder podというリポジトリからソースをcloneしてソースのビルドからイメージのビルドまでを実行するPodが起動する

zaki@mascarpone% oc get all                                                 [~]
NAME                          READY     STATUS    RESTARTS   AGE
pod/javaee-memoapp2-1-build   1/1       Running   0          17s
pod/memoapp-db-1-2lsjj        1/1       Running   0          10m

NAME                                 DESIRED   CURRENT   READY     AGE
replicationcontroller/memoapp-db-1   1         1         1         10m

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/javaee-memoapp2   ClusterIP   172.30.210.59   <none>        8080/TCP   18s
service/memoapp-db        ClusterIP   172.30.11.241   <none>        3306/TCP   10m

NAME                                                 REVISION   DESIRED   CURRENT   TRIGGERED BY
deploymentconfig.apps.openshift.io/javaee-memoapp2   0          1         0         config,image(javaee-memoapp2:latest)
deploymentconfig.apps.openshift.io/memoapp-db        1          1         1         config,image(mysql:5.7)

NAME                                             TYPE      FROM      LATEST
buildconfig.build.openshift.io/javaee-memoapp2   Source    Git       1

NAME                                         TYPE      FROM          STATUS    STARTED          DURATION
build.build.openshift.io/javaee-memoapp2-1   Source    Git@188442f   Running   17 seconds ago   

NAME                                             DOCKER REPO                                TAGS      UPDATED
imagestream.image.openshift.io/javaee-memoapp2   172.30.1.1:5000/samplepj/javaee-memoapp2             
zaki@mascarpone% oc get pod                                                 [~]
ocNAME                      READY     STATUS    RESTARTS   AGE
javaee-memoapp2-1-build   1/1       Running   0          25s
memoapp-db-1-2lsjj        1/1       Running   0          10m

この場合はoc logs -f javaee-memoapp2-1-buildでビルドログ(Mavenの実行状態)を確認できる。

zaki@mascarpone% oc logs -f javaee-memoapp2-1-build

...

Pushing image 172.30.1.1:5000/samplepj/javaee-memoapp2:latest ...
Pushed 0/13 layers, 0% complete
Pushed 1/13 layers, 10% complete
Pushed 2/13 layers, 18% complete
Pushed 3/13 layers, 25% complete
Pushed 4/13 layers, 32% complete
Pushed 5/13 layers, 40% complete
Pushed 6/13 layers, 47% complete
Pushed 7/13 layers, 55% complete
Pushed 8/13 layers, 63% complete
Pushed 9/13 layers, 75% complete
Pushed 9/13 layers, 82% complete
Pushed 10/13 layers, 89% complete
Pushed 10/13 layers, 94% complete
Pushed 11/13 layers, 97% complete
Pushed 12/13 layers, 97% complete
Pushed 13/13 layers, 100% complete
Push successful
zaki@mascarpone% 

ビルドが完了されると、内部で動作しているイメージレジストリへpushされ実行可能状態になり、
そのままPodが起動される。

zaki@mascarpone% oc get pod
NAME                      READY     STATUS      RESTARTS   AGE
javaee-memoapp2-1-build   0/1       Completed   0          4m
javaee-memoapp2-1-rgjqq   1/1       Running     0          11s
memoapp-db-1-2lsjj        1/1       Running     0          15m
zaki@mascarpone

APサーバ関連のPodは、oc logsで確認してエラーがなくlisteningとかstartedとか起動してる感じのログが出ていればOK

07:21:38,706 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://0.0.0.0:9990/management
07:21:38,707 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://0.0.0.0:9990
07:21:38,716 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly Full 13.0.0.Final (WildFly Core 5.0.0.Final) started in 46464ms - Started 698 of 890 services (315 services are lazy, passive or on-demand)

これでDBとwebアプリケーションが動作している状態

zaki@mascarpone% oc get service
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
javaee-memoapp2   ClusterIP   172.30.210.59   <none>        8080/TCP   9m
memoapp-db        ClusterIP   172.30.11.241   <none>        3306/TCP   19m

routerの作成

アプリをデプロイしただけだと、動作しているServiceに対してクラスターの外部からアクセスすることができないため、外部からのアクセス用のRouter Podを作成する。

zaki@mascarpone% oc expose service javaee-memoapp2
route.route.openshift.io/javaee-memoapp2 exposed
zaki@mascarpone%
zaki@mascarpone% oc get route
NAME              HOST/PORT                                        PATH      SERVICES          PORT       TERMINATION   WILDCARD
javaee-memoapp2   javaee-memoapp2-samplepj.192.168.99.100.nip.io             javaee-memoapp2   8080-tcp                 None

これで、http://javaee-memoapp2-samplepj.192.168.99.100.nip.ioに対してアクセスすると、javaee-memoapp2のPodの8080/TCPへルーティングしてくれる、という状態になる。

ちなみに、oc exposeで作成されるRouter Podのドメイン名は、デフォルトでは<サービス名>-<ネームスペース名>.サブドメインとなる。なのでワイルドカードDNSが使用できる環境が基本的には必要。
(--hostnameオプションで任意のホスト名/FQDNを指定することも可能)

ブラウザでwebアクセス

Minishift環境だとrouteで作成したドメイン名はpublicなワイルドカードDNSサービスを使って作られるので特に意識せずに利用できる。
ワイルドカードDNSは nip.io が良い - 約束の地

routeのドメインであるjavaee-memoapp2-samplepj.192.168.99.100.nip.ioにブラウザでアクセスすると…

image.png

そういえばアプリの構成的にコンテキストルートでの動作ではなかった。
/memoapp2のパスを付け加えてアクセス。。

image.png

うごいたああ!!

image.png

日本語入力も大丈夫でした。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1