こんにちは、テクマトリックスの酒井です。

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 に設定した値を入力してログインします。

MinIO にログインした直後

次に、成果物を保存するためのバケットを作成します。画面中央の 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 を選択します。

Artifact Management for Builds の設定

次は、 MinIO にアクセスするための認証情報を設定します。 Jenkins の管理 > AWS の順に移動し、ページ下部の Amazon Credentials にて Amazon Credentials を設定します。 追加 > Jenkins の順にクリックし、次のように認証情報を設定して追加します。

項目説明
Domainグローバルドメイン
種類AWS Credentials
スコープグローバル
IDminio-access-key任意の値
説明(空欄)入力は任意
Access Key IDMinIO のアクセストークンの Access Key
Secret Access KeyMinIO のアクセストークンの Secret Key
IAM Role Supportデフォルトのまま入力の必要なし

認証情報を追加したら、 Amazon Credentials にてたった今追加した認証情報(MinIO のアクセストークンの Access Key)を選択し、 適用 ボタンをクリックします。

Amazon Credentials の設定

最後に、ページ上部の Amazon S3 Bucket Access settings を設定します。少なくとも以下を設定します。

項目説明
S3 Bucket NamejenkinsMinIO で作成したバケット名
Custom Endpointlocalhost:9000MinIO を実行した Docker ホストと、 MinIO の API ポート番号
Custom Signing Region(空欄)
Use Path Style URLオン
Use Insecure HTTPオン
Use Transfer Accelerationオフ
Disable Session Tokenオン

入力後 Validate S3 Bucket configuration をクリックして success と表示されることを確認します。

Amazon S3 Bucket Access settings の設定

最後に 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 を参照していることが分かります。

build-tag.txt を表示した様子

成果物が保存されている様子は MinIO でも確認できます。左側メニューの User > Object Browser に移動し、 jenkins バケットを選択すると、パイプラインジョブ名と同じ minio-demo フォルダがあります。 minio-demo、ビルド番号、 artifacts の順にフォルダに移動すると、成果物ファイルやフォルタが表示され、保存されていることが分かります。もちろんここからビルド成果物をダウンロードすることもできます。

MinIO に保存された成果物

なお 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 を実行した方が良いと思います。

By tsakai

Jenkins関連のサービスやCloudBees製品を主に担当しています。 Certified CloudBees Jenkins Engineer (CCJE) および CloudBees CI DevOps Associate です。