Jenkins X で実現するサーバーレスJenkins


Serverless Jenkins with Jenkins X

Jenkins は2004年にHudsonとして誕生しました。それ以来、Jenkinsはソフトウェア開発とデリバリーに関わる私たちにとってなじみの名前になり、今では継続的インテグレーションに加え継続的デリバリーツールのリーダーでもあります。現時点で2050万以上のJenkinsジョブがあり、20万近くのJenkinsサーバーが稼働しています。これは驚異的な数字です!

この成長の間に、クラウドやコンテナ化など、技術的にも大幅な進歩がありました。そのため、Jenkinsはより優れた実装となる必要があり、私たちはそれを活用することに目を向けなければなりません。今日では、ほとんどの企業がクラウドを推進しているため、私たちはJenkinsを時代とともに進化させ、Jenkins自身のクラウドネイティブへの旅を進めることを望んでいます。Jenkinsは成長を続け、多くの人々から信頼を得ている自動化、信頼性、開発者エクスペリエンスを提供し続ける必要があります。

Jenkinsは多大な成功を収めましたが、それには痛みも伴います。私たちが耳にしている大きな問題は次のとおりです。

  • Jenkinsサーバーが単一障害点(SPOF)になっている。特に、メンテナンスによるダウンタイム中にgitのwebhookイベントが失われる。
  • Jenkinsサーバーでは、頻繁にディスク領域が不足するため、機能を維持し続けるためには、スクリプトや手動によるクリーンアップが必要である。
  • プラグインのバージョンが合っていないと、アップグレード時に競合が発生する可能性がある。
  • マルチブランチプラグインのスキャンによるGitHubのレート制限。
  • 大きなメモリを必要とする大規模なJava仮想マシン(JVM)は、使用量ベースの価格設定では、ビルドが実行されていない場合にも不必要なコストが発生する。

そこで、もし以下が可能となるとどうなるでしょうか。

  • ビルドが要求され、パイプラインを実行するときにだけJenkinsを動かし、クラウドの使用料金を減らす。
  • ビルドが完了したら、一時的なパイプラインエンジンを破棄し、ファイルシステムがいっぱいになってディスクスペースが不足するのを防ぐ。
  • 継続的インテグレーションで、新しいプラグインやプラグインのアップグレードを検証する。
  • 高可用性とスケーラブルなWebhookハンドラを提供して、SPOFに対処する。
  • GitHub APIのスキャンを避け、レ​​ート制限のリスクを軽減する。
  • すべてのジョブ設定をGitに保存し、障害リカバリー戦略を可能にする。

Jenkins Xプロジェクトは、今年初めにKubernetes対応の自動CI + CDとして発表されました。Jenkins Xは、プルリクエストのプレビュー環境や、複数の環境にまたがる(テスト – >ステージング – >プロダクション)自動GitOpsプロモーション機能を備えています。また、Jenkins XはCRD( カスタムリソース定義 : custom resource definitions)を使用してKubernetesを拡張し、Jenkinsサーバーおよびパイプラインをオーケストレーションします。

そしてこのたび、Jenkins XおよびJenkinsプロジェクトは、Serverless Jenkinsを発表しました。Jenkins XはServerless Jenkins、静的なJenkinsマスター、またはチームごとのKnativeビルドのいずれもオーケストレーションできるようになりました。つまり、オープンソースのJenkinsのクラウ​​ドで、完全なKnativeビルドがサポートされるようになったのです!

Serverless Jenkinsは、広く支持されている革新的なオープンソースプロジェクトを使用して、上記のような静的Jenkinsマスターの問題を解決します。今やKubernetesはデファクトのクラウド実装ですので、今回は、Serverless Jenkinsを支えている、他のそれほど知られていないプロジェクト、つまりProwとKnative Buildに焦点を当てたいと思います。

このブログの一番下には、Serverless Jenkinsが実際に動いているところをデモしている未編集のYouTube録画へのリンクがあります。

Prowとは

ProwはKubernetesエコシステムから生まれました。もともとは、Googleの優秀なエンジニアたちが、KubernetesのGitHub リポジトリでJenkinsを使うのに苦労していたときに開発したものです。Kubernetesは、GitHubで最大かつ最も成功したオープンソースプロジェクトの1 つですが、ProwはKubernetesの140のリポジトリすべてに加えて、IstioJetstackでも使用されています。Prowは個別の機能を担当する多数のマイクロサービスから構成されたイベントベースのソリューションであり、クラウドネイティブアーキテクチャにとって理想的な、緩やかに結合されたアーキテクチャを提供します。Prowは、マスターへのマージ(プルリクエストビルドの実行前と実行後の両方の)を強力に制御することを可能にし、また、ChatOpsを使用してビルドシステムとやり取りします。

Prowにはスケーラブルで可用性の高いwebhookイベントハンドラーが含まれており、Gitイベントに基づいてProwJob CRDをKubernetesに書き込むことで、他のマイクロサービス(ProwJobイベントを監視するKubernetesコントローラー)がイベントに応じて継続的インテグレーションまたはデリバリーパイプラインを実行することを可能にします。Gitイベントは、新しいPRや課題、コメント、マージ、プッシュなどによってトリガーされるので、さまざまなトリガーに対処することができます。

また、ラベルに基づくルールセットを指定し、プルリクエストを自動的にマージする機能もあります。

Prowコンポーネントのリストと説明については、 このリポジトリを参照してください。

Prowはジョブの設定をGitに保存します。つまり、障害からのリカバリーを行わなければならない場合も、すべてのCIジョブとCDジョブを復元できます。サンプルとして、Jenkins XプロジェクトはいつものようにProwを真っ先に自プロジェクトで採用し、検証してからユーザーに公開しました。ここで、CI/CDが必要なすべてのリポジトリ用に作成されたJenkins Xプロジェクト自体のProw設定を参照できます。

Knative Build

Knative Buildも、やはりクラウドネイティブソリューションです。Knative Buildは、KubernetesをCRDで拡張し、ユーザーがソースからアプリケーションをビルドする方法を提供します。Knative Buildの画期的な特長の1つは、同じKubernetesポッドで順次実行される複数の単純なステップを組み立てて、異なるコンテナを使用して各ステップ間で状態を共有できることです。このアプローチでは、 Kubernetesのinitコンテナを使用します。

ビルドテンプレートは、ビルド実行用に作成されるKubernetesポッドのタイプを記述する方法です。ビルドテンプレートを使用すると、ビルドを実行するDockerイメージ、ビルド時に必要な環境変数やサービスアカウント、シークレット、マウントする必要があるボリューム​​を指定できます。ビルドテンプレートはKubernetes CRDであり、Jenkins Xのリリースごとに自動的にアップグレードされます。アプリケーションの作成またはインポート時にJenkins Xによって生成されるProw設定は、ビルドテンプレートを参照します。Jenkins Xプロジェクトでの例は、 ビルドテンプレートを指すprow 設定です。

Serverless Jenkinsとは

これで背景が理解できたので、次にServerless Jenkinsとは何かを見てみましょう。Serverlss Jenkinsとは、開発者、チーム、組織がクラウドに移行するのを支援し、単にJenkinsがクラウドに対応できるというだけでなく、クラウドとJenkinsの両方の強みを活用できるようにする、Cloud Native Jenkinsの取り組みの一部です。

詳細

 

KubernetesでJenkins Xを使用すると、ProwとKnativeが自動的にインストールされ、設定されます。jx CLIは必要な設定をすべて生成し、プロジェクトの作成時またはインポート時にGit リポジトリのwebhookエンドポイントを更新します。

すると、マスターへのプルリクエストまたはマージのたびに、Knativeを使用してKubernetesに一時的なJenkinsがスピンアップされ、Gitリビジョンをチェックアウトし、必要な認証情報を設定し、 Jenkinsfileを使用してアプリケーションビルドパイプラインを実行します。ビルドが完了すると、Jenkinsfileランナーポッドは破棄されます。

Jenkins Xのリリースプロセスは、Custom War Packager (CWP)を利用して、必要なビルドツールを含むさまざまな種類のJenkinsサーバーを構築します。言語検出機能により、適切な種類が使用されます。また、ビルド時に必要なJenkinsの設定を追加するために、 Configuration as Codeプラグイン (CasC)を使用します。CWPの特長の1つは、Serverless Jenkinsのビルド時(Serverless Jenkinsが起動するときではなく)にJenkinsプラグインを抽出することです。そのため、Jenkins XベースのJenkinsイメージのコンテナおよびJVMの起動に要する時間は5秒未満です。いっぽう、 JenkinsサーバーをKubernetesで起動する場合は数分かかることもあります。

Jenkins Xのリリースのたびに、monorepoを使用して、これらの言語固有のJenkinsイメージが自動的にビルドおよびリリースされます。

これは、私たちのプラグインがyamlで定義され、Gitに保存されているので、私たちのCI/CDツールの開発にCI/CDを適用できるということも意味します。プラグインをアップグレードしたい場合、プルリクエストを作成すると、それをトリガーとしてCIが開始され、プレビュー用Jenkinsイメージをビルドするので、そこでプラグインの競合がないことを確認するとともに、自動テストとしてモックジョブを実行することもできます(この部分はまだ現実化されてはいませんが)。また、誰もがまったく同じアプローチでカスタムServerless Jenkinsイメージを構築し、同じようにパイプラインで使用することができます。

ここで強調すべきことの1つは、Serverless Jenkinsに切り替えると、ビルドとビルドの間で状態が保存されないことです。つまり、各ジョブのビルド番号は常に1になります。Jenkins Xでは、 PipelineActivity用のCRDを作成するので、次のビルド番号を生成することができます。また、ビルドに関する情報も保存できるので、Jenkinsのシングルショットのビルドが完了した後、パイプラインの以前のビルドを視覚化できます。

Prowがwebhookイベントを受信すると、KubernetesにKnativeビルドリソースが作成されます。次に、ビルドを監視しているKnativeビルドコントローラーは、Kubernetesポッドを作成し、PRまたはリリース ブランチのソース コードをクローンするinitコンテナを自動的に追加します。次に、 Jenkinsfileランナーを利用して、シングルショットのJenkinsを別のステップで起動し、Knativeによってクローンされたソースコードにアクセスし、アプリケーションのJenkinsfileを処理します。

Serverless Jenkins を試してみましょう

最新のJenkins Xには、次のように terraformを使用してGKE上にクラスタを作成したとき、デフォルトでProwが含まれています。

jx create terraform

また、次のように他のcreate clusterコマンドまたはinstallコマンドで機能フラグを使用した場合も同様です。

jx create cluster gke --prow
jx install  -  prow

FAQ

Q. 静的なJenkinsサーバーが実行されていないのであれば、GUIにアクセスするにはどうすればよいですか?

A. Serverless Jenkins用のオープンソースのJenkins GUIはありません。これは非常に重要な点なので、もう少し詳しく説明しましょう。Jenkins XにはJenkins Xの開発者にとって使いやすいIDECLIのツールがあります。ただし、GUIはもうありません。Prowには、Deckと呼ばれるオープンソースのGUIがあり、これはJenkins Xとともにデフォルトでインストールされます。

 

Q.ビルドログはどこにありますか?

A.より良いソリューションはこれから開発されるところですが、今のところ、Jenkinsfileランナーはビルドログを標準出力に出力するので、Stackdriver、CloudWatchなどのKubernetesクラスターの集中ログソリューションを活用することができます。また `jx logs -k`(ビルドの実行中に利用可能)と` jx get build log`(数時間利用可能)も使用できます。

 

Q. `JOB_NAME`のような特定のJenkinsマルチブランチプラグイン環境変数に依存するJenkinsファイルを変更する必要はありますか?

A. いいえ。MBP関連のすべての環境変数が同じ形式で追加されるようにしました。もし私たちが見逃しているものがあれば、どうぞお知らせください。

どうやって既存のJenkinsfileをServerless Jenkins 用に変換するのですか?

Jenkins Xプロジェクト自体も、これまでの静的(常時オンの)Jenkinsサーバーの代わりにServeless Jenkinsを使用するように移行ました。そうです、私たちはJenkinsサーバーを0にスケールダウンし、すべてのGitリポジトリをProwとServerless Jenkinsに移動したのです。JenkinsXサイトのプルリクエストを見ると、実際の動作を確認できます。私たちは宣言スタイルのJenkinsfile (これは新しいプロジェクトをJenkins Xにインポートするときに追加されるものです)を使用していました。したがって、Serverless Jenkinsへの移行は、Jenkinsfileへのわずかな調整だけで済みました。

  1. エージェントタイプを「any」に変更して、パイプラインが一時的なワンショットJenkinsで実行されるようにします。
  2. すべてのJenkinsfileのコンテナブロックを削除します。なぜなら、すべてのステップがワンショットのJenkinsパイプラインエンジンで実行されることになるからです。
  3. そのタグを持つすべてのリリースブランチパイプラインについて(必ずGitタグを作成する必要があります)、 checkout scmgit 'github/foo.git'に変更する必要があります。これは、Jenkinsワークスペースにリポジトリを追加するときにシンボリックリンクが使用されるらしく、cloneされたリポジトリをKnativeおよびJenkinsfileランナーから再利用するのに問題があるためです。この問題はいずれ修正したいと考えています。

上記の変更の例は、ここで参照できます 。prowのChatOps /approveコメントを有効にするには、承認者のGitHub IDを使用する同様のOWNERSファイルも必要です。

既知の制限事項

  • 現在のところはGitHubのみがサポートされています。他のGitプロバイダーのサポートも行われる予定です。
  • Jenkins Xはフォークを使用しますが、これは数週間後に上流のprow リポジトリを使用するように切り替わります
  • Jenkins Xは、デフォルトで宣言型パイプラインJenkinsfilesを作成します。スクリプト型Jenkinsfileおよび共有ライブラリJenkinsfileパイプラインではテストされていません。私たちは、これらが期待通りに機能するかどうかについてのフィードバックを求めています。
  • Kubernetes Plugin PodTemplatesはまだサポートされていません。サポートするべきかについても、結論は出ていません。したがって、複数の異なるcontainer {…}ブロックを持つ既存のJenkinsfileを移行する場合は、上のCWPで作成したシングルショットのJenkinsに各コンテナのビルドツールを追加する必要があります。

今後やるべき作業もまだたくさんあるので、プロジェクトに関わりたいと思われた方は、 Jenkins X Kubernetes slack roomsに顔を出して、課題を手伝ってください。あるいは、まずはJenkins X を試してみて、どんな感じかを教えてください。

まとめ

Jenkins Xは、Prow ChatOpsを使用して静的、サーバーレス、またはKnativeのビルドジョブをオーケストレーションするチームのためのワンストップショップであり、Kubernetesワークロード用の自動化されたCI/CDが付属しています。

その他のリソース

(この記事は、CloudBees社 Blog 「Serverless Jenkins with Jenkins X」2018年11月20日 James Rawlings 投稿の翻訳記事です。)