Vagrant(Ubuntu) + Chef + Berkshelf での環境構築でつまづいた部分の改善


##はじめに
パーフェクトRuby on Rails 8章でのVagrantとChefの環境構築においていろんな部分でつまづいたので改善案を示す.


##1. chefの導入

###エラーの発生
chefを導入する際にgemfileから作成する場合,rubyのバージョンが推奨バージョンではないためにインストール時にエラーを引き起こした.

###対処
以下のようにgemfileを編集し,rubyのバージョンを最新版(2.3.1)に変更してインストールした.
この導入に関してはホストOSのVagratfileがあるディレクトリで行った.

```gemfile:gemfile(ホストOS)
gem 'chef'
gem 'knife-solo'
gem 'berkshelf'
``` 

##2. Berkfileの導入

問題なかったので省略

##3. ChefのレシピをVagrant上のVMに適用する.

###エラーの発生①
Vagrantfileに以下のような記述を行い,プロビジョニングを行った.

```vagrantfile:Vagrantfile
  #省略
  config.vm.provision "chef_solo" do |chef|
    chef.cookbooks_path = "cookbooks"
    chef.add_recipe 'git'
  end
  #省略
```

```bash
$ vagrant reload --provision
```

プロビジョニングを行うと以下の様なエラーが発生した.

```
==> default: [2016-07-05T14:53:07+00:00] INFO: Started chef-zero at chefzero://localhost:8889 with repository at /tmp/vagrant-chef/9a77c1dbb09132c286d613dff86a2c6b, /tmp/vagrant-chef
==> default:   One version per cookbook
==> default: [2016-07-05T14:53:07+00:00] INFO: Forking chef instance to converge...
==> default: Starting Chef Client, version 12.11.18
==> default: [2016-07-05T14:53:07+00:00] INFO: *** Chef 12.11.18 ***
==> default: [2016-07-05T14:53:07+00:00] INFO: Platform: x86_64-linux
==> default: [2016-07-05T14:53:07+00:00] INFO: Chef-client pid: 3170
==> default: [2016-07-05T14:53:09+00:00] INFO: GET /organizations/chef/nodes/
==> default: [2016-07-05T14:53:09+00:00] INFO: #<ChefZero::RestErrorResponse: 404: Object not found: chefzero://localhost:8889/nodes/>
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/rest_base.rb:91:in `rescue in get_data'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/rest_base.rb:83:in `get_data'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/endpoints/rest_object_endpoint.rb:18:in `get'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/rest_base.rb:62:in `call'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/rest_router.rb:24:in `call'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/server.rb:664:in `block in app'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/server.rb:336:in `call'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/server.rb:336:in `handle_socketless_request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/socketless_server_map.rb:87:in `request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/socketless_server_map.rb:33:in `request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http/socketless_chef_zero_client.rb:154:in `request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:305:in `block in send_http_request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:336:in `block in retrying_http_errors'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:334:in `loop'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:334:in `retrying_http_errors'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:299:in `send_http_request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:144:in `request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:111:in `get'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/node.rb:604:in `load'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/node.rb:588:in `find_or_create'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/policy_builder/dynamic.rb:72:in `load_node'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/client.rb:467:in `load_node'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/client.rb:269:in `run'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:286:in `block in fork_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:274:in `fork'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:274:in `fork_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:239:in `block in run_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/local_mode.rb:44:in `with_server_connectivity'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:227:in `run_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/client.rb:456:in `sleep_then_run_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/client.rb:443:in `block in interval_run_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/client.rb:442:in `loop'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/client.rb:442:in `interval_run_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/client.rb:426:in `run_application'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:59:in `run'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/solo.rb:217:in `run'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/bin/chef-solo:25:in `<top (required)>'
==> default: /root/.rbenv/versions/2.2.2/bin/chef-solo:23:in `load'
==> default: /root/.rbenv/versions/2.2.2/bin/chef-solo:23:in `<main>'
==> default: [2016-07-05T14:53:09+00:00] INFO: HTTP Request Returned 404 Not Found: Object not found: chefzero://localhost:8889/nodes/
==> default: [2016-07-05T14:53:09+00:00] INFO: POST /organizations/chef/nodes
==> default: --- POST BODY ---
==> default: {"name":"vagrant-a53e4a25","chef_environment":"_default","json_class":"Chef::Node","automatic":{},"normal":{},"chef_type":"node","default":{},"override":{},"run_list":[]}
==> default: --- END POST BODY ---
==> default: [2016-07-05T14:53:09+00:00] INFO: #<ChefZero::RestErrorResponse: 404: Parent not found: chefzero://localhost:8889/nodes>
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/rest_base.rb:187:in `rescue in create_data'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/rest_base.rb:181:in `create_data'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/endpoints/rest_list_endpoint.rb:31:in `post'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/endpoints/nodes_endpoint.rb:24:in `post'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/rest_base.rb:62:in `call'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/rest_router.rb:24:in `call'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/server.rb:664:in `block in app'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/server.rb:336:in `call'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/server.rb:336:in `handle_socketless_request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/socketless_server_map.rb:87:in `request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-zero-4.7.0/lib/chef_zero/socketless_server_map.rb:33:in `request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http/socketless_chef_zero_client.rb:154:in `request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:305:in `block in send_http_request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:336:in `block in retrying_http_errors'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:334:in `loop'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:334:in `retrying_http_errors'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:299:in `send_http_request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:144:in `request'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/http.rb:127:in `post'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/node.rb:639:in `create'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/node.rb:592:in `rescue in find_or_create'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/node.rb:588:in `find_or_create'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/policy_builder/dynamic.rb:72:in `load_node'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/client.rb:467:in `load_node'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/client.rb:269:in `run'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:286:in `block in fork_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:274:in `fork'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:274:in `fork_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:239:in `block in run_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/local_mode.rb:44:in `with_server_connectivity'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:227:in `run_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/client.rb:456:in `sleep_then_run_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/client.rb:443:in `block in interval_run_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/client.rb:442:in `loop'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/client.rb:442:in `interval_run_chef_client'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/client.rb:426:in `run_application'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application.rb:59:in `run'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/lib/chef/application/solo.rb:217:in `run'
==> default: /root/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/chef-12.11.18/bin/chef-solo:25:in `<top (required)>'
==> default: /root/.rbenv/versions/2.2.2/bin/chef-solo:23:in `load'
==> default: /root/.rbenv/versions/2.2.2/bin/chef-solo:23:in `<main>'
==> default: [2016-07-05T14:53:09+00:00] INFO: HTTP Request Returned 404 Not Found: Parent not found: chefzero://localhost:8889/nodes
==> default: 
==> default: ================================================================================
==> default: Chef encountered an error attempting to load the node data for 
==> default: ================================================================================
==> default: 
==> default: 
==> default: Resource Not Found:
==> default: -------------------
==> default: The server returned a HTTP 404. This usually indicates that your chef_server_url is incorrect.
==> default: 
==> default: 
==> default: 
==> default: Relevant Config Settings:
==> default: -------------------------
==> default: chef_server_url "chefzero://localhost:8889"
==> default: 
==> default: 
==> default: 
==> default: Platform:
==> default: ---------
==> default: x86_64-linux
==> default: 
==> default: 
==> default: 
==> default: Running handlers:
==> default: [2016-07-05T14:53:09+00:00] ERROR: Running exception handlers
==> default: Running handlers complete
==> default: 
==> default: [2016-07-05T14:53:09+00:00] ERROR: Exception handlers complete
==> default: Chef Client failed. 0 resources updated in 01 seconds
==> default: [2016-07-05T14:53:09+00:00] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
==> default: [2016-07-05T14:53:09+00:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
==> default: [2016-07-05T14:53:09+00:00] ERROR: 404 "Not Found"
==> default: [2016-07-05T14:53:09+00:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
Chef never successfully completed! Any errors should be visible in the
output above. Please fix your recipes so that they properly complete.
```

###対処①

エラーに関しては長過ぎるので要約すると

```
#<ChefZero::RestErrorResponse: 404: Object not found: chefzero://localhost:8889/nodes/>
```

404が発生しているためエラーを吐いていた.

これに関してvagrantfileに以下の記述を追加した.

```vagrantfile:vagrantfile
  config.vm.provision "chef_solo" do |chef|
    chef.channel = "stable"
    chef.version = "12.10.40"
    #略
  end
```

これでプロビジョニングを行った.

###エラーの発生②

先ほどの設定でプロビジョニングを実行すると次は以下の様なエラーが発生した.

```error
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

curl -sL https://omnitruck.chef.io/install.sh | sudo bash -s -- -P "chef" -c "stable" -v "12.10.40"

Stdout from the command:

ubuntu 14.04 x86_64
Getting information for chef stable 12.10.40 for ubuntu...
downloading https://omnitruck.chef.io/stable/chef/metadata?v=12.10.40&p=ubuntu&pv=14.04&m=x86_64
  to file /tmp/install.sh.2721/metadata.txt
trying wget...
ERROR 404
Omnitruck artifact does not exist for version 12.10.40 on platform ubuntu

Either this means:
   - We do not support ubuntu
   - We do not have an artifact for 12.10.40

This is often the latter case due to running a prerelease or RC version of chef
or a gem version which was only pushed to rubygems and not omnitruck.

You may be able to set your knife[:bootstrap_version] to the most recent stable
release of Chef to fix this problem (or the most recent stable major version number).

In order to test the version parameter, adventurous users may take the Metadata URL
below and modify the '&v=<number>' parameter until you successfully get a URL that
does not 404 (e.g. via curl or wget).  You should be able to use '&v=11' or '&v=12'
succesfully.

If you cannot fix this problem by setting the bootstrap_version, it probably means
that ubuntu is not supported.

Metadata URL: https://omnitruck.chef.io/stable/chef/metadata?v=12.10.40&p=ubuntu&pv=14.04&m=x86_64


Stderr from the command:

stdin: is not a tty
```


###対処②

このエラーの対処として先ほど記述していたchefのversionをダウングレードした.

```vagrantfile:vagrantfile
  config.vm.provision "chef_solo" do |chef|
    chef.channel = "stable"
    chef.version = "12.10.24"
    #略
  end
```

次にVagrantのバージョンを確かめてみると

```
$ vagrant -v

=> Vagrant 1.8.1
```

だったので最新版(1.8.4)を[ダウンロード](https://www.vagrantup.com/downloads.html)し,最新版に更新した.

これらを踏まえてプロビジョニングするとエラーを吐くことなく導入ができた.

:+1: 

##まとめ

Ruby on Rails 8章の環境導入で躓いた時に確認することは

- Rubyのバージョンを確認する
- chefの環境はvagrantfileのディレクトリに置く.
- chefのバージョンを明記する
- vagrantのバージョンを確認する.

これをちゃんとやれば導入ができる.