Jenkinsビルド失敗のトラブルシューティング:包括的ガイド
この包括的ガイドでは、Jenkinsビルド失敗のトラブルシューティングに役立つ専門家の戦略を提供し、迅速な診断と解決を実現します。コンソールログを体系的に分析して根本原因を特定し、SCM認証、環境設定(PATHやツールバージョン)、依存関係キャッシュ、ビルドエージェントのリソース制約に関連する一般的な落とし穴に対処する方法を学びます。開発者が堅牢で信頼性の高いCI/CDパイプラインを維持するための実践的な手順とコマンドライン例も含まれています。
Jenkinsビルド失敗のトラブルシューティング:包括的ガイド
CI/CDにおいてビルド失敗は普通のことです。コストがかかるのは赤いステータスそのものではなく、皆が推測に時間を費やすことです。Jenkinsはコードエラー、認証情報の欠落、エージェントの問題、依存関係の停止、プラグインの問題などを指し示している可能性があります。これらを迅速に切り分けることが仕事です。
最初の実際のエラー、エージェント名、コミットSHA、そして最後に成功したビルド以降に変更された点から始めましょう。これら4つの事実で、通常は多くのノイズを防げます。
最初のステップ:コンソール出力の分析
Jenkinsビルド失敗のトラブルシューティングにおいて最も重要なツールは、コンソール出力です。このログには、実行されたすべてのコマンド、すべての出力ストリーム、そして重要なエラーメッセージを含む、完全な実行履歴が含まれています。
根本原因の特定
最終的な失敗ステータスではなく、最初の実際のエラーメッセージを探すために上にスクロールすることが重要です。エラーは連鎖することがよくあります。単一の環境設定ミスが、後続の数十のエラーやスタックトレースにつながる可能性があります。ERROR、FATAL、EXCEPTION、または特定のビルドツールエラー(例:MavenのBUILD FAILURE、npmのELIFECYCLE)などのキーワードを探してください。
ヒント: コンソール出力が過度に大きい場合は、ブラウザの検索機能を使用するか、ログを正規表現検索をサポートするテキストエディタにコピーして、エラーマーカーにすばやくジャンプしてください。
ビルド失敗の一般的なカテゴリと解決策
ビルド失敗は通常、5つの主要なカテゴリに分類されます。これらのカテゴリを体系的に調査することで、徹底的な診断が可能になります。
1. ソースコード管理(SCM)の問題
初期チェックアウトフェーズで発生する失敗は、通常、接続性、認証、またはパス設定に関連しています。
| 原因 | 診断/解決策 |
|---|---|
| 認証失敗 | Jenkins(またはエージェント)がリポジトリをクローンするために必要な認証情報(SSHキー、個人アクセストークン、ユーザー名/パスワード)を欠いています。解決策: パイプラインで使用されている認証情報IDが、Jenkinsに保存されている有効で期限切れでない認証情報と一致し、Jenkinsエージェントがそれを使用するためのアクセス権を持っていることを確認してください。 |
| 不正なブランチ/タグ | 指定されたブランチまたはタグが存在しないか、設定が古い参照を指しています。解決策: パイプライン設定またはcheckoutステップのブランチ名を再確認してください。Gitの権限がその特定の参照の読み取りを許可していることを確認してください。 |
| シャロークローンの問題 | リポジトリがシャロークローン(depth: 1)用に設定されている場合、ビルドプロセスが後でダウンロードされなかった履歴コミットやタグにアクセスしようとすると失敗する可能性があります。解決策: 深さの制約を削除するか、履歴アクセスが必要な場合は深さを増やしてください。 |
2. 環境とパスの設定ミス
失敗の最も頻繁な原因の1つは、ローカル開発環境とリモートJenkinsエージェント環境の間の不一致です。エージェントにツールやパス定義が欠けている可能性があります。
不足しているツールとパスの診断
環境変数のダンプ: パイプラインに簡単なステップを追加して、エージェントが使用する環境変数を出力します。これにより、
PATHが正しく設定され、システム変数が定義されていることが確認できます。stage('環境チェック') { steps { sh 'printenv' // または特定のツールチェック sh 'java -version' sh 'mvn -v' } }ツールインストールの確認: ビルドを実行するJenkinsエージェントに、必要なツール(Java Development Kit、Node.js、Python、Mavenなど)がインストールされていることを確認してください。Jenkinsがツールインストールを管理している場合は、Jenkinsの管理 > グローバルツール設定でツール設定を確認してください。
シェルの違い: 失敗が複雑なシェルスクリプトを含む場合は、異なるエージェント間で使用されるシェル(例:
/bin/bashvs./bin/sh)の互換性を確認してください。
3. 依存関係とビルドツールの失敗
これらの失敗は、ビルドツール(例:npm、pip、Maven、Gradle)が実行されたものの、依存関係を解決したりコードをコンパイルしたりできない場合に発生します。
ネットワークとリポジトリアクセス
- ファイアウォールによるブロック: 企業ファイアウォールやセキュリティグループの制限により、Jenkinsエージェントが外部の依存関係リポジトリ(例:Maven Central、Docker Hub、PyPI)に到達できない場合があります。解決策: エージェントマシンから
curlまたはwgetを使用してリポジトリURLに手動で接続をテストしてください。 - プロキシ設定: 外部アクセスにプロキシが必要な場合は、プロキシ設定(
HTTP_PROXY、HTTPS_PROXY)がJenkinsエージェントの環境変数に正しく定義されていることを確認してください。
破損したキャッシュとローカルアーティファクト
ビルドツールによって維持されるローカルキャッシュ(Mavenの~/.m2/repositoryやNodeの~/.npmなど)が破損し、検証の失敗につながることがあります。
- 実行可能な解決策: エージェント上のキャッシュディレクトリを一時的にクリアまたは名前変更し、ビルドを再実行してください。Mavenの場合は、
-Uフラグを付けて実行し、依存関係の更新を強制することもできます。
4. ワークスペースとリソースの制約
Jenkinsビルドには、特にディスク容量とファイルシステムの権限に関して、適切なリソースが必要です。
ディスク容量と権限
- デバイスに空き領域がありません: Jenkinsエージェントのワークスペースドライブがいっぱいの場合、ビルドプロセス(特に大規模なアーティファクトを生成したりDockerビルドを実行したりするもの)は失敗します。解決策: 保持ポリシーまたは自動化されたワークスペースクリーンアップスクリプトを実装してください。エージェントのディスク使用量をプロアクティブに監視してください。
- 権限が拒否されました: Jenkins実行ユーザーが、特定のディレクトリ、一時ファイル、または出力パスに対する読み取り/書き込み権限を欠いている可能性があります。解決策:
jenkinsユーザー(またはエージェントプロセスを実行するユーザー)が、ワークスペース(/var/lib/jenkins/workspace/)およびビルドがアクセスする外部ディレクトリに対して必要な権限を持っていることを確認してください。
古いワークスペース
以前の失敗したビルドからの残存ファイル(例:古いコンパイル済みアーティファクト、ロックファイル)が新しいビルドに干渉することがあります。ワークスペースを手動で削除した後にビルドが成功し始めた場合、古いデータが原因である可能性が高いです。
ベストプラクティス: パイプラインの開始時または終了時に
cleanWs()ステップを使用するか、チェックアウト前にワークスペースをワイプするようにジョブを設定してください。pipeline { agent any stages { stage('クリーンアップ') { steps { cleanWs() } } // ... 残りのパイプライン } }
5. プラグインとJenkinsシステムの問題
環境問題ほど一般的ではありませんが、システムレベルの問題はビルドを広範囲に停止させる可能性があります。
- プラグインの競合/非推奨: 最近更新された、または新しくインストールされたプラグインが、既存のパイプラインステップやJenkinsコア機能と競合する可能性があります。解決策: Jenkinsシステムログ(Jenkinsの管理 > システムログ)でプラグイン関連の例外を確認してください。問題のあるプラグインバージョンをロールバックしてみてください。
- パイプライン構文エラー(Groovy): 宣言的パイプラインまたはスクリプト化パイプラインを使用している場合、構文エラー、括弧の不一致、または許可されていないメソッド(Groovyサンドボックスが有効な場合)は、実行を即座に失敗させます。解決策: 組み込みのパイプライン構文ジェネレーターと、失敗したジョブのリプレイ機能を使用して、小さな変更をすばやくテストしてください。
高度なデバッグ手法
永続的または複雑な失敗には、より深い調査が必要です。
分離と再現
Jenkinsの外部で、ビルドエージェントマシン上で同じユーザーと環境変数を使用して、正確な失敗シーケンスを再現してみてください。手動でプロセスが失敗した場合、問題はコードまたはエージェントのセットアップにあり、Jenkins自体にはありません。
デバッグフラグの使用
多くのビルドツールは、実行ロジックに関する追加の洞察を提供する詳細モードまたはデバッグモードを提供しています。
| ツール | デバッグフラグ/コマンド |
|---|---|
| シェルスクリプト | シェルスクリプトの先頭にset -xを追加して、コマンドを実行前に出力します。 |
| Maven | mvn clean install -X(詳細なデバッグ用)またはmvn clean install -e(スタックトレース用)を使用します。 |
| Gradle | ./gradlew build --debugまたは./gradlew build --stacktraceを使用します。 |
リモートシェルアクセス
ポリシーで許可されている場合は、Jenkinsエージェントマシンに直接SSHセッションを確立してください。これにより、ファイルの権限を検査したり、リソース使用量をリアルタイムで確認したり(df -h、top)、Jenkinsユーザーとまったく同じようにコマンドを実行したりできます。
実際に役立つ予防策
Jenkinsの失敗のトラブルシューティングには、コンソール出力から始めて、SCM、環境、依存関係、リソースのチェックを体系的に進めるアプローチが必要です。ほとんどの失敗は、環境のドリフトまたは認証の問題に起因します。
将来の失敗を最小限に抑えるために、次のベストプラクティスを採用してください。
- コンテナ(Docker)の使用: Dockerコンテナ内でビルドを実行して、すべてのジョブに一貫性のある分離された環境を保証し、ほとんどの環境パスやツールインストールの問題を排除します。
- 明示的な環境定義: すべての必要な環境変数(例:
JAVA_HOME)をJenkinsジョブまたはパイプラインスクリプト内で明示的に定義します。 - 堅牢なクリーンアップの実装: チェックアウト前にワークスペースをワイプするか、ビルド後にクリーンアップして、古いデータの競合を防ぎます。
最初の10分間でのビルド失敗トリアージ
最初の10分間で、トラブルシューティングが冷静に進むか、ランダムな再実行に変わるかが決まります。まず、失敗したビルド番号、エージェント名、コミットSHA、最初の実際のエラー行の4つの事実を収集します。変更を加える前に、これらをインシデントノートまたはチケットに記録します。
次に、同じコミットが他の場所で成功したかどうかを確認します。同じコミットが別のブランチやエージェントで成功した場合、問題はおそらく環境、認証情報、タイミング、またはインフラストラクチャにあります。同じコミットがどこでも失敗する場合、コード、依存関係ロックファイル、またはパイプライン定義が原因である可能性が高いです。1つのエージェントだけが失敗する場合は、理由がわかるまでそのエージェントを隔離します。疑わしいエージェントにさらにジョブを割り当てると、ノイズの多い失敗が発生します。
失敗が既知の不安定な外部依存関係のように見える場合は、1回再実行します。証拠を収集せずに5回再実行しないでください。再実行は、明確な失敗を幸運な成功に置き換えることで、有用なパターンを消去する可能性があります。
チェックアウトの失敗には独自の対応が必要
プロジェクトコマンドが実行される前にビルドが失敗した場合は、ソース管理に焦点を当ててください。一般的な兆候としては、Could not read from remote repository、Authentication failed、Repository not found、Host key verification failed、Couldn't find any revision to buildなどがあります。
SSHベースのGitチェックアウトの場合は、ラップトップではなくエージェントからテストします。
ssh -T [email protected]
git ls-remote [email protected]:org/repo.git
可能であれば、同じJenkinsユーザーを使用してください。ターミナルで管理者に有効な認証情報が、Jenkinsがジョブに使用する認証情報であるとは限りません。HTTPSチェックアウトの場合、期限切れの個人アクセストークンと変更されたリポジトリ権限が一般的です。マルチブランチパイプラインの場合、ブランチインデックスとビルドチェックアウトで異なる認証情報が使用される可能性があることに注意してください。
Jenkinsがブランチを見つけられない場合は、ブランチがまだ存在し、refspecに含まれていることを確認してください。プルリクエストジョブは、プロバイダーによって異なるマージ参照または変更参照を使用する場合があります。
ビルドツールの失敗は通常、Jenkinsの失敗ではない
Maven、Gradle、npm、pip、Go、Docker、またはその他のツールが実行を開始すると、Jenkinsは主に出力と終了ステータスを収集するだけです。ツール自体のエラーを読んでください。Mavenの依存関係解決エラーは、Javaコンパイルエラーとは異なる方法で解決されます。npmのロックファイルの不一致は、Nodeバイナリの欠落とは異なる方法で解決されます。
依存関係の失敗については、エージェントがレジストリに到達できるかどうかを確認してください。
curl -I https://repo.maven.apache.org/maven2/
curl -I https://registry.npmjs.org/
企業ネットワークでは、修正はプロキシ設定または内部アーティファクトミラーへのアクセスである可能性があります。1つの依存関係だけが失敗する場合は、それが削除、移動、ポリシーによってブロックされたか、不正なチェックサムで公開されたかを確認してください。
コンパイルの失敗については、ローカルとCIのツールバージョンを比較してください。Java 21でローカルにビルドされるプロジェクトが、まだJava 17を使用しているエージェントで失敗する可能性があります。Nodeプロジェクトは、package.jsonのpackageManagerを通じてコミットされた正確なパッケージマネージャーバージョンに依存する場合があります。パイプラインの早い段階でバージョンを出力して、将来の失敗を読みやすくします。
ワークスペースの問題は見えにくい
古いファイルは奇妙な失敗を引き起こします。古いブランチから生成されたファイルがワークスペースに残り、後のビルドに影響を与える可能性があります。テストレポートが以前の実行から取得される可能性があります。Docker Composeプロジェクトはコンテナを残す可能性があります。一時ファイルがディスクを埋める可能性があります。
ワークスペースをワイプした後に失敗が消えた場合は、そこで止まらないでください。ジョブが常にクリーンな状態で開始するべきか、特定のクリーンアップステップが欠けているかを判断してください。モノレポや大規模プロジェクトの場合、毎回完全にワイプするのはコストがかかりすぎるかもしれませんが、対象を絞ったクリーンアップは依然として必要です。
便利なチェック:
pwd
ls -la
df -h .
find . -maxdepth 2 -type f -name '*.log' -size +50M
複数のジョブがカスタムワークスペースを共有している場合は、停止して再検討してください。共有ワークスペースは、ジョブ間の汚染の一般的な原因です。共有が意図的で保護されていない限り、個別のワークスペースを使用してください。
リソースの失敗にはJenkins外部の証拠がある
明確なアプリケーションエラーなしでビルドが停止した場合は、エージェントホストを調査してください。Jenkinsはプロセスが終了したか、チャネルが閉じたことだけを示す場合があります。オペレーティングシステムが実際の原因を示す場合があります。
メモリ不足による強制終了を確認します。
dmesg -T | grep -i -E 'out of memory|killed process'
ディスクとinodeの枯渇を確認します。
df -h
df -i
エージェントプロセスが再起動したかどうかを確認します。
journalctl -u jenkins-agent --since '1 hour ago'
コンテナ化されたエージェントは別のレイヤーを追加します。Kubernetesはメモリ、エフェメラルストレージ、またはノードプレッシャーに対してポッドを退去させる場合があります。その場合、kubectl describe podは通常、Jenkinsコンソールよりも多くの情報を提供します。
次回の失敗を診断しやすくする
優れたパイプラインは、原因の近くで明確に失敗します。長いビルドの前にバージョンチェックを追加します。統合テストの前にヘルスチェックを追加します。外部サービスには明示的なタイムアウトを使用します。人々が実際に必要とするログをアーカイブしますが、シークレットや巨大な無関係なファイルをダンプすることは避けてください。
最初の近くにある小さな診断ステージは時間を節約できます。
stage('ビルドコンテキスト') {
steps {
sh '''
hostname
whoami
pwd
git rev-parse HEAD
java -version || true
node --version || true
df -h .
'''
}
}
短く保ってください。目標はすべてのビルドをシステム監査に変えることではありません。目標は、次の失敗を推測なしで理解できるように十分な手がかりを残すことです。