GeekFactory

int128.hatenablog.com

GitとJenkinsを使ってChefを運用する

Chefはリポジトリをバージョン管理する仕組みを持っていますが、チームでの協調作業を考えるとバージョン管理システムを使う方が運用しやすいと考えます。本稿では、GitとJenkinsを使ってChefを運用するための1つのパターンを考えます。

以下があることを前提とします。

基本的な考え方

CookbookをGitリポジトリで管理します。開発者がgit pushすると同時にChef ServerのCookbookが更新されるようにします。これにより、GitリポジトリとChef Serverが同期されるようになります。

また、後続ジョブとして各サーバでChef Clientが実行されるようにします。ビルドパイプラインを組むことで、Staging EnvironmentにおけるChef Client、Production EnvironmentにおけるChef Clientをワンクリックで実行することもできます。


ChefリポジトリをGitで管理する

空のChefリポジトリGitHubから取得します。ChefリポジトリにはCookbookだけでなくData Bagsや設定が含まれていますが、本稿ではCookbookのみを対象とします。

git clone git://github.com/opscode/chef-repo.git
git remote rename origin github
git remote add origin git://git.example.com/chef-repo.git
git push origin master

上記のgit.example.comは適当なGitリポジトリです。GitHubでも構いません。まずは、自分のGitリポジトリにpushできたことを確認しましょう。

JenkinsからknifeでCookbookをアップロードする

knifeの準備

Jenkinsの実行ユーザがknifeを実行できるように設定します。

  1. Chef Web UIから新しいクライアントを作成します。
  2. 表示された秘密鍵を /home/jenkins/.chef/client.pem に配置します。
  3. 設定ファイルを /home/jenkins/.chef/knife.rb に配置します。
  4. Jenkinsの実行ユーザで knife node list を実行し、ノード一覧が表示されるか確認します。

設定ファイルはこんな感じで。

# /home/jenkins/.chef/knife.rb
log_level                :info
log_location             STDOUT
node_name                'jenkins'
client_key               '/home/jenkins/.chef/client.pem'
chef_server_url          'http://localhost:4000'

/home/jenkins はJenkinsの実行ユーザ(Jenkins SlaveでもOK)のホームディレクトリです。環境に合わせて読み替えてください。

ジョブの作成

GitリポジトリからCookbookを取得し、Chef Serverにアップロードします。

シェルスクリプトの実行:

/usr/local/rbenv/shims/knife cookbook upload -a -o cookbooks

上記はrbenvを使う例です。knifeのパスは適宜読み替えてください。

JenkinsからChef Clientを実行する

Jenkins Slaveの準備

Chef Clientを実行したいノードでJenkins Slaveをセットアップします。

ジョブの作成

複数ノードで同じコマンドを実行したいので multi-configuration project にします。

シェルスクリプトの実行:

sudo /usr/local/bin/chef-client

作成したジョブを実行してみましょう。各サーバでchef-clientを実行した結果がコンソールログに残っていればOKです。

Git server-side hookでJenkinsジョブを実行する

最後に、GitのHookで上記ジョブが実行されるようにします。GitのHookはリポジトリのhooksフォルダで設定できます。

例えば /home/git/repositories/chef-repo.git/hooks/post-update という感じで。

#!/bin/sh
exec curl -k 'http://www.example.com/jenkins/job/chef-repo/build?token=xxxxxxxx

リモートからJenkinsのジョブを実行するには、Jenkins上で認証トークンを設定しておきます。リモートでは、ジョブ名に認証トークンを付加したURLをcurlコマンドで叩けばOKです。

このパターンのメリット

チームでの開発や運用において、以下のメリットがあると思います。

  • knifeの煩雑なコマンド操作を自動化することで、チームスケーラビリティの向上や作業ミスの軽減を期待できます。
  • Chef Clientの実行結果がコンソールログに残ります。問題があった場合に調査しやすくなります。
  • Chefのプロセスが可視化されることで、チームメンバーがインフラ構成管理に関心を持つことを期待できます。

Webで調べてもこういう話はなかったんですよね。もっといいパターンがある場合はトラックバックをお待ちしています。このエントリは書き始めてから1ヶ月も放置してしまったぜ・・・。