Digital OceanにVagrantとChefを使ってJenkins環境を構築する


## 概要
タイトルそのままのことをします。順序としては、
1. Vagrantをインストール
2. Vagrantのプラグインその他のインストール
3. Chefをインストール
4. Chefの準備
5. Vagrantの設定
という流れになります。

## Vagrantのインストール
まずはローカル環境にVagrantをインストールします。私は[boxen](http://boxen.github.com)を使ってるのでそちらでインストールしました。[公式サイト](http://www.vagrantup.com)からインストールするのが確実だと思われます。

## VagrantのDigital Ocean用プラグイン及びboxのインストール
VagrantからDigital Ocean（以下DO）にアクセスするには、プラグインをインストールする必要があります。私はまたしてもboxenを使ってインストールしましたが、コマンドラインから一発です。

```sh
vagrant plugin install vagrant-digitalocean
```

プラグインをインストールしたら次はboxをインストールします。boxとはVagrant向け環境のフォーマットで、これを使うことで手っ取り早く環境を構築できます。

```sh
vagrant box add digital_ocean https://github.com/smdahlen/vagrant-digitalocean/raw/master/box/digital_ocean.box
```

## Chefのインストール
Chefはgemとして用意されているので、そちらを使うのがいいと思われます。ただし、依存関係で20個近いgemが一度にインストールされるので注意（自分は驚きました）。

```sh
gem i chef
```

[公式サイト](http://www.getchef.com/chef/install/)でインストーラも配布されているようです。

## Chefの準備
まずは

```sh
knife configure
```

でChefの設定をします。いつの間にか使えるようになっている`knife`コマンドはChefと一緒にインストールされたもので、Chef用便利ツールです。ここで色々聞かれますが、全部エンター押すだけでいいです。

Chefについて詳しい説明をするのはこの記事の範囲を超えますが、今回使うのはchef-soloというものです。そして、chef-soloを便利に使うための`knife-solo`というgemがあるのでそれをインストールします。

```sh
gem i knife-solo
```

これで`knife solo`コマンドが使えるようになります。このコマンドでChefレポジトリを作成します。ここでは`chef-repo`という名前にしましょう。

```sh
knife solo init chef-repo
cd chef-repo
```

このレポジトリでVagrantをinitします。もし複数のプロジェクトでChefのcookbookを共有したい場合、

```sh
mkdir -p projects/jenkins && cd projects/jenkins
```

などとして、そこで以下の作業を行うといいでしょう（ただし、私は試していません）。

## Cookbookのインストール
Chefを使ってソフトウェアのインストールを行うには`cookbook`なるものが必要になります。自分で作ることもできるのですが、公開されているものを利用することもできます。幸い、有名なソフトウェアであればすでに公開されている場合が多いようです。ので、それを使います。
**が。**
公開cookbookを利用するのは結構面倒です。方法としては以下の2つがあります。

1. `knife cookbook site install`コマンドを使う
2. `git submodule add`コマンドを使う

`knife cookbook site install`コマンドの利点は、依存関係について考慮する必要がないことです。実際、コマンド1つで10以上のcookbookがインストールされる様は壮観でした。
一方、欠点は **opscodeへのユーザー登録が必要である**というものです。…正直萎えます。さらに、秘密鍵を適切な場所に置く必要もあります。ええ、ここで挫折した場合は、`git submodule`を使う他ありません。私の場合は、まあこれからも使うだろうということでユーザー登録をしましたが。
`git submodule add`コマンドを使う場合、依存関係を手動で入れる必要があります。…ええ、ここで挫折してももう行く場所がありません。頑張りましょう。
私の場合、秘密鍵をコピペして`~/.chef/okuramasafumi.pem`とい名前で保存し、その上で

```sh
knife cookbook site install jenkins
knife cookbook site install git
```

のコマンドでcookbookのインストールは完了しました。

## Vagrantの設定

```sh
vagrant init digital_ocean
```

このコマンドでVagrantfileを作成します。作成されたものは大量の設定サンプルがコメントアウトされた状態になっていますが、大事なのは以下の3点です。

1. config.vm.box = 'digital_ocean'
2. config.vm.provider 'digital_ocean'ブロック
3. config.vm.provision 'chef_solo'ブロック

`config.vm.box`の部分は、initの引数が使われるようですので、上記のコマンドを発行していればすでに設定済みになっていると思われます。
`config.vm.provider 'digital_ocean'`の部分は新規に記述する必要があります。以下にスニペットを載せます。

```ruby:Vagrantfile
 config.vm.provider 'digital_ocean' do |provider|
    provider.client_id = CLIENTID
    provider.api_key = APIKEY
    provider.image = 'Ubuntu 14.04 x64' # Example
    provider.name = 'San Francisco 1' # Example
    provider.slug = 'sfo1' # Example
  end
  ENV['VAGRANT_DEFAULT_PROVIDER'] = 'digital_ocean'
```

注意すべきは、DOのクライアントIDとAPIキーをハードコードしないことです。`Vagrantfile`はSCMにチェックインするので、機密情報を含めるべきでないためです。機密情報を外部化する手っ取り早い方法は、`credentials.rb`のようなファイルに情報を置いておき、それを`load`する方法でしょうか。もちろん、`.gitignore`に追記を忘れず。

```ruby:credentials.rb
CLIENTID = 'your_digital_ocean_client_id'
APIKEY = 'your_digital_ocean_api_key'
```

`config.vm.provision 'chef_solo'`ブロックはすでにコメントアウトされていると思います。コメントアウトを解除し、適宜設定します。手元のファイルでは以下のようになっています。

```ruby:Vagrantfile
 config.vm.provision "chef_solo" do |chef|
    chef.cookbooks_path = "./cookbooks"
    chef.roles_path = "./roles"
    chef.data_bags_path = "./data_bags"
    chef.add_role "ci"
  end
```

`ci`というroleはまだないので、これから作成します。

## Chefのrole作成
`chef-repo`のルートに`roles`というディレクトリがあります。ここに`ci.rb`という名前のファイルを作成します。Chefにおける`role`というのは、文字通りサーバの役割で、このroleを駆使することでDBサーバとアプリケーションサーバでインストールするソフトウェアを変えたりできるようです。今回はJenkinsを使いたいわけですので`ci`としました。

```ruby:ci.rb
name 'ci'

run_list(
  'recipe[jenkins::java]',
  'recipe[jenkins::master]',
  'recipe[git]'
)
```

先ほどインストールしたcookbook内にある`recipe`をここに記述していきます。注意したいのは、JenkinsはJavaに依存しているので、`'recipe[jenkins::java]'`でJavaをインストールする必要があることです。
`'recipe[git]'`はJenkins自体には不要なのですが、Jenkinsからgitレポジトリにアクセスする場合に必要となります。

## Vagrantの起動
長かったですね！いよいよDOのサーバを起動します。

```sh
vagrant up
```

これだけです。すべてがうまくいっていれば、大量のログが流れ、DOのサーバが起動します。何かが間違っていれば…問題を修正しましょう。幸い、エラーログは非常にわかりやすいので問題の所在は明らかになるはずです。

## 確認
DOのサーバのIPアドレスのポート8080（Jenkinsのポート）にブラウザからアクセスします。Jenkinsのホーム画面が見えれば成功です！ただし、Jenkinsの起動には少し時間がかかるので、そこは注意。

## まとめ
長かった(´・ω・｀)
しかもここまでやってJenkins自体は全く設定できていないという。なので、別の記事でJenkinsの設定をまとめるかもしれません。
今回やったことはいかんせん複雑なので、勘違い・間違いが多いと思われます。それらを見つけた方はコメントでお知らせください。


## 参考資料
http://ryan.muller.io/devops/2014/03/26/chef-vagrant-and-digital-ocean.html
http://tsuchikazu.net/chef_solo_start/