본문

Tech
Kubernetes PodでJenkins Agentを動的に生成する

작성일 2021.03.17

blog_77_main.jpg

JenkinsでCI / CDを構築すると、ビルド用のagentサーバーをMasterに接続し、特定のサーバーでビルド展開を実行するように構成することがよくあります。そうすると、管理対象サーバーが増えます。

Jenkins kubernetes plugin を使用すると、プラグインが kubernetesクラスタにPodとしてagentを生成し、PodのコンテナでJobを実行できるようになります. そして、Jobが終わると消えます。つまり、維持する必要はありません。

クラスタでビルド展開を実行するように設定すると、次のような利点が得られます。

  • 管理対象をクラスタ一つに減らすことができる。
  • コンテナの資源制限(分離)を利用して資源効率的なCI/CDを行うことができる。
  • コンテナイメージを使用して一貫した環境でビルド、デプロイを行うことができる。

では、自分で設定してみましょう。

Kubernetes plugin for Jenkinsのインストール

テストのために、クラスタ内にPodとしてJenkinsサーバーを新規作成しました。JenkinsのPlugin ManagerでKubernetesを検索すると、Kubernetesというプラグインがあり、そのプラグインをインストールします。

%EA%B7%B8%EB%A6%BC2.png

インストールが開始されると、依存プラグインが一緒にインストールされます。

%EA%B7%B8%EB%A6%BC3.png

JenkinsでKubernetesクラスター情報を設定する

これで、jenkinsはpodを生成するためのKubernetesクラスタ情報を設定する必要があります。設定画面は、Jenkins管理 - システム設定 - Cloudの欄にあります。最新バージョンのjenkinsでは別のページに分割されているので、テキストをクリックして設定ページに移動します。Add New Cloudを押してKubernetesをクリックし、Kubernetes Cloud details...を押してクラスタ情報を設定します。

%EA%B7%B8%EB%A6%BC4.png

上記の設定ボックスが表示されますが、ユーザーの環境によって必要な設定が異なります。ここでは、接続するクラスタのkubeconfigファイルをjenkins credentialにsercret fileとしてアップロードし、Kubernetes APIと通信するように設定します。(Jenkins Masterがクラスタ内でPodとして機能している場合は、ServiceAccountを割り当ててKubernetes APIと通信することもできる。)

kubeconfigをJenkins Credentialsに登録するkubeconfigをJenkins Credentialsに登録する
Kubernetes APIと通信が成功すると、Connectedメッセージが表示される。Kubernetes APIと通信が成功すると、Connectedメッセージが表示される。

通常の通信が確認されたら、サンプルPipelineスクリプトを実行するテストjobを作成して、正常かどうかと動作が確認できます。

Sample Maven Build Pipeline スクリプトSample Maven Build Pipeline スクリプト

ビルドを開始すると、新規に作成されたjobの名前が付けられた新しいAgentがビルドリストに登場し、Podを照会すると、指定したネームスペースに新規Podが生成されたことが確認できます。

ビルド実行リストビルド実行リスト
生成されたJenkins Agent Pod生成されたJenkins Agent Pod

kubectlでPodを見ると、サンプルスクリプトで定義されたmavenコンテナ以外の1つがより機能していることがわかります。Jenkinsコンソールの出力を見ると、パイプラインを実行する前にビルドを実行するPodの内容を確認でき、サンプルスクリプトで定義したPodTemplateにjnlpコンテナが自動的に追加されたことが確認できます。 jnlpコンテナにjenkins agentが実行され、jenkins masterと通信する役割を果たすのにプラグインが自動的にPodに追加したものです。

ビルドするPodのコンテナの内容ビルドするPodのコンテナの内容

サンプルPipelineスクリプトで正常に動作することを確認し、全体的な実行プロセスを見たので、PodTemplateを自分で作成してみます。Jenkins agentとして使用するPod Templateを作成する方法は、Global Pod TemplateとPiepelineスクリプトに直接定義する方法の2つがありますが、すでに使用しているjobにPod Templateを適用するには、Global Pod Templateを定義して簡単に設定できます。

Global Pod Templateとして定義

Jenkinsのシステム設定でKubernetesを設定したページには、Pod Template details ...というボタンがあり、ここでPodを簡単に定義できます。

Global Pod TemplateGlobal Pod Template

Podに必要な情報を入力し、使用する画像を指定します。複数のコンテナを設定することもできますが、注意すべき点はjnlpコンテナが追加されるので、なるべくjnlpコンテナを追加してオーバーライドされないようにする必要があります。

その他、Pod設定に入力できるさまざまな設定も以下にあります。

特定のNodeで動作させるには、nodeSelector、env、hostPath volumeなど、Kubernetes Podに必要な既存の情報をほとんど設定できます。特にLabelsのような場合は、pipelineスクリプトで書き込むノードを指定するときに使用されるので、ユニークな名前で指定する必要があります。上記の例では、1つのPodにtest、test2というコンテナがubuntuイメージを有効にしています。

このようにGlobal Pod templateを一度定義しておくと、後でスクリプトからこのtemplateを継承してmergeまたはoverwriteすることもできます。それでは、前に定義したPodを使って簡単なスクリプトを実行するDeclarative pipelineを作ってテストしてみましょう。

blog_77_code_01.webp

Build stageでAgentを生成し、Stageの単純なシェルスクリプトを指定したコンテナで並列に実行させる簡単な例です。Labelsで実行するTemplateを指定し、stageのstepsで実行するコンテナを指定しました。そして、各コンテナでechoを実行した後に終了します。

各コンテナでスクリプトを実行する各コンテナでスクリプトを実行する
並列に実行された結果並列に実行された結果

このように、簡単にGlobal Pod Templateを既存のpipeline scriptに簡単にリンクできます。必要に応じて、1つのPodで複数のコンテナではなく複数のAgentを生成して並列に実行するように設定することもできます。

スクリプトにPod Templateを定義

Pipelineスクリプトに直接Pod Templateを定義するには、Pod yamlの内容を直接書き込むか、プラグインが提供する設定に合わせて作成します。プラグインが提供する設定はリンクで確認できます。これらの設定に合わせて、podTemplateをpipelineスクリプトに直接書いてみましょう。

blog_77_code_02.webp

Global Pod Templateで定義したものをpipeline scriptで作成した内容です。プラグインのpodTemplate設定でPodを定義し、その後パイプラインスクリプトの内容が追加される構造です。

まず、Pod yamlの内容を変数の文字列として定義します。そして、プラグインが提供する設定であるpodTemplateにyaml変数を指定します。yaml を定義する必要なくpodTemplate 設定だけで行うことができますが、プラグインの設定中に必要なものがない場合は yaml で定義するだけです。

もし、podTemplateの設定に必要なものがない場合は、yamlで定義してからyamlと設定をoverrideする方法をご使用ください。

たとえば、上記の例ではPod yamlにtolerationsの内容がありますが、podTemplate設定はtolerations設定をサポートしていません。 そのため、yamlにtolerationsを追加し、スクリプト設定にnodeSelectorを追加しました。

その後、yamlで定義した内容とpodTemplateで設定した内容がoverride(デフォルト)になります。そのため、yamlで特定のtaintを持つnodeにアクセシブルなtolerationsを与えたので、プラグイン設定で定義したnodeSelectorによってそのノードに割り当てが可能になり、このノードでのみPodが生成されます。このように、現在使用している環境やユーザーのニーズに合わせて設定するだけです。

スクリプトで定義した方法で実行した結果スクリプトで定義した方法で実行した結果

実行すると、前に設定したGlobal方式と同じように動作します。

まとめ

dindを使用して並列にコンテナからコンテナイメージをビルドするdindを使用して並列にコンテナからコンテナイメージをビルドする

Kubernetes plugin for jenkinsを使用すると、前述の利点を簡単に入手できます。アプリケーションごとにagentを生成し、並列にjobを実行してビルド時間を短縮する試みを試すことができます。

動的agentとkanikoまたはdind(Docker in Docker)を使用すると、各agentにDockerイメージのビルドを並列に実行させることができます。

Dockerの場合、docker-composeを使用しないと、1つのDockerエンジンで同時にイメージをビルドすることができず、順次進行しますが、docker-composeを使用しなくても各agentでdindまたはkanikoコンテナイメージを使用して並列に実行するように設定できます。

何よりも、Docker イメージを構築するために別々のサーバーやクラウドサービスを追加する必要はありません。

次には、ドッカーでドッカーをビルドできるdind(Docker in Docker)やkanikoについての詳細をご紹介します。

WhaTap Monitoringを体験してみましょう。
難しかったモニタリングと分析が容易に実現できます。