こんにちは、テクマトリックスの酒井です。
Jenkins を使って CI/CD を実現する場合、ジョブを実行して生成されるバイナリやテストレポートなどの成果物は Jenkins のサーバーに保存することが一般的かと思います。しかし成果物は往々にしてサイズが大きく、 Jenkins のサーバーのディスク容量を圧迫してしまい、その結果ビルドが正常に実行できなくなってしまうことを経験した方もいらっしゃるのではないでしょうか。そこで今回は、ジョブを実行して生成される成果物を、 Jenkins とは別のサーバーで実行する MinIO に保存する方法を試してみます。
目次
成果物の保存に関する問題と解決策
一般的に Jenkins でビルドの成果物を保存するには、フリースタイルジョブでは ビルド後の処理
の 成果物の保存
ステップ、パイプラインでは archiveArtifacts
ステップを利用します。またパイプラインでは、後続のステージを実行する別のエージェントで成果物を利用できるよう保存する stash
ステップも利用できます(保存した成果物を復元するには unstash
ステップを利用します)。デフォルトでは、これらのステップは生成されたすべての成果物を Jenkins コントローラーのローカルファイルシステムに保存します。そのため、サイズが大きい成果物を生成するジョブを高頻度に実行するほどディスク容量を消費します。またコンソールの出力も同様に Jenkins コントローラーのローカルファイルシステムに保存されるため、ディスクに空き容量がなくなるとビルドが実行できなくなってしまいます。さらに、成果物の読み書きのために Jenkins のサーバーに高パフォーマンスのファイルシステムが必要となりますし、初期サイズ設定やダウンタイムを伴うサイズ変更などのシステム構成上のすべての問題が発生します。
一方、成果物を保存するのに便利なプラグインは多数提供されています。しかしどのプラグインを利用するにしても、プラグインが提供するステップを利用するようにすべてのジョブやパイプラインを変更する必要があります。そのため残念ながら、 Jenkins とジョブの管理のしやすさと使い勝手の点で 成果物の保存
ステップなどの方が勝ります。
そこで Jenkins プロジェクトでは、この問題の解決策としてクラウドが提供するサービスを利用可能にする改善が行われています。成果物をクラウドストレージに保存することはこの改善の最初期に実装され、参照実装として Artifact Manager on S3 プラグインが利用可能になりました。執筆時点では他にも Azure Artifact Manager プラグイン なども利用可能です。
MinIO とは?
MinIO は、高性能の分散オブジェクトストレージシステムです。これはソフトウェアで定義されるものであり、業界標準のハードウェアで実行され、主要なライセンスが GNU AGPL v3 である 100% オープンソースです。
MinIO は Amazon S3 と互換性のある API を提供します。また普通の Windows や Linux のマシンで実行できます。そのため、会社のセキュリティポリシーなどによりクラウドサービスを自由に利用できなくても、 MinIO を利用して社内に Amazon S3 互換のストレージサービスを立ち上げることが簡単にできます。そしてこのストレージサービスに Jenkins のビルド成果物を保存することで、オンプレミス環境の Jenkins であっても成果物の保存に関する問題を解決できます。
環境を作ってみる
では環境を作っていきます。まずは Jenkins 用と MinIO 用の 2 台のマシンを用意します。
Jenkins 用としては今回は Windows のマシンを用意し、 Jenkins を通常の手順でセットアップしました。この後の手順を行うには Jenkins に管理者としてログインできる必要があります。
MinIO 用のマシンについては、 MinIO は Windows と Linux どちらも対応していますが、今回はコンテナで実行したかったため、 Linux マシンを用意して Docker をインストールしました。
MinIO の実行と設定
Quickstart for Containers に従って MinIO を開始します。
最初に、次のコマンドを実行して MinIO のコンテナを起動します。 docker run
コマンドで設定する 2 つの環境変数 MINIO_ROOT_USER
と MINIO_ROOT_PASSWORD
の値は変更してください。
mkdir -p ~/minio/data
docker run \
-p 9000:9000 \
-p 9001:9001 \
--name minio \
-v ~/minio/data:/data \
-e "MINIO_ROOT_USER=ROOTNAME" \
-e "MINIO_ROOT_PASSWORD=CHANGEME123" \
quay.io/minio/minio server /data --console-address ":9001"
ウェブブラウザで http://<MinIO 用のマシンの IP アドレス>:9001/
にアクセスすると、 MinIO のログインページが表示されます。ここで環境変数 MINIO_ROOT_USER
と MINIO_ROOT_PASSWORD
に設定した値を入力してログインします。
次に、成果物を保存するためのバケットを作成します。画面中央の Create a Bucket をクリックし、次の画面で Bucket Name にバケット名として jenkins
と入力して、 Create Bucket ボタンをクリックします。
これで新しいバケットが作成されました。
最後に、 MinIO にアクセストークンを作成します。左側メニューの User > Access Keys をクリックし、続いて画面右上の Create access key ボタンをクリックします。次の画面では単に Cteate ボタンをクリックします。 Access Key と Secret Key が表示されますので、これらをメモするかダウンロードしておきます。
これで MinIO の準備ができました。
Jenkins の設定
今度は、成果物の保存先として MinIO を利用するよう、 Artifact Manager on S3 プラグインのドキュメントに従って Jenkins を設定していきます。
最初に、 Artifact Manager on S3 plugin プラグインをインストールします。 Jenkins の管理 > プラグイン > Available plugins の順に移動し、 Artifact Manager on S3 plugin をインストールします。インストールが完了したら、念のため Jenkins を再起動します。
続いて、成果物の保存先を設定します。 Jenkins の管理 > システム の順に移動し、 Artifact Manager for Builds までスクロールします。 追加 をクリックして Cloud Artifact Storage
を選択し、続いて Cloud provider に Amazon S3
を選択します。
次は、 MinIO にアクセスするための認証情報を設定します。 Jenkins の管理 > AWS の順に移動し、ページ下部の Amazon Credentials にて Amazon Credentials を設定します。 追加 > Jenkins の順にクリックし、次のように認証情報を設定して追加します。
項目 | 値 | 説明 |
---|---|---|
Domain | グローバルドメイン | |
種類 | AWS Credentials | |
スコープ | グローバル | |
ID | minio-access-key | 任意の値 |
説明 | (空欄) | 入力は任意 |
Access Key ID | MinIO のアクセストークンの Access Key | |
Secret Access Key | MinIO のアクセストークンの Secret Key | |
IAM Role Support | デフォルトのまま | 入力の必要なし |
認証情報を追加したら、 Amazon Credentials にてたった今追加した認証情報(MinIO のアクセストークンの Access Key)を選択し、 適用 ボタンをクリックします。
最後に、ページ上部の Amazon S3 Bucket Access settings を設定します。少なくとも以下を設定します。
項目 | 値 | 説明 |
---|---|---|
S3 Bucket Name | jenkins | MinIO で作成したバケット名 |
Custom Endpoint | localhost:9000 | MinIO を実行した Docker ホストと、 MinIO の API ポート番号 |
Custom Signing Region | (空欄) | |
Use Path Style URL | オン | |
Use Insecure HTTP | オン | |
Use Transfer Acceleration | オフ | |
Disable Session Token | オン |
入力後 Validate S3 Bucket configuration をクリックして success と表示されることを確認します。
最後に Save ボタンをクリックして、設定は完了です。
成果物の保存を試してみる
環境ができましたので、今度はジョブを作成して実行し、成果物が MinIO に保存されていることを確認してみます。
パイプラインジョブの作成
Jenkins のダッシュボードに戻り、パイプラインジョブ minio-demo
を作成します。パイプラインジョブの設定にて以下のパイプラインコードを入力します。
pipeline {
agent any
stages {
stage('Test') {
steps {
powershell '''
# スクリプト行を実行時に出力
Set-PSDebug -Trace 1
# ワークスペースをクリーンアップ
Remove-Item -Path *.* -Recurse -Force
# テキストファイルを生成
"Hello ${Env:BUILD_TAG}" > build-tag.txt
# レポートを生成
New-Item -Path "report" -ItemType Directory -Force | Out-Null
Invoke-WebRequest -Uri "https://www.jenkins.io/images/logos/jenkins/jenkins.png" -OutFile "report\\logo.png"
'<html><body><img src="logo.png"></body></html>' > report\\report.html
'''
archiveArtifacts artifacts: '*.txt, report/**' <em>// 成果物を保存</em>
}
}
}
}
このパイプラインコードでは、 powershell
ステップにて build-tag.txt
というテキストファイルと、 report
ディレクトリ以下にテストレポートファイル一式(実際には、画像ファイルとそれを参照する HTML ファイル)を作成します。そして archiveArtifacts
ステップにてこれらのファイルを保存します。
実行と確認
minio-demo
パイプラインジョブのページにて ビルド実行 をクリックしてビルドを開始します。ビルドが完了(成功)したら、ビルド番号をクリックしてビルドのページに移動します。すると、保存されたビルドの成果物の一覧が表示されます。
ここで成果物の一つを選択すると、 MinIO に保存されているファイルを参照することができます。このときブラウザは MinIO の URL を表示しており、 Jenkins を経由せずに直接 MinIO を参照していることが分かります。
成果物が保存されている様子は MinIO でも確認できます。左側メニューの User > Object Browser に移動し、 jenkins
バケットを選択すると、パイプラインジョブ名と同じ minio-demo
フォルダがあります。 minio-demo
、ビルド番号、 artifacts
の順にフォルダに移動すると、成果物ファイルやフォルタが表示され、保存されていることが分かります。もちろんここからビルド成果物をダウンロードすることもできます。
なお Jenkins のビルドのページで report.html
を開くと、 HTML は表示されますが画像が表示されません。理由は、選択した成果物を表示する際は URL に MinIO の認証情報が付きますが、 HTML からリンクされた画像などの URL には認証情報が付かないためです。 MinIO でバケットのアクセスポリシーやアクセスルールなどを適切に設定することで、 URL に認証情報が付いていなくても表示することができるようになります。例えば、 Administrator > Buckets > jenkins
> Anonymous にて、 Prefix が /
、 Access が readonly
のアクセスルールを追加すると、 repot.html
を選択したときに画像も表示可能になります。
気になったこと
この記事を書き始めたとき、 MinIO も Windows 上で実行するつもりでした。しかし Windows 用の MinIO を使用すると、 Jenkins 上の一部のリンクが機能しませんでした。具体的には、 Jenkins の成果物のページにある「参照」リンク、および、「(全てのファイルを zip で)」のリンクをクリックすると、怒った執事が表示されてしまいました。 OS を Windows に統一したい方には残念ですが、この記事の執筆時点では MinIO は Windows 以外の OS で実行するのが良いと思われます。
まとめ
Jenkins の Artifact Manager on S3 プラグインと、オブジェクトストレージシステムの MinIO を利用して、ジョブやパイプラインを変更することなく、ビルド成果物を Jenkins とは別のサーバーに保存することができました。これにより、ディスク不足によって Jenkins がビルドを実行できなくなる可能性が低減できます。また Jenkins のサーバーに高速で大容量のディスクを多数接続したりディスク増設のために Jenkins を停止したりする必要性もなくなります。結果として、多数の開発者が Jenkins を安定して利用できるようになり、 Jenkins の管理者にとっても管理の労力を削減できると感じました。ただ、 MinIO を Windows で実行すると問題が発生することがあるため、本記事の執筆時点では Windows 以外の OS で MinIO を実行した方が良いと思います。