これはドリコム Advent Calendar 2020 の9日目です。
8日目は 本間寿々香 さんによる「AdventCalendarかきおろしイラスト」です。学びを得ました。
こんにちは。DRIP エンジニアの広井淳貴です。
DRIP は Drecom Invention Project の略称で、ドリコムが発明を産み続けるためのプロジェクトです。
その中でわたしは「AROW」というプロジェクトで活動しています。AROW では3Dリアルマップの研究開発を行っていて、没入感のある新しいゲーム体験の実現を目指すために現在開発中です。
今回は、CEDEC2020 で講演されたセッション 「『ラブライブ!スクールアイドルフェスティバル ALL STARS』を支えるビルドパイプライン 〜より安定したサービス提供を目指して〜」で知った Jenkins Configuration as Code について、実際に試してみてとてもいいと感じたので記事を書いてみます。

記事の内容

  • 概要
  • 既存の Jenkins のバックアップ
    • master 本体の設定のバックアップ
    • インストールしているプラグインの一覧のバックアップ
    • 各ジョブ設定のバックアップ
  • バックアップからの引っ越し
    • master 本体の設定のバックアップからのリストア準備
    • インストールしているプラグインの一覧のバックアップからのリストア準備
    • 各ジョブ設定のバックアップからのリストア準備
    • Jenkins の起動
  • 再現リポジトリの紹介
  • まとめ

概要

Jenkins Configuration as Code とは Jenkins 公式が提供している Jenkins 設定の管理の仕組みです。設定/環境をコード化することで、バックアップ/リストア/管理がかんたんにできるようになります。 この記事では既存の Jenkins について以下の3点をバックアップします。
  • master 本体の設定を Jenkins Configuration as Code でバックアップする
  • インストールしているプラグインのリストを実行可能な groovy スクリプトにしてバックアップする
  • 各ジョブの設定をバックアップする
各ジョブの実行履歴はバックアップしません。 バックアップしたものを Jenkins 起動時にリストアすることで引っ越しを実現します。

既存の Jenkins のバックアップ

master 本体の設定のバックアップ

ログインや各種プラグインの設定を含む Jenkins の全体の設定をバックアップします。 Jenkins Configuration as Code のプラグインで設定を Yaml ファイルとしてバックアップできます。

1.Jenkins の管理画面でプラグイン Configuration as Code をインストールする。
jenkins の管理画面でプラグイン Configuration as Code をインストールする。
2.管理画面に Configuration as Code が追加されているのでクリックする。
3.「Download Configuration」でダウンロードする。
これで jenkins.yaml が保存されます。

インストールしているプラグインの一覧のバックアップ

インストールしているプラグインはスクリプトを使って一覧にして、実行可能な groovy スクリプトにすることでバックアップします。

1.Jenkins の管理画面でスクリプトコンソールを開く。
2.以下のスクリプトを実行する。

Jenkins.instance.pluginManager.plugins.each {
  p-> println ("${p.getShortName()}")
}

3.インストールしているプラグインの一覧が出力されるので以下の groovy スクリプトの plugins 部分に合うように編集して保存する。この groovy スクリプトは plugins に指定されたプラグインをインストールするスクリプトです。

import jenkins.model.*

def instance  = Jenkins.getInstance()
def plugins = [
  "ssh-agent",
  "ssh-slaves",
  "git",
  "ssh-credentials",
  "plain-credentials",
  "git-client",
  "configuration-as-code",
  // 一部抜粋
]

pm = instance.getPluginManager()
uc = instance.getUpdateCenter()

uc.updateAllSites()

def enablePlugin(pluginName) {
  if (! pm.getPlugin(pluginName)) {
    deployment = uc.getPlugin(pluginName).deploy(true)
    deployment.get()
  }

  def plugin = pm.getPlugin(pluginName)
  if (! plugin.isEnabled()) {
    plugin.enable()
  }

  plugin.getDependencies().each {
    enablePlugin(it.shortName)
  }
}

plugins.each {
  def plugin = pm.getPlugin(it)
  enablePlugin(it)
}

各ジョブ設定のバックアップ

各ジョブはスクリプトを使って xml 形式の設定ファイルにすることでバックアップします。 1.jenkins の管理画面でスクリプトコンソールを開く。
2.以下のスクリプトを実行する。これは /var/jenkins_home/backup以下に各ジョブの config.xmlファイルをバックアップしています。

import jenkins.model.*

def instance  = Jenkins.getInstance()
def topLevelItems = instance.getItems()

def backupDirectory = new File("/var/jenkins_home/backup")
backupDirectory.mkdir()

topLevelItems.each { topLevelItem ->
  topLevelItem.getAllJobs().each { job ->
    println configPath = job.getBuildDir().getParent() + "/config.xml"
    println backupPath = backupDirectory.getAbsolutePath() + "/" + job.name + ".xml"
    new File(backupPath).setBytes(new File(configPath).getBytes())
  }
}

バックアップからの引っ越し

「Jenkins 起動時にバックアップからリストア」する方法と「Jenkins 起動後にブラウザから操作してリストア」する方法があります。今回の記事では「Jenkins 起動時にバックアップからリストア」を案内します。せっかく公式サイトで以下のことが書いてあるので操作する箇所は最小限にしたいです。
Configure ALL Jenkins initial setup
Fully working Jenkins controller with:
no hands on keyboard
– no click on UI https://www.jenkins.io/projects/jcasc/

Jenkins 起動前にそれぞれ以下の準備を行うと、起動時にリストアされます。

master 本体の設定のバックアップからのリストア準備

環境変数 CASC_JENKINS_CONFIGjenkins.yaml へのパスがあれば起動時にリストアされます。
保存しておいた jenkins.yamljenkins_home 以下の任意の場所に置き、環境変数 CASC_JENKINS_CONFIGを設定します。

インストールしているプラグインの一覧のバックアップからのリストア準備

jenkins_homeinit.groovy.d ディレクトリ以下に配置されたスクリプトは Jenkins 起動時に辞書順に実行されます。
jenkins_homeinit.groovy.d ディレクトリ以下に「インストールしているプラグインの一覧のバックアップ」の項目で作成した groovy スクリプトを配置します。
注意: plugins の依存によってインストール順番の関連のエラーが起こります。”configuration-as-code” を最後にしないと成功しないということが起こりました。

各ジョブ設定のバックアップからのリストア準備

jenkins_homeinit.groovy.d ディレクトリ以下に配置されたスクリプトは Jenkins 起動時に辞書順に実行されます。
jenkins_homeinit.groovy.d ディレクトリ以下に /var/jenkins_home/backupにあるバックアップファイルをリストアする groovy スクリプト(https://github.com/junjanjon/jenkins_configuration_as_code_sample/blob/master/init.groovy.d/2_load_jobs.groovy)を配置し、/var/jenkins_home/backup以下に各ジョブのバックアップした xml ファイルを配置します。

Jenkins の起動

準備を終えたら Jenkins を起動します。その際 JAVA_OPTS=-Djenkins.install.runSetupWizard=false を設定しておけばJenkins デフォルトのセットアップウィザードをスキップできます。 プラグインのインストールが含まれるため、通常のJenkins の起動より時間がかかります。
Jenkins が起動したらそれぞれ設定を確認します。ジョブが再現できており、意図通りのプラグインがインストールされていれば引っ越し完了です。

再現リポジトリの紹介

ここまでの設定を Docker 上の Jenkins で再現するリポジトリを作成しました。 Dockerfile をビルドして起動するだけで各設定(master設定、プラグインインストール、ジョブ設定)が反映されている Jenkins が起動できることを確認できます。よければミニマムな例としてご参考ください。

まとめ

Jenkins Configuration as Code 含め Jenkins の設定はかなり強力に再現性が担保できることを確認しました。セッションではこれらの設定について git で管理しコードレビュー可能にまでなっているとありましたが、自分はまだそこまでできていないため今後の課題として取り組んでいこうと考えています。
本記事がどなたかのお役に立てればうれしいです。 10日目は 廣田洋平 さんによる「Raspberry PiとLINE Botを連携してハムスターの環境を監視する」です。
ドリコムでは一緒に働くメンバーを募集しています!募集一覧はコチラを御覧ください!