要は(TL;DR;)
- OpenShift環境下のDevOpsパイプランで、Maven/Javaのビルドが毎回遅いなあ、と思ってる方
- OpenShift上にOSSのリポジトリー・マネージャー Nexus3をデプロイすれば、Mavenプロキシーとなってキャッシュが効くのでビルドが速くなりますよ!
困ったこと
こんにちわ!石田です。今OpenShiftのDevOpsのデモ環境を作ってるんですが、Java/Mavenのビルドが遅いです。。具体的にはソースの変更をトリガーにJavaアプリケーションをOpenShift上のコンテナでMavenビルドする場合、コンテナはビルドの都度、新規作成されるのでMavenのキャッシュがありません。結果として初回のビルドも2回目以降のビルドもインターネット上のMavenリポジトリーからのダウンロードが発生し、結構な時間がかかります。
こんな超シンプルなサーブレットのビルドですが何度やっても毎回60秒前後かかってます
package my;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class SimpleServlet
*/
@WebServlet("/*")
public class SimpleServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().print("<h1><font color=green>Simple Servlet ran successfully</font></h1>"
+ "Powered by WebSphere Application Server Liberty Profile");
}
}
新規コンテナ(Pod)の起動時はキャッシュ($home/.m2/repository)が無いため、repo.maven.apache.orgから以下のように毎回延々ダウンロードが行われています。
[INFO] ------------------------< SimpleApp:SimpleApp >-------------------------
[INFO] Building SimpleApp 1.0
[INFO] --------------------------------[ war ]---------------------------------
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom
Progress (1): 2.2/8.1 kBProgress (1): 5.0/8.1 kBProgress (1): 7.8/8.1 kBProgress (1): 8.1 kB Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom (8.1 kB at 4.4 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-plugins/23/maven-plugins-23.pom
Progress (1): 2.2/9.2 kBProgress (1): 5.0/9.2 kBProgress (1): 7.8/9.2 kBProgress (1): 9.2 kB Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-plugins/23/maven-plugins-23.pom (9.2 kB at 48 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/maven-parent/22/maven-parent-22.pom
.....
念のため、ですが当記事はDevOpsパイプラインでOpenShift上でMavenのビルドを行う場合の話です。つまりs2iを使わない場合=ソースからのMavenビルドをOpenShiftの外(=要は普通のOSのコマンド環境など)で実行してwar/earファイルを作成し、OpenShiftにはwar/earを配置(コピー)するだけの場合は通常のMavenのキャッシュが効くので問題になりません。
mvnビルドの実行時間を短縮する案
まず一般論を言うと、通常の(=コンテナ環境ではない)場合は初回のmvn ビルドの実行時に$home/.m2/repositoryの下にコンテンツがキャッシュされ、2回目以降はキャッシュが参照されるのでビルド時間が短縮されます。
1. s2iのインクリメンタル・ビルドの機構を使って自力で.m2を保管・復元する
同様のことをコンテナ環境に置き換えて考えると、まずはs2iのインクリメンタル・ビルド(s2i build --incremental)を使ってsave-artifactsにて.m2を保管して2回目以降で復元する方法が考えられます。例はこちらなど。ただしこの方法は自分でs2iのスクリプトを実装する必要があること、複数のビルドがあった場合に各々個別に実装する必要があることより、イマイチな印象です。
2. OpenShiftにNexus3をMaven Proxyとしてデプロイする
より簡単で柔軟な方法として、Sonatype社がOSSで提供しているリポジトリー・マネージャー Nexus3を使う方法があります。Nexus3はリポジトリー・マネージャーであり、MavenのみならずDockerレジストリーの代替など様々な用途に使えますが、デフォルトでMavenプロキシーの機能があります。Dockerhub上にコンテナ・イメージが公開されていますので、OpenShift上にデプロイするのも非常に簡単です。OpenShift上でのJava/Mavenビルドの際の参照リポジトリーにNexus3を指定すると、初回はNexus3のMavenプロキシーを介してインターネット上のMavenリポジトリーにアクセスしますが、リソースはNexus3側にキャッシュされます。よって2回目以降のビルドではMavenのリソースがNexus3のキャッシュにヒットするので、ビルド時間が短縮できます。
要はOpenShift内の新規コンテナ(Pod)でmvn packageを実行する場合、
① デフォルトでは毎回ダウンロードが発生します
② Nexus3を稼働させると初回はダウンロードしますがキャッシュされます
③ Nexus3を稼働させた場合の2回目以降のビルドではキャッシュにヒットします(のでダウンロードしません)
やってみた
以下、Nexus3のセットアップと利用の手順をお示しします。
おことわり
- 当記事執筆時点(2020/1月)でネットを検索すると、OpenShift上にNexusをデプロイする方法の記事があれこれヒットします。いくつか試したのですが、記事が古くてそのままでは動かないものも多いようでした。また、Nexus3のリポジトリーの指定方法はじめ、記事によって違う方法を記載しているものもあります。当記事は筆者が執筆時点で実際にやってみて動いた手順を記載していますが、それ以外の方法もあるという点、まずはご認識ください。
- 特にOpenShift 3.11の公式ドキュメント 「Setting Up a Nexus Mirror for Maven」を参考にしました
環境
- IBM Cloud(IaaS)上で稼働するOKD 3.11( on ubuntu 18.04)- oc cluster upで起動したall-in-one構成
OpenShiftへのNexus3イメージのデプロイ
Dockerhub上に上記のイメージが公開されていますので、ocコマンドで簡単にOpenShiftにデプロイできます。
ログインして新しいプロジェクトを作成の上、sonatype/nexus3のイメージをデプロイしてサービスとルートを作ります。
oc login -u developer -p dummy
oc new-project nexus3
oc new-app sonatype/nexus3
oc expose svc/nexus3
oc statusでルート(上の例ではhttp://nexus3-nexus3.162.133.79.188.nip.io)ができていればオーケーです。
handson01@devops01:~$ oc status
In project nexus3 on server https://162.133.79.188:8443
http://nexus3-nexus3.162.133.79.188.nip.io to pod port 8081-tcp (svc/nexus3)
dc/nexus3 deploys istag/nexus3:latest
deployment #1 deployed 2 minutes ago - 1 pod
2 infos identified, use 'oc status --suggest' to see details.
管理コンソール上もPodが起動していますね?
Next3のセットアップ
管理者パスワードの入手
次にNexus3のコンソールに管理者(admin)でログインしてセットアップを行いますが、その前に管理者のパスワードを入手する必要があります。
sonatype/nexus3のサイト記述によると、パスワードはadmin.passwordというファイルに書き込まれているとのこと。
Notes:
Default user is admin and the uniquely generated password can be found in the admin.password file inside the volume. See Persistent Data for information about the volume.
上記の手順でpod名を特定し、oc rshでpodにログインしてから/nexus-data/admin.passwordの中身をcatしてパスワードを入手します。1
handson01@devops01:~$ oc get pods
NAME READY STATUS RESTARTS AGE
nexus3-1-45rpz 1/1 Running 0 2m
handson01@devops01:~$ oc rsh nexus3-1-45rpz
sh-4.4$ find / -name admin.password
find: '/var/cache/ldconfig': Permission denied
find: '/var/lib/private': Permission denied
find: '/var/lib/portables': Permission denied
find: '/lost+found': Permission denied
find: '/proc/tty/driver': Permission denied
/nexus-data/admin.password
sh-4.4$ cat /nexus-data/admin.password
6a37dec6-fc57-41c8-87ac-***********sh-4.4$
Nexus3の管理コンソールへのログイン
ルートで示されたURL(例. http://nexus3-nexus3.162.133.79.188.nip.io) へアクセスし、Nexus3の管理コンソールを開いてから右上の「Sign In」をクリック
ユーザーはadmin, パスワードは先ほど入手したものを入力して「Sign In」
セットアップ・ウイザード
アノニマスなアクセスを許容するかどうか、を指定。今回はパブリックなmaven2リポジトリーをキャッシュする目的なので機密性はなく、ゆえに「Enable anonymous access」にチェックを入れて「Next」
MavenプロキシーのURLの入手
maven package実行時に指定するべきリポジトリーのURLを入手します。
コンソール上部の「歯車マーク(Server Administration and Configulation) 」- 「Repository」- 「Repositories」で表示されリポジトリーの一覧からmaven-centralをクリック
URLの個所がMavenで参照先とすべきURLです。
mavenビルド時の指定
これでNexus3は使えるようになったので、あとはMavenでビルドする際のリポジトリーとして(デフォルトのrepo.maven.apache.orgではなく) Nexus3のMavenプロキシーを参照するようにURLを指定します。
具体的には以下のようにmvn packageによるビルド時に -s nexus-settings.xml
2でユーザー設定ファイルを指定します。
mvn package -s nexus-settings.xml
cp -f target/*.war /config/dropins/
ユーザー設定ファイルの内容は下記で、URL 3個所を書き換えます。3
記述は記事 OpenShift Nexusを参考にしました。
<settings>
<servers>
<server>
<id>nexus</id>
<!-- username>admin</username -->
<!-- password>password</password -->
</server>
</servers>
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://nexus3-nexus3.162.133.79.188.nip.io/repository/maven-central/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://nexus3-nexus3.162.133.79.188.nip.io/repository/maven-central/</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://nexus3-nexus3.162.133.79.188.nip.io/repository/maven-central/</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
結果
上記の指定をしたうえで再度Mavenビルドを実行すると、初回はダウンロードのたえ60秒以上かかりますが、2回目以降はキャッシュが効いて15秒前後でビルドが終了しました!
podのビルドのログでもNexus3を参照していることが分かります。(Downloading from nexus:~)
[INFO]
[INFO] ------------------------< SimpleApp:SimpleApp >-------------------------
[INFO] Building SimpleApp 1.0
[INFO] --------------------------------[ war ]---------------------------------
Downloading from nexus: http://nexus3-nexus3.162.133.79.188.nip.io/repository/maven-central/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom
Progress (1): 4.1/8.1 kBProgress (1): 7.7/8.1 kBProgress (1): 8.1 kB Downloaded from nexus: http://nexus3-nexus3.162.133.79.188.nip.io/repository/maven-central/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom (8.1 kB at 43 kB/s)
Downloading from nexus: http://nexus3-nexus3.162.133.79.188.nip.io/repository/maven-central/org/apache/maven/plugins/maven-plugins/23/maven-plugins-23.pom
Progress (1): 4.1/9.2 kBProgress (1): 7.8/9.2 kBProgress (1): 9.2 kB Downloaded from nexus: http://nexus3-nexus3.162.133.79.188.nip.io/repository/maven-central/org/apache/maven/plugins/maven-plugins/23/maven-plugins-23.pom (9.2 kB at 766 kB/s)
...
おわりに
OpenShift環境でのNexus3のMavenプロキシーは導入や環境設定も非常に簡単で、JavaアプリケーションのDevOpsパイプラインを構築する際のMaven ビルド時間の短縮に効果があります。ぜひお試しください。また、Nexus3を用いてプライベートなDockerイメージ・レジストリーを構築することもできます。OpenShiftには独自のイメージ・レジストリーが標準装備されていますので必要性は薄いかもしれませんが、別の選択肢として覚えておくとよいかもしれません。以上です。