こんにちは!現場の自動化に日夜奮闘している君なら、一度はこんな悩みにぶつかったことがあるはずです。
「Jenkinsのビルドが重い……。よく見たら、過去の成果物や不要なキャッシュファイルがワークスペースを圧迫している」
「特定のスペックを持つエージェント(ノード)に、ジョブの負荷状況を見て動的に仕事を振り分けたいのに、標準機能だけだとカユいところに手が届かない……」
GUIをポチポチしているだけでは、大規模なCI/CDパイプラインの泥臭い課題は解決できません。そこで登場するのが、Jenkinsの心臓部を直接ハックする「Groovy(グルーヴィー)スクリプト」です。
今回は、Jenkinsの裏側を自在に操り、ビルド後の自動クリーンアップとノード間ジョブ遷移を完全に自動化する実践的なテクニックを、優しく丁寧に解説していきます。これをマスターすれば、毎日の運用のストレスが劇的に消え去りますよ!
—
そもそも、なぜJenkinsで「Groovy」なのか?
JenkinsはJavaベースで作られており、その内部では「Groovy」というJVM言語が動いています。
つまり、Groovyを使いこなすということは、JenkinsのAPIを直接叩いて、GUIでは絶対にできない高度な自動化やカスタマイズを自由自在に行えるようになるということです。
「難しそう……」と身構える必要はありません。まずは基本のキから、一緒にステップを踏んでいきましょう。
—
1. 秘密兵器「スクリプトコンソール」を使ってみよう
まずは、Groovyの力を体感するための実験場、「スクリプトコンソール」の使い方を知りましょう。
1. Jenkinsのダッシュボード画面を開く。
2. 左側メニューの [Jenkinsの管理] (Manage Jenkins) をクリック。
3. ツールとアクションの中から [スクリプトコンソール] (Script Console) を選択。
ここに直接Groovyコードを書いて「実行 (Run)」を押すと、Jenkinsのマスター上でコードが即座に実行されます。
例えば、現在動いているJenkinsのバージョンを知りたいときは、こう書くだけです。
// Jenkinsのインスタンスを取得してバージョンを表示する
println “現在のJenkinsバージョン: ${Jenkins.instance.VERSION}”
このコンソールを使えば、これから紹介する高度な処理を安全にテストすることができます。
—
2. ワークスペースの不要ファイルを根こそぎ自動クリーンアップ
ビルドを繰り返すうちに、ワークスペースは `node_modules` やビルドキャッシュ、一時ファイルで膨れ上がります。ディスク容量が圧迫されると、最悪の場合Jenkinsサーバー自体がクラッシュします。
標準のクリーンアッププラグインもありますが、「特定の条件に合致する古いファイルだけを狙い撃ちで消したい」といった細かい要望には、Groovyスクリプトによるジョブ内処理が最も確実です。
以下は、パイプライン(Declarative / Scripted)の `post` セクションや、システム管理スクリプトとして組み込める「容量・経過日数ベースのスマート・クリーンアップ」のコードです。
import hudson.model.
import hudson.FilePath
// 対象のジョブとワークスペースを取得する例
def workspace = Thread.currentThread().executable.workspace
if (workspace.exists()) {
println “=== 🧹 クリーンアップ処理を開始します: ${workspace} ===”
// 例:3日(72時間)以上アクセスされていない一時ファイルを削除する
long thresholdTime = System.currentTimeMillis() – (3L 24 60 60 1000L)
workspace.act(new FilePath.FileCallable
@Override
Void invoke(File f, VirtualChannel channel) throws IOException, InterruptedException {
// ディレクトリ内を走査
f.eachFileRecurse { file ->
// 特定の拡張子や不要なキャッシュディレクトリをターゲットにする
if (file.name.endsWith(‘.log’) || file.name == ‘tmp_cache’) {
if (file.lastModified() < thresholdTime) {
println "削除対象: ${file.absolutePath}"
file.delete()
}
}
}
return null
}
})
println "=== ✨ クリーンアップが完了しました ==="
} else {
println "ワークスペースが存在しません。"
}
ここがポイント:
`workspace.act()` を使うことで、Jenkinsのマスターからエージェント(ノード)側のファイルシステムへ安全にアクセスし、リモート実行させることができます。分散ビルド環境でもそのまま動く、非常に堅牢な書き方です。
—
3. 負荷に応じて動的にノードを割り当てる(ノード間ジョブ遷移の自動化)
「重いビルドはハイスペックな専用ノードに投げたいけれど、軽いテストは空いている軽量ノードに分散させたい」
そんな時、静的にラベルを固定するのではなく、Groovyを使って現在のノードの稼働状況(負荷)を動的に判断し、適切なノードへジョブをルーティングしてみましょう。
以下のスクリプトは、エージェントの空き状況をチェックし、最適なノードを動的に選択して処理を流すロジックの原型です。
import jenkins.model.
import hudson.model.
// 1. 登録されている全エージェント(ノード)の稼働状況をチェック
def nodes = Jenkins.instance.nodes
def selectedNode = ‘built-in’ // デフォルトはマスター
println “— 📊 現在のノード稼働状況チェック —”
for (node in nodes) {
def computer = node.toComputer()
// オフラインならスキップ
if (computer.isOffline()) continue
// 負荷指標(ビジーなエグゼキュータの割合など)を取得
int numExecutors = computer.getNumExecutors()
int freeExecutors = computer.countIdle()
println “ノード名: ${node.name} / 空きエグゼキュータ: ${freeExecutors} / 総数: ${numExecutors}”
// 例:空きエグゼキュータが最も多く、かつ特定のプレフィックスを持つノードを動的選択
if (freeExecutors > 0 && node.name.startsWith(‘worker-heavy-‘)) {
selectedNode = node.name
break // 最適なノードが見つかったので抜ける
}
}
println “👉 今回割り当てられた最適ノード: ${selectedNode}”
// Pipeline(Declarative)のagentディレクティブ動的指定風に利用するスニペット
return selectedNode
これをJenkinsfile(パイプラインスクリプト)の中に組み込むことで、「今のサーバーの混雑具合に応じて、仕事を割り振る場所を自動で変える賢いパイプライン」が完成します。
—
現場で役立つ!Groovyを安全に使いこなすための心得
最後に、プロダクション環境(本番のJenkins)でGroovyを扱う際の、先輩からの大切なアドバイスをいくつか。
1. サンドボックスを味方につける
Jenkinsにはセキュリティ上の理由から、管理者権限なしでは危険なAPIを叩けない仕組み(Script Security)があります。最初は「承認済み(Approved)」になるコードを意識し、安全なAPIの組み合わせを心がけましょう。
2. まずは検証環境(Staging)で試す
本番のJenkinsサーバーでいきなり複雑なGroovyスクリプトを動かすのは、爆弾処理のようなものです。DockerなどでローカルにJenkinsを立てて、まずはそこで挙動を確かめる習慣をつけてください。
—
まとめ
今回は、JenkinsのGroovyスクリプトを活用した「ワークスペースの自動クリーンアップ」と「動的なノード割り当て」について解説しました。
標準機能の枠を超えてJenkinsをカスタマイズできるようになると、CI/CDパイプラインは単なる「自動化ツール」から、「チームの開発スピードを爆発的に上げる最強のインフラ」へと生まれ変わります。
最初は難しく感じるかもしれませんが、一行ずつコードの意味を理解していけば、必ずあなたの強力な武器になります。
毎日の面倒な運用作業をコードでスマートに自動化し、もっとクリエイティブな開発に時間を使いましょう!応援しています!