Jenkinsで長年運用しているジョブが、あるとき突然再現できなくなる。そんな経験に心当たりがあるなら、この記事が役に立つかもしれません。GitHub ActionsやGitLab CIといったSaaS型のCI/CDが普及した今でも、Jenkinsは多くの企業で現役です。ただし運用歴が長いプロジェクトほど、GUIベースの設定が積み重なり、身動きが取れなくなっている状態が見受けられます。
対象読者は、Jenkinsの管理画面から「新規ジョブ作成」→「フリースタイル・プロジェクト」を選んでビルド設定を組んできたチームです。すでにJenkinsfileを使っているなら、この記事は既存パイプラインの点検用として読んでください。
何が起きるか
Freestyleジョブ(Web UIのフォーム上でシェルスクリプトやビルド手順をポチポチ設定していく従来型のジョブ形式)には、静かに蓄積するリスクがあります。
設定変更がGit管理の外で行われるため、「いつ・誰が・何を変えたか」が追えません。ビルドが急に失敗するようになっても、直前の設定変更を差分で確認する手段がないのです。
さらに深刻なのは、Jenkinsサーバー自体が壊れたときです。バックアップから復元できても、数十個のFreestyleジョブに設定された複雑な条件分岐やビルドステップは、手作業で再現するしかありません。プルリクエストでレビューすることもできないため、ビルド設定の変更がそのまま本番影響につながるケースもあります。
もう一つ見落とされがちな問題が、Controller(旧称Master、Jenkinsの中枢でWeb UIやジョブのオーケストレーションを担うノード)上で重いビルドを直接実行してしまう設定です。CPUやメモリを食いつぶし、CI/CD基盤全体が落ちるという事象につながります。
なぜ起きるか
原因を分解すると、大きく3つの層があります。
1つ目はアーキテクチャの理解不足です。JenkinsはController(設定管理・UI・ジョブ調整を担う)と、Agent(旧称Slave、実際のビルドを実行する別マシンやDockerコンテナ)に役割が分かれています。Agentには複数のExecutor(1つのビルドステップを実行するスロット、スレッドのようなもの)があり、Executor数だけ並列実行が可能です。この構造を知らずにジョブを組むと、Controllerに負荷を寄せてしまいます。
2つ目は、Jenkinsの歴史的経緯です。Freestyleプロジェクトは古くからある設定方式で、学習コストが低く始めやすい反面、コードとして扱われません。Pipeline機能が導入される以前のプロジェクトほど、Freestyleのまま塩漬けになりやすい傾向があります。
3つ目は、Pipeline機能自体にもScripted(Groovyベースのスクリプトで柔軟だが複雑になりやすい記法)とDeclarative(構造化された定型のスキーマで可読性が高い記法)の2種類があり、どちらを選ぶべきか整理されないまま導入されているケースです。95%のユースケースではDeclarative Pipelineが推奨される選択肢とされていますが、古い記事やテンプレートを参考にするとScripted寄りの複雑な記法が混ざり込みやすくなります。
自分のプロジェクトが該当するか確認する
実際に確認してみましょう。
まず、Jenkinsの管理画面トップから対象ジョブを開き、左メニューに「設定」しかなく「Pipeline」の文字が見当たらない場合、それはFreestyleジョブです。ジョブ一覧画面でもアイコンの形でFreestyleかPipelineかが区別できます。
次に、対象リポジトリのルートに Jenkinsfile が存在するかを確認してください。存在しない、あるいは存在してもごく一部のジョブにしかないなら、大半がFreestyleで運用されている可能性が高いです。
# リポジトリ内にJenkinsfileがあるか確認
find . -iname "Jenkinsfile*"
# Jenkins CLIでジョブの設定XMLを取得し、Freestyleか確認
java -jar jenkins-cli.jar -s http://<jenkins-url> get-job <job-name>取得したXMLの先頭タグが <project> ならFreestyleジョブ、<flow-definition> ならPipelineジョブです。この違いだけでも、移行対象の棚卸しに使えます。
あわせて、Controller上で直接ビルドが走っていないかも確認しておきましょう。管理画面の「Manage Jenkins」→「Nodes」を開き、Controllerノードの「Executors」の数と、実際にそこで実行されているジョブの agent 設定を照合します。Jenkinsfileがある場合は agent ディレクティブが any や特定ラベル、あるいは docker { image ... } になっているかをチェックしてください。指定がなくController固定になっているなら要注意です。
対策の手順
Freestyleジョブが見つかった場合の移行手順です。
1. 既存のビルド手順を洗い出す - Freestyleジョブの「ビルド」欄にあるシェルスクリプトやビルドステップを、実行順にメモします。
2. リポジトリにJenkinsfileを作成する - 以下は最小構成の例です。
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building the project'
sh 'npm install'
}
}
stage('Test') {
steps {
sh 'npm test'
}
}
}
}3. agentディレクティブを明示する - Controllerへの負荷を避けるため、agent any ではなくラベル指定やDockerコンテナ実行に寄せます。Node.jsアプリなら次のように書けます。
pipeline {
agent {
docker { image 'node:18-alpine' }
}
environment {
APP_ENV = 'staging'
}
stages {
stage('Install Dependencies') {
steps {
sh 'npm ci'
}
}
}
}4. 新規ジョブとして並走させる - いきなりFreestyleジョブを削除せず、「Pipeline」タイプで新規ジョブを作成し、同じトリガー条件で並走させます。数回のビルドで結果が一致することを確認してから切り替えます。
5. プルリクエストでレビューする運用に切り替える - Jenkinsfileはリポジトリ内のファイルなので、通常のコードレビューフローに乗せられます。ビルド設定の変更履歴もGitのコミットログで追えるようになります。
6. AIコーディングツールでの移行支援 - Freestyleジョブの設定XMLをClaudeやChatGPTなどに読み込ませ、「このFreestyle設定をDeclarative Pipelineに変換して」と依頼する運用も現実的です。ただしXML内のシェルスクリプト部分は変換漏れが起きやすいため、生成結果と元のビルドログを必ず突き合わせてください。
導入前に確認すること
Freestyleジョブからの移行は、一度に全社的にやり切る必要はありません。
- まず
find . -iname "Jenkinsfile*"やget-jobコマンドで、現状Freestyleがどれだけ残っているか棚卸しする - Controller上で直接ビルドを実行しているジョブがないか、Nodes画面とagentディレクティブを照合する
- 影響範囲の小さいジョブから1つ選び、Declarative Pipelineへの並走移行を試す
- 移行後はJenkinsfileをプルリクエストでレビューする運用に切り替える
小さく始めて、レビュー可能なパイプラインが1つでも増えれば、それだけ「壊れたら誰も直せない」設定が減っていきます。