Jenkinsエージェントの一般的な接続問題とその解決策のトラブルシューティング

Jenkinsエージェントで「オフライン」や「接続が拒否されました」という問題に直面していませんか?この包括的なガイドでは、一般的な接続問題に対するステップバイステップの解決策を提供します。ネットワーク、ファイアウォール、JNLP、SSH、エージェント設定の問題をトラブルシューティングし、Jenkinsのビルド実行エージェントが常に利用可能で効率的に動作するようにする方法を学びます。迅速な解決のための実用的なヒントとログ分析も含まれています。

Jenkinsエージェントの一般的な接続問題とその解決策のトラブルシューティング

Jenkinsエージェント(ノードとも呼ばれる)は、実際にほとんどのビルド作業が実行される場所です。エージェントがオフラインになると、症状は明らかです。ジョブがキューに滞留し、ラベルが満たされず、チームは決して開始されなかったビルドを再実行し始めます。有用な作業は、どのレイヤーが壊れたのかを特定することです。ネットワーク到達性、SSH、インバウンドリモーティング、Java、認証情報、ディスク、またはコントローラー自体です。

エージェントが到達不能になる理由を理解することは、効果的なトラブルシューティングの第一歩です。これらの問題は、ネットワーク設定の誤り、エージェント設定の誤り、ファイアウォールの制限、またはJenkinsコントローラー自体の問題に起因する可能性があります。これらの領域を体系的にチェックすることで、根本原因を迅速に特定し、解決策を実装できます。

Jenkinsエージェント切断の一般的な原因

いくつかの要因がエージェントのオフラインにつながる可能性があります。特定の症状を特定することが、潜在的な原因を絞り込む鍵となります。

  • エージェントに到達できない: Jenkinsコントローラーがエージェントへの接続を確立できません。
  • 接続が拒否されました: エージェントマシンがコントローラーからの接続試行を積極的に拒否します。
  • エージェントが正常に接続した後にオフラインを報告: エージェントは接続されていたが、その後接続が切断されました。
  • JSchエラー(SSHベースのエージェントの場合): SSH接続に使用されるJava Secure Channelライブラリに関連する特定のエラー。

ネットワークとファイアウォールの問題

ネットワーク接続は、エージェント接続問題の最も頻繁な原因です。Jenkinsコントローラーがエージェントマシンに到達でき、その逆も可能であることを確認することが最も重要です。

ネットワーク到達性の確認

Jenkins固有の設定に入る前に、基本的なネットワーク接続を確認します。

  1. エージェントにpingを実行: Jenkinsコントローラーマシンから、エージェントマシンのIPアドレスまたはホスト名にpingを試みます。
    ping <agent-hostname-or-ip>
    
  2. エージェントポートにtelnet: Jenkinsがエージェントへの接続に使用するポートが開いていてリッスンしているかテストします。JNLPエージェントの場合、これは通常ポート50000です。SSHエージェントの場合、SSHポート(デフォルトは22)です。
    telnet <agent-hostname-or-ip> <agent-port>
    
    接続がタイムアウトするか拒否された場合、ポートをブロックするネットワークまたはファイアウォールの問題が存在する可能性があります。

ファイアウォール設定

Jenkinsコントローラー、エージェントマシン、または中間ネットワークデバイスのいずれかのファイアウォールが、必要なポートをブロックする可能性があります。

  • Jenkinsコントローラーファイアウォール: コントローラーがエージェントのポートへの接続を開始できることを確認します。
  • エージェントマシンファイアウォール: エージェントマシンのファイアウォール(例:ufwfirewalld、Windowsファイアウォール)が、JenkinsコントローラーのIPアドレスからのエージェントポートへの着信接続を許可していることを確認します。
  • ネットワークファイアウォール: ネットワークに内部ファイアウォールがある場合、コントローラーとエージェント間のトラフィックが許可されていることを確認します。

例:エージェントでポート50000を許可する(Linux、ufw使用)

# 特定のIP(Jenkinsコントローラー)からの接続を許可
sudo ufw allow from <jenkins-controller-ip> to any port 50000

# または任意のIPからの接続を許可(安全性は低い)
sudo ufw allow 50000

# ファイアウォールルールをリロード
sudo ufw reload

例:エージェントでポート22を許可する(Linux、firewalld使用)

# 特定の送信元IPからのSSHサービスを永続的に許可
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="<jenkins-controller-ip>" port protocol="tcp" port="22" accept'

# ファイアウォールルールをリロード
sudo firewall-cmd --reload

ヒント: セキュリティを向上させるために、特定のIPアドレスからの接続を常に優先的に許可してください。

Jenkinsエージェント設定の問題

Jenkins内またはエージェント自体の設定ミスは、接続問題の一般的な原因です。

JNLPエージェント設定

Java Network Launch Protocol(JNLP)エージェントは、専用ポートを使用してJenkinsコントローラーと通信します。主な設定には、エージェントの起動方法とコントローラーの利用可能なポートが含まれます。

Jenkins UIでエージェントがオフライン

Jenkins UIでエージェントがオフラインと表示される場合、コントローラーが接続を確立または維持できなかったことを意味します。

  1. エージェントの起動方法を確認: エージェントが正しく起動するように設定されていることを確認します。一般的な方法は次のとおりです。
    • エージェントをマスターに接続して起動: エージェント側からの手動開始が必要です。
    • SSH経由でエージェントを起動: SSH認証情報とホスト設定を使用して設定します。
    • 組み込みノードプロパティを使用してエージェントを起動: 特定のシナリオ向け。
  2. JNLPポートの可用性を確認: Jenkinsコントローラーは、設定されたJNLPポート(デフォルト50000)でリッスンする必要があります。Jenkinsの管理 -> システム -> 詳細設定 -> ファイル -> JNLPエージェントのTCPポート に移動し、設定されていてアクセス可能であることを確認します。

JNLPエージェント起動時の「接続が拒否されました」

これは多くの場合、JenkinsコントローラーのJNLPポート(デフォルト50000)がエージェントマシンから開いていないかアクセスできないことを意味します。コントローラーのファイアウォールルールを確認し、ポートが正しく設定されていることを確認します。

ヒント: Jenkinsコントローラーを再起動すると、一時的なJNLPポートの問題が解決することがあります。

SSHエージェント設定

SSHを使用してエージェントに接続する場合、いくつかの要因が問題を引き起こす可能性があります。

  1. SSH認証情報の誤り: JenkinsでSSH接続用に設定されたユーザー名、パスワード、または秘密鍵を確認します。秘密鍵が正しくフォーマット(例:PEM形式)され、正しい権限を持っていることを確認します。
  2. エージェントでSSHサーバーが実行されていない: エージェントマシンでSSHデーモン(sshd)が実行されていることを確認します。
    # エージェントマシン上で
    sudo systemctl status sshd
    # または
    sudo service ssh status
    
    実行されていない場合は、起動します。
    sudo systemctl start sshd
    sudo systemctl enable sshd
    
  3. SSHポートの不一致: Jenkinsで設定されたポートが、SSHサーバーがリッスンしているポート(デフォルト22)と一致していることを確認します。
  4. エージェントのホスト名/IP解決: Jenkinsコントローラーがエージェントのホスト名またはIPアドレスを解決できる必要があります。
  5. SSH鍵の権限: エージェントマシン上で、Jenkinsが接続するユーザーの~/.ssh/authorized_keysファイルが正しい権限(通常600)を持っている必要があります。

例:SSH接続を手動でテストする

Jenkinsコントローラーマシンから、Jenkinsで設定されたものと同じ認証情報とポートを使用して、エージェントにSSH接続を試みます。

ssh -p <ssh-port> <jenkins-user>@<agent-hostname-or-ip>

この手動SSHコマンドが失敗した場合、問題はJenkinsのSSH設定の外部、つまりエージェントのネットワーク、ファイアウォール、またはSSHサーバー設定にある可能性があります。

エージェントの作業ディレクトリの権限

Jenkinsがエージェントのファイルシステムで動作するには、特定の権限が必要です。Jenkinsがエージェントへの接続に使用するユーザー(またはエージェントプロセスを実行するユーザー)には、エージェントの設定された作業ディレクトリへの書き込み権限が必要です。

  • 所有者と権限を確認: エージェント上で、Jenkinsホームディレクトリとそのサブディレクトリの所有権と権限を確認します。
    ls -ld /path/to/jenkins/agent/home
    ls -l /path/to/jenkins/agent/home
    
  • 権限を付与(必要な場合): Jenkinsが接続するユーザーに読み取りおよび書き込みアクセス権があることを確認します。chownchmodは慎重に使用してください。

Jenkinsコントローラーの問題

場合によっては、問題がエージェントではなくJenkinsコントローラー自体にある可能性があります。

コントローラーの過負荷

Jenkinsコントローラーが高負荷(多くのジョブ実行中、高いCPU/メモリ使用率)の場合、エージェント接続の管理に問題が生じる可能性があります。コントローラーのリソース使用率を監視します。

JNLPポートの競合

JNLPポート(デフォルト50000)がJenkinsコントローラー上の別のプロセスですでに使用されている場合、エージェントは接続に失敗します。

  • ポート使用状況を確認: コントローラーマシンで、netstatまたはssを使用して、どのプロセスがポートを使用しているかを確認します。
    sudo netstat -tulnp | grep 50000
    # または
    sudo ss -tulnp | grep 50000
    
    別のプロセスが使用している場合、Jenkinsまたは他のアプリケーションのいずれかを再設定して、異なるポートを使用する必要があります。

高度なトラブルシューティングとログ

標準的なチェックで問題が明らかにならない場合は、より詳細な調査が必要です。

Jenkinsコントローラーログ

エージェント接続に関連するエラーについて、Jenkinsコントローラーログを確認します。これらのログは、特定のエラーメッセージを提供する可能性があります。

  • 場所: 通常は$JENKINS_HOME/jenkins.logにあります。または、Jenkinsの管理 -> システムログからアクセスできます。
  • 探すもの: エージェントのホスト名、IPアドレス、接続試行、JSch例外、または「接続が拒否されました」エラーに言及しているメッセージ。

エージェントログ

エージェントが実行中であるがオフラインを報告している場合は、そのログでエラーを確認します。

  • JNLPエージェント: エージェントプロセス自体が、コンソールまたは指定されたログファイルにログを出力する場合があります。
  • SSHエージェント: ログはエージェントマシンの$JENKINS_HOME/agent.logにあるか、SSHレベルで接続が失敗した場合はsshdに関連している可能性があります。

デバッグログの有効化

非常に永続的な問題の場合、関連するJenkinsコンポーネントのデバッグログを一時的に有効にすると、より詳細な情報が得られます。

  • JNLP/エージェント通信: Javaシステムプロパティを調整するか、Jenkinsのログ設定(Jenkinsの管理 -> システムログ -> ログレコーダー)を使用して、hudson.slavesまたは関連パッケージの詳細レベルを上げる必要がある場合があります。

繰り返しの停止を防ぐ実用的な習慣

Jenkinsエージェントの接続トラブルシューティングには、基本的なネットワークチェックから始めてJenkins固有の設定に進む体系的なアプローチが必要です。

  • ネットワークを確認: 常にpingとtelnet/ncから始めて、基本的なネットワーク到達性とポートアクセスを確認します。
  • ファイアウォールを確認: コントローラーとエージェントの両方のファイアウォール、およびネットワークファイアウォールが、必要なポートでのトラフィックを許可していることを確認します。
  • 認証情報を検証: SSH鍵、ユーザー名、パスワードを再確認します。
  • エージェントサービスを確認: SSHエージェントの場合、sshdが実行されていてアクセス可能であることを確認します。
  • Jenkinsログを監視: コントローラーログは、接続障害を理解するための主要な情報源です。
  • 特定のIPを使用: 可能な場合は、ファイアウォールとJenkinsを設定して、広い範囲や0.0.0.0ではなく特定のIPアドレスを使用します。

これらの手順に従うことで、最も一般的なJenkinsエージェントの接続問題を効果的に診断および解決し、CI/CDパイプラインをスムーズに実行し続けることができます。

推測せずにオフラインメッセージを読む

「オフライン」という言葉は、それだけでトラブルシューティングするには広すぎます。Jenkinsの設定を変更する前に、エージェントページを開き、Jenkinsが示す正確な理由を読んでください。「接続が拒否されました」、「権限が拒否されました」、「ホスト鍵の検証に失敗しました」、「JNLPエージェントが拒否されました」、「チャネルが閉じられました」の間には大きな違いがあります。これらはすべてオフラインノードで終わりますが、異なるレイヤーを指しています。

私は通常、症状を平易な言葉で書き留めます。「コントローラーがTCPポート22に到達できない」、「SSHログインは機能するがJavaを起動できない」、「インバウンドエージェントは起動するがコントローラーにコールバックできない」、または「エージェントが接続し、ビルド中に切断する」。その一文で調査の焦点が定まります。

エージェントが一度も接続したことがない場合は、設定、DNS、ファイアウォール、認証情報、または起動コマンドを疑ってください。数か月間接続していて今日から失敗し始めた場合は、最近の変更を確認します。ローテーションされたSSH鍵、Jenkinsのアップグレード、プラグインの更新、新しいファイアウォールルール、期限切れの証明書、エージェントイメージの再構築、クラウドネットワークの変更などです。タイムラインは、エラーテキストよりも有用な場合がよくあります。

SSHエージェント:ログイン問題と起動問題を分離する

SSHベースのエージェントの場合、Jenkinsが使用するのと同じパスをテストします。コントローラーホストから、Jenkinsで設定されたユーザーとして接続します。

ssh -vvv jenkins-agent-user@agent-hostname

詳細出力は、認証前、認証中、ログイン後のいずれで失敗が発生するかを示します。SSHがサーバーに到達しない場合、Jenkinsはそれを修正できません。ルーティング、セキュリティグループ、ネットワークACL、ホストファイアウォール、SSHデーモンを確認してください。SSHがサーバーに到達するが鍵を拒否する場合は、Jenkinsの認証情報、ユーザーのauthorized_keys、ファイルの権限、アカウントがロックされているかどうかを確認します。

手動SSHログインは機能するがJenkinsがまだ失敗する場合は、リモートルートディレクトリとJavaの起動を確認します。Jenkinsはリモーティングファイル用に書き込み可能なディレクトリを必要とし、エージェントユーザーはそこにファイルを作成する権限が必要です。よくある間違いは、リモートルートをrootが所有するパスや別のプロセスによってクリーンアップされるパスに指定することです。

エージェントでこれらのチェックを実行します。

whoami
pwd
java -version
test -w /path/to/jenkins-agent && echo writable
df -h /path/to/jenkins-agent

Javaのバージョンは重要です。最新のJenkinsコントローラーは、エージェントに互換性のあるJavaバージョンを必要とするためです。正確な要件はJenkinsのリリースによって異なるため、古いエージェントイメージがまだ有効であると想定するのではなく、お使いのバージョンのJenkinsドキュメントを確認してください。

インバウンドエージェント:コールバックパスが通常の落とし穴

インバウンドエージェントは、コントローラーがエージェントへのSSHを開始できない場合(NATの背後や制限されたネットワーク内のエージェントなど)によく使用されます。エージェントプロセスはJenkinsの外部で起動し、コントローラーに接続して戻ります。つまり、ネットワークパスが逆になります。エージェントはJenkinsのURLを解決して到達する必要があります。

エージェントホストで、設定されたとおりにJenkins URLをテストします。

curl -I https://jenkins.example.com/

Jenkinsがリバースプロキシの背後にある場合は、Jenkinsの管理 > システムのパブリックURLが正しいことを確認します。間違ったJenkins URLは、生成されたエージェントコマンドがエージェントが解決できない内部ホスト名を指す原因となる可能性があります。インバウンドエージェントにWebSocketモードが有効になっている場合は、プロキシがWebSocketアップグレードヘッダーをサポートしていることを確認します。代わりにTCPインバウンドエージェントポートを使用する場合は、固定ポートが設定され、エージェントネットワークから到達可能であることを確認します。

TLSの問題はJenkinsの問題のように見えることがあります。エージェントが最小限のコンテナイメージで実行されている場合、内部CA証明書がない可能性があります。curlは通常、それをすぐに明らかにします。証明書の検証を無効にするのではなく、CA証明書をエージェントイメージにインストールします。

ビルド中に切断するエージェント

正常に接続し、ビルド中に切断するエージェントは、通常、基本的な接続問題ではありません。リソースのプレッシャーとプロセスのライフサイクルを確認します。

オペレーティングシステムがエージェントプロセスを強制終了したかどうかを確認します。

dmesg -T | grep -i -E 'killed process|out of memory'
journalctl -u jenkins-agent --since '2 hours ago'

また、ディスク容量も確認します。Jenkinsのリモーティング、チェックアウト、テストレポート、アーカイブされたアーティファクトはすべて容量を必要とします。ワークスペースボリュームがいっぱいになると、リモーティングプロセスが一時ファイルやログを書き込めなくなるため、エージェントが信頼性を欠くように見える可能性があります。

切断が大量のコンソール出力、アーティファクトのアーカイブ、またはテストレポートの公開中に発生する場合は、ネットワークの安定性とコントローラーの負荷を確認します。エージェントチャネルはライブ接続です。コントローラーの長時間のガベージコレクションポーズ、過負荷のプロキシ、アイドル接続のタイムアウト、パケット損失はすべて接続を閉じる可能性があります。ロードバランサーや企業プロキシを通過するエージェントの場合は、アイドルタイムアウト設定とキープアライブ動作を確認します。

DNSとホスト鍵の問題

DNSの変更は見逃しがちです。Jenkinsはbuild-agent-01に接続するかもしれませんが、手動テストではIPアドレスを使用します。コントローラーからホスト名をテストします。

getent hosts build-agent-01
nc -vz build-agent-01 22

ホスト名が間違ったアドレスに解決される場合は、DNSまたはエージェント設定を修正します。明確な所有権プロセスがない限り、長期的な/etc/hostsパッチは避けてください。それらは目に見えないインフラストラクチャになるためです。

SSHエージェントの場合、ホスト鍵の検証は、Jenkinsが予期しないマシンに接続するのを防ぎます。エージェントが再構築された場合、そのホスト鍵が変更されている可能性があります。盲目的に検証を無効にしないでください。再構築を確認し、コントローラーユーザーのknown_hostsから古い鍵を削除し、設定されたJenkins戦略を通じて新しい鍵を受け入れます。

本番エージェントのための復旧チェックリスト

複数のエージェントが同時にオフラインになった場合、共通の原因を見つける前に、それらを1つずつ修正することは避けてください。次の質問を自問してください。

  1. Jenkinsコントローラーが再起動またはアップグレードされましたか?
  2. 共有認証情報がローテーションされましたか?
  3. ベースエージェントイメージが変更されましたか?
  4. ファイアウォール、プロキシ、VPN、またはDNSの変更が展開されましたか?
  5. 失敗したすべてのエージェントが同じサブネット、クラウドアカウント、Kubernetes名前空間、またはアベイラビリティゾーンにありますか?

1つのエージェントだけが失敗した場合は、そのホストを調査します。グループ全体が一緒に失敗した場合は、共通の依存関係を調査します。これにより、大規模なJenkinsフリートで多くの時間を節約できます。