生産性向上ブログ

継続的な生産性向上を目指すエンジニアのためのブログ

Jenkins 2.0 (2): Jenkins Pipeline

Jenkins 2.0の最新情報について書く記事の第2回目です。今回は、2.0の中心となるPipelineについて書きます。

Pipeline Plugin

Jenkins Pipelineは、Pipeline Pluginを中心とした一連のプラグインからなる、デプロイパイプラインを実現するための仕組みです。デプロイパイプラインは、継続的デリバリーというプラクティスの根幹となる要素で、詳細を知りたい人は『継続的デリバリー』という本を読むのが一番いいと思います。

Jenkins Pipelineでは、ジョブの設定を以下のようなコード(DSL)で記述します。

pipeline {
  agent any

  stages {
    stage('install') {
      steps {
        sh 'npm install'
      }
    }
    stage('test') {
      steps {
        sh 'npm test'
      }
    }
    stage('publish') {
      steps {
        sh 'npm publish'
      }
    }
  }
}

Jenkins公式ではこのようにパイプラインをコードとして表現することを、"Pipeline as Code"と表記しています。ジョブの設定をコード化することによって、様々なメリットを得られます。

Pipeline as Codeのメリット

1.xでのフリースタイル・プロジェクトなどのGUIによるジョブ設定は、取っ付きやすいというメリットもある一方、デメリットも多くありました。

まず、設定項目が多すぎて複雑になりがちです。設定項目はプラグインのインストールによって増えることがあるため、実際に使わない設定も多く表示され、どの項目を設定するべきなのかわかりにくいという問題がありました。

次に、変更内容の管理が困難です。JobConfigHistory Pluginのようなプラグインも存在しますが、XMLで差分が表示されるのは厳しいですし、どのような意図で変更されたかといった情報も管理されません。

一方、Pipeline as Codeでは必要な設定のみがコードとして表現されるため、シンプルな見通しになります。また、ジョブの設定をGitHubなどのソースコード管理システムでバージョン管理できるようになるため、プルリクエストによる変更内容の共有やレビューといったことも行えるようになります。

デプロイパイプラインの管理に、既存のソフトウェア開発のプラクティスを適用できることが、Pipeline as Codeのメリットなのです。

これまでのパイプラインとの違い

1.x時代のJenkinsにも、デプロイパイプラインを実現するための仕組みは存在しました。例えば、Build PIpeline PluginDelivery Pipeline Pluginを使えばデリバリーパイプラインを構築することができます。

これまでの仕組みは、1つのジョブをパイプライン上の1ステージとして、複数のジョブをビルド後のトリガーでつなぎ合わせ、プラグインによってパイプラインとして可視化するというものでした。しかし、この仕組だとパイプラインのフローの設定やステージ間での成果物や環境変数などの受け渡しが大変という問題がありました。例えば、ジョブA→ジョブBの順でビルドを実行するためにはジョブAのビルド後の処理でジョブBのビルドをトリガしないといけないのですが、ジョブBのビルドを実行するために必要なパラメータが変わったときなどにジョブA側の設定も変更しないといけなくなるというように、複数のジョブを横断して設定変更しないといけなくなります。これは、慣れていないと設定変更の影響範囲を把握することが難しいです。既存のジョブの仕組みの上で強引にパイプラインを実現しようとしていたため、複雑かつ柔軟性のない設定となってしまっていたのが1.xのパイプラインでした。

一方、2.0のJenkins Pipelineではすべてのステージを1つのジョブとしてDSLで設定できます。これにより、ステージ間の影響範囲などもわかりやすくなりますし、成果物や環境変数の受け渡しといったこともプログラマブルに行えるので、明確かつ柔軟なパイプラインを設計できるようになります。

また、Jenkins 2.0で追加された新しい特性の恩恵も得られるようになるため、それについても説明していきます。

パイプラインの耐久性

Jenkins Pipelineは、ジョブ実行中にmasterが再起動されても生き残り続けるというこれまでにない耐久性があります。

これまでは、メンテナンスなどの目的のためにmasterを再起動したくても、日中は実行中のビルドがあるためなかなかできませんでした。しかし、Jenkins上のジョブをPipelineだけで構成すれば、実行に長時間かかる大規模なパイプラインが存在しても気兼ねすることなくmasterを再起動することができるようになります。

これにより、Jenkins 2.0では柔軟な運用ができるようになります。

手動オペレーションとの融合

Jenkins Pipelineには、ビルドを途中で一時停止して、人間の入力を待つための仕組みが存在します。

継続的デリバリーの中にヒューマンオペレーションを入れるのは必ずしもよいプラクティスではないですが、現実的には人間の判断を途中で入れたいケースは存在します。例えば、リリースの承認やタイミングを人手でコントロールしたいケースなどがそれにあたります。

steps {
    input 'Ready to go?'
}

上記のような input をパイプラインのコードの中に記述するとそのステップでビルドが一時停止し、"Proceed"か"Abort"の2択の選択肢が表示されます。"Proceed"を選択するとその先のステップにビルドが進み、"Abort"を選択するとビルドが中断されます。

このように、Jenkins 2.0のパイプラインでは、多様なパイプラインを実現するための仕組みが備わっています。

対応プラグイン

既存のプラグインがJenkins Pipelineに対応しているかどうかは、GitHub上で表になっています。

github.com

対応済みのものはチェックが入っており、未対応だけど対応のためのissueが登録されているものはチェックなしでissueへのリンクと共に書かれているようです。

今後、既存のジョブをパイプラインへ移行する場合は、事前に使っているプラグインが対応しているか確認しましょう。

まとめ

  • Jenkins 2.0のパイプラインはDSLの記述により明確かつ柔軟にパイプラインを設計できる
  • Jenkins Pipelineは、2.0で新しく追加された機能の恩恵を得られる
  • Jenkins Pipelineに対応済みのプラグイン一覧が存在する

次回は、PipelineのDSLについてもっと詳細に書く予定です。