🦁

Jenkins Kubernetes Plugin

7 min read

はじめに

今回は Jenkins の Kubernetes Plugin のお話です。
Jenkins には Kubernetes Plugin があります。これはジョブ実行時に Kuberentes 上に専用のコンテナが起動し、起動したコンテナでジョブを実行することができます(Jenkins の Slave 的な)。
こちらを今回は試行しようと思います。お試しということで今回は実行ジョブで Ansible を実行できるようにしていきます。

環境情報

  • Kubernetes:v1.20.6
    • StorageClass として Ceph を導入しています

https://qiita.com/t_ume/items/4ac37f746bf07146d5f9
  • helm:v3.5.4
  • Jenkins:2.289.1
  • Kubernetes Plugin:1.29.4

Deploy Jenkins

まずは Jenkins をデプロイします。今回は helm を使ってデプロイします。

※参考(helm)

https://helm.sh/ja/docs/intro/install/
# リリースを指定して、git clone
$ git clone https://github.com/jenkinsci/helm-charts.git -b jenkins-3.4.0 --depth 1

# ディレクトリを移動して、values.yamlを書き換える
$ cd helm-charts/charts/jenkins/
$ vim values.yaml

values.yaml を書き換えることで、デプロイするコンテナの設定を変更することができます。今回は以下の箇所を書き換えています。

  • イメージを最新に変更
  • 外部からのアクセス用に Service を NodePortに変更
  • StorageClass を Ceph に変更
@@ -19,7 +19,7 @@ controller:
   # Used for label app.kubernetes.io/component
   componentName: "jenkins-controller"
   image: "jenkins/jenkins"
-  tag: "2.289.1-jdk11"
+  tag: "2.299"
   imagePullPolicy: "Always"
   imagePullSecretName:
   # Optionally configure lifetime for controller-container
@@ -111,7 +111,7 @@ controller:
   targetPort: 8080
   # For minikube, set this to NodePort, elsewhere use LoadBalancer
   # Use ClusterIP if your setup includes ingress controller
-  serviceType: ClusterIP
+  serviceType: NodePort
   # Jenkins controller service annotations
   serviceAnnotations: {}
   # Jenkins controller custom labels
@@ -717,7 +717,7 @@ persistence:
   ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
   ##   GKE, AWS & OpenStack)
   ##
-  storageClass:
+  storageClass: rook-ceph-block
   annotations: {}
   accessMode: "ReadWriteOnce"
   size: "8Gi"

早速デプロイします。

$ helm install jenkins .
NAME: jenkins
LAST DEPLOYED: Tue Jun 22 19:03:14 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
・・・

# 接続先のノードのIPを出力
$ kubectl get nodes -n default \
-o jsonpath="{.items[0].status.addresses[0].address}"
192.168.10.61

# NodePort で開放した Jenkins アクセス用のポートを出力
$ kubectl get services jenkins -n default \
-o jsonpath="{.spec.ports[0].nodePort}"
32036

# 管理者(admin)のログイン用パスワードを出力
$ kubectl exec -n default -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/chart-admin-password && echo
xxxxx

取得した情報を元に Jenkins のログイン画面にアクセスし、admin/取得したパスワードでログインします。
※今回のURLは、http://192.168.10.61:32036/



Jenkins 準備

ログイン後、「Jenkinsの管理」から設定を行おうと思ったのですが、プラグインの依存関係で色々とエラーが・・・

赤い部分だけ気になったので、以下のプラグインをアップデートしました。
※何度かに分けてアップデートを行い、都度「ダウンロードして再起動後にインストール」でアップデートを行いました

1 回目

  • JavaScript GUI Lib: ACE Editor bundle plugin
  • Pipeline: Supporting APIs
  • JUnit

2 回目

  • Pipeline: Model API
  • Pipeline: Job
  • Credentials Binding

3 回目

  • Docker Pipeline
  • Lockable Resources
  • Pipeline: Declarative
  • Pipeline: Shared Groovy Libraries

Kubernetes Plugin 準備

helm でデプロイした Jenkins には既に Kubernetes Plugin がインストールされているので、早速各種設定を行っていきます。

セキュリティ設定

通信設定用に以下を確認します(デフォルトではチェックが入っているはずですが念のため)。

  1. 「Jenkinsの管理」⇒「グローバルセキュリティの設定」
  2. 「Agents」⇒「Agent protocols...」をクリック
  3. 「Inbound TCP Agent ...」にチェックを入れて「保存」

認証情報登録

ジョブを実行するコンテナは Kubernetes にデプロイします。このため Kuberenetes アクセスで必要な認証情報を登録します。

登録出来る認証情報は以下のとおりです。

https://plugins.jenkins.io/kubernetes/

・Username/password
・Secret File (kubeconfig file)
・Secret text (Token-based authentication) (OpenShift)
・Google Service Account from private key (GKE authentication)
・X.509 Client Certificate

今回は kubeconfig ファイルを用意して、アップロードします。
kubeconfig ファイルは、kubectl を実行している端末の.kube/config に格納されています。必要に応じて編集してアップロードしましょう。

  1. 「Jenkinsの管理」⇒「Manage Credential」
  2. 「Store」の「Jenkins」をクリック⇒「グローバルドメイン」
  3. 左メニューから「認証情報の追加」をクリック
  4. 以下で認証情報を登録
  • 種類:Secret file
  • スコープ:グローバル
  • File:上記で作成したファイル
  • ID:kubernetes-user(任意)

ジョブ実行ノードの登録

最後にジョブ実行ノードの登録を行います。
「Jenkinsの管理」⇒「ノードの管理」⇒「Configure Clouds」の順で画面遷移すると「Kubernetes」で1つ登録されているので、以下の様に編集します。

Kubernetes(Kubernetes Cloud details...)

  • Name:kubernetes(任意)
  • Kubernetes URL:空白
    • 今回はCredentialに記載があったので空白
    • ユーザ、パスワードなど Credential に接続先の記載がない場合は入力
  • Kubernetes Namespace:default(任意)
  • Credentials:上記で登録した認証情報を選択
  • Jenkins URL:http://jenkins:8080
    • Jenkins デプロイの際に、8080 ポートで登録されている Service 名を記載
  • Jenkins tunnel:jenkins-agent:50000
    • Jenkins デプロイの際に、50000 ポートで登録されている Service 名を記載
  • Pod Label
    • Key:jenkins/jenkins-jenkins-agent
    • Value:true

変更したら、忘れずに「保存」を押しましょう。

ジョブの登録・実行

ジョブを実行する準備はできたので、早速ジョブを登録していきましょう。
今回はパイプラインで登録していきます。

  1. 「新規ジョブ作成」⇒「パイプライン」を選択⇒ジョブ名を入力して「OK」をクリック
  2. パイプラインのテキストエリアに以下を入力して、「保存」をクリック
pipeline.yaml
podTemplate(containers: [
    containerTemplate(name: 'bbox', image: 'busybox', command: 'sleep', args: '99d'),
    containerTemplate(name: 'ansible', image: 'ansible/ansible-runner:1.4.6', command: 'sleep', args: '99d')
  ]) {
    node(POD_LABEL) {
        stage('Echo Test') {
            container('bbox') {
                sh 'echo "hello busy box"'
            }
        }
        stage('Let\'s Ansible') {
            container('ansible') {
                sh '''
		    ansible --version
                    ansible -i 192.168.10.61, 192.168.10.61 -m ping
                '''
            }
        }
    }
}

「ビルド実行」から早速実行してみましょう。

画像にもある通り、既に何度か失敗しています・・・

#1 Let's の「'」をエスケープし忘れる
#2 ansible の PATTERN の入力し忘れ
#3 ansible は実行できたけど失敗(接続用の鍵情報がない)

#3 の Output

・・・

・・・

今回はまず試行できるところまでということで、ここまでとします。
認証情報や git の資材の配置、成果物の連携については追々勉強していこうと思います。

まとめ

今回は Jenkins の Kubernetes Plugin を使ってコンテナ上でジョブ実行を行いました。ジョブの実行する環境をコンテナで用意できるので、各種ツールや言語、クラウドを利用している場合など、環境を柔軟に活用できるのではと思っています。

ちなみに今回のつまづきポイントは Plugin の設定で行った「Jenkins URL」と「Jenkins tunnel」でした。色々な値を試しては、起動するコンテナのログを逐次参照してテストを行っていました・・・


※参考

https://plugins.jenkins.io/kubernetes/

https://www.jenkins.io/doc/pipeline/steps/kubernetes/

https://github.com/jenkinsci/kubernetes-plugin/tree/master/examples

https://github.com/jenkinsci/kubernetes-plugin/tree/master/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/pipeline/samples