動機
Jenkins には Job を slave に流して実行させる機能があります。
slave には 「このスレーブをできるだけ利用する」と「このマシンを特定ジョブ専用にする」という Mode が存在しています。
Job には、「実行するノードを制限」という項目があり、ここで特定の slave または slave にタグをつけておいてそのタグを持つ slave のうちいずれかで実行するということができます。
Job を何回か実行してみるとたとえ同じタグに複数の slave があったとしても同じマシンで実行されていることが気になりました。
雰囲気でJenkins のノードを制限したり、タグを利用していることが多かったので少し調べてみました。
バージョン
Jenkins: 2.235
Job 実行までのフロー
Job には実行するノードを制限 「する」場合と「しない」場合があります。
これはユースケースとして、実行するOS(Windows か Linuxか)であったり、ランタイムの相違(Java8 なのか Java11 なのか)や地理的(やネットワーク的に)な場所でノードを選択できるようにすることに利用されます。
ネットワークというのは、Aとタグのついた slave からはサーバX にアクセスできないが、Bというタグのついた slave からはアクセスできるというようなことが考えられます。
Slave には「このスレーブをできるだけ利用する」モードと「このマシンを特定ジョブ専用にする」モードがあります。
これはユースケースとして、セキュリティ的な理由や、ノードのリソースをいつでも利用可能な状態にしておきたいといったことが考えられます。
slave のスケジューリング
Scheduling strategy
Some agents are faster, while others are slow. Some agents are closer (network wise) to a master, others are far away. So doing a good build distribution is a challenge. Currently, Jenkins employs the following strategy:
- If a project is configured to stick to one computer, that's always honored.
-
Jenkins tries to build a project on the same computer that it was previously built.
-
プロジェクトがあるコンピューター専用に設定されている場合は、常にそれを優先します
-
Jenkinsは以前ビルドしたコンピュータと同じコンピュータ上で、プロジェクトをビルドするように試みます
となっています。
まとめ
Job を複数回連続して実行したときに空いている slave あるにも関わらず同じ slave で実行し続けていたのでなんでだろと思っていました。
Jenkins のビルドは、第三世代CIツールで採用されているコンテナ内で実行し終わったら破棄するというものではなく、環境を使い続ける方法です。そのため、意図せず違う slave で実行されることでビルドに失敗するということを防ぐために、一度成功した環境で再び実行する戦略をとっているのかと考えられます。
そのため、Job が均等に分散されずに一見賢く見えなかったのだと思います。
また、Jenkins のスケジューリング周りの設定については、
- ノードには複数のタグを付与することができるので、OSやランタイムでタグをつけておき、実行するJob の設定で実行するノードを制限することで必要なOSやランタイムを指定する
- リソースを特定のjob に空けておきたい場合は、slave の設定をしたうえで実行ノードを指定する
- 特に気にしない場合は、実行ノードの指定はせず、Job の設定も行わない
というようにすればよいことがわかりました。
参考
https://wiki.jenkins.io/display/jenkins/distributed+builds#Distributedbuilds-Schedulingstrategy
https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Computer.java#L909
https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Executor.java#L321