WindowsでもVagrantでChefしたい、rbenvも(11.12.4-1版)
以前、Chefの導入編の記事を書きましたが、4月に、Ubuntu14.04 LTSのまっさらなVagant Boxをつくったので、Chefのレシピを書いておきたいと思います。
ところで。
心を入れ替えます。
導入編から書きなおしてみます。
方針としては、Chefリポジトリは(1)Git+GitHubで管理する、(2)Vagrantプロジェクトの中に入れる(ディレクトリ構成のはなし)。
「Chefって結局なんなの?」という方は『入門Chef Solo - Infrastructure as Code』を読んで下さい。
- ChefとChef-Soloを(ひとまず)区別しましょう(ローカル開発環境=Vagrantで使うのはChef-Soloです)
- 「冪等性(べきとうせい: Idempotence)」「収束(Convergence)」がキーワードですよ
- NodeのことをClientとよんだりする(厳密にはChefのAPIと通信できるすべての端末のこと、したがってknifeもChef Clientのひとつ)
- knife-soloとはChef-Soloを扱うにさいして便利なツールです
こう書いてみると当たり前のことばかりですが、Chefの概念図だけ頭にあると、こんがらがってきます。
ぼくはこの本を読んで、Chefライフがすべてうまく行き始めた気がしてきました。不思議なマジックをもった本です。
筆者の環境:
- Windows 7 SP1 64bit
- Ruby 2.0.0p451
- gem 2.2.2
- Git 1.9.2(http://msysgit.github.io/)(Git\binにパスを通している)
- Vagrant 1.5.4
- VirtualBox 4.3.10
- 環境変数HOMEにC:\Users\hidex7777をセットしている
- GitHubにchef-repoという空のリポジトリを作ってある
VagrantにはUbuntuサーバ14.04のボックスが登録されている:
>vagrant box list Trusty (virtualbox, 0)
Vagrantのプラグインvagrant-omunibusは便利ですがknife solo prepare
で済むので、個人的には必要ないかな―と思っています。本番環境でVagrant使うかどうかわかんないですし。
あとvagrant-berkshelfは開発が終わるようなので、見送ります。gemでインストールするBerkshelfは終わるわけではないので、gemで入れましょう。
この記事では、rbenvとruby-buildでrubyをインストールするのに使います。
下準備
>pwd /c/Users/hidex7777 >mkdir mychef3 >cd mychef3 >vagrant init Trusty >vim Vagrantfile (Vagrantfileの修正) config.vm.network "private_network", ip: "192.168.33.10" :wq >vagrant up >vagrant ssh $ exit >vagrant ssh-config --host mychef3 >> %HOME%\.ssh\config >ssh mychef3 $ exit
Macとかの場合、ssh-config --host
の出力先は~/.ssh/config
にします。
WorkstationにChefとかをインストール
Step 2: Set up your workstationの"Run the Chef installer"の指示に従ってChef Clientをインストールします(前回、WindowsはGemでインストールするべきだと書きましたが、いまのインストーラならそちらを使うべきかと思います。knifeとかのツールもこれで使えるようになります)。
11.12.4-1がWin7で使える記事執筆時点の最新版みたいです。
インストールが終わったらコンソールを再起動して:
>path C:\opscode\chef\bin;C:\opscode\chef\embedded\bin;
にパスが通っているのを確認。
knifeの設定:
>knife configure
いろいろ聞かれますがぜんぶY
とかEnter
でOK。
便利なツールknife-soloは入れておきます:
>gem install knife-solo
Windowsの場合
ちなみに、Windows版だとないと困るgemを、前もってアンインストールしておきましたが:
gem uninstall win32-process gem uninstall windows-pr
このChefのインストールで、これらも入りました。
さらに、Windowsだとやはりrsyncがないので、cwRsyncのFree Editionをダウンロード、解凍して、中身をぜんぶパスが通っているディレクトリ(ぼくの場合はC:\Users\hidex7777\bin)に入れて、ssh.exeとssh-keygen.exeを削除。
以下の環境変数も追記:
chef-repo作成
>pwd /c/Users/hidex7777/mychef3 >knife solo init chef-repo
- ~/mychef3/chef-repo/.chef/knife.rb
ができていればたぶんOK。
自作のレシピは、つくられたディレクトリのなかのsite-cookbooksに入れます。
とりあえずGitHubにpush
GitHub側であらかじめchef-repoリポジトリをつくってあるとして:
>cd chef-repo >git init >git add . >git commit -m "first commit" >git remote add origin https://github.com/hidex7777/chef-repo.git >git push -u origin master
NodeをChefに対応させる
>knife solo prepare mychef3
- ~/mychef3/chef-repo/nodes/mychef3.json
というファイルができていれば、たぶんOKです。
defsetというcookbookをつくってみる
>knife cookbook create defset -o site-cookbooks
- ~/mychef3/chef-repo/site-cookbooks/defset/recipes/default.rb
ができていればたぶんOK。
/chef-repo/.chef/knife.rbに
cookbook_path ["cookbooks", "site-cookbooks"]
という記述があることを確認します。
(このknife.rbは~/.chef/knife.rbとは別のファイルです)
とりあえずHello Worldをやっておきます。
default.rbをテキストエディタで開いて:
log "hello world"
と記入。
~/mychef3/chef-repo/nodes/mychef3.jsonに:
{ "run_list":[ "recipe[defset]" ] }
と記入。
CookbookをNodeに反映
>pwd /c/Users/hideo64temp/mychef3/chef-repo >knife solo cook mychef3 * log[Hello World] action write
ここまででいちおうコミットしておく:
>git status >git add . >git commit -m "add defset" >git push origin master
ここまでは前回と同じです。
今回は、もうちょっと先に進みたいと思います。
ここから先は、すべてdefsetのdefault.rbに追記していきます。
aptitudeをupdate
してdist-upgrade
する
aptのupgradeはユーザがrecipeで自動化するべきではない、と述べられています。
そのため、これはインストール後、手動でやるべきとされています。
パッケージを最新版にしたければ、packageのリソース内に記述するべきであると。
例:
package "nginx" do action :upgrade end
とはいえ、使い捨てのVagrantにそこまで気を使う必要もない気がするので、次のように書いてしまう:
execute "aptitude-dist-upgrade" do command "aptitude dist-upgrade -y" action :nothing end execute "aptitude-update" do command "aptitude update -y" notifies :run, "execute[aptitude-dist-upgrade]", :immediately end
cookのとき、dist-upgradeのほうはaction :nothingなのでスルーされて、updateが実行されたときにnotifiesでdist-upgradeを:runするようになっています。
なお、「この書き方ではaptシステムを使っているディストリビューションでしか有効でなく、普遍性がないではないか」という批判は正しいのですが、「個人的レシピは徐々に育てる」をモットーにしていきたいと思います。
.bashrcファイル中のHISTSIZEとHISTFILESIZEをそれぞれ90000にする
templateリソースを使います。
ぼくはConsole2を使っているので、chef操作をしているタブとは別タブで、sshログインしておきます。
ssh mychef3
したコンソールのタブで、
cp /home/vagrant/.bashrc /vagrant/.bashrc.erb
でコピーしておく。
Nodeの/vagrantディレクトリは、WorkstationのVagrantfileがあるディレクトリと共有フォルダになっているので、手元にコピーがきます。
このファイルをおもむろにコピーして、/chef-repo/site-cookbooks/defset/templates/defaultディレクトリにペーストします。
この.bashrc.erbファイルをテキストエディタで開き、以下の部分を次のように書き換えます:
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1) HISTSIZE=<%= node['bashrc']['histsize'] %> HISTFILESIZE=<%= node['bashrc']['histfilesize'] %>
サイズは変数にしておきます。ファイル名は拡張子.erb
をつけて.bashrc.erbとして保存。
/chef-repo/nodes/mychef3.jsonをテキストエディタで開き、次のように変数の値(Attribute)を用意しておきます:
{ "bashrc":{ "histsize": 90000, "histfilesize": 90000 }, "run_list":[ "recipe[defset]" ] }
/chef-repo/site-cookbooks/defset/recipes/default.rbにtemplateリソースの記述をします:
template ".bashrc" do path "/home/vagrant/.bashrc" source ".bashrc.erb" mode 0644 end
コンソールのChef操作タブに戻り、
> knife solo cook mychef3
でNodeに反映させます。
-HISTSIZE=1000 -HISTFILESIZE=2000 +HISTSIZE=90000 +HISTFILESIZE=90000
のようにdiffが表示されればOKのはずです。
Vagrantにログインしているタブに切り替えて、ll
コマンドで.bashrcファイルのモードが-rw-r--r--
(つまり0644)になっているのを確認。
vi .bashrc
で、ファイルが適切に書き換えられているのを確認する。
.bash_aliasesファイルにalias eng='export LANG=en_US.UTF-8'
とalias jpn='export LANG=ja_JP.UTF-8'
の行を追記
これはssh接続でなく直接サーバのターミナルを開いたときに、日本語がちゃんと表示されないのを回避するためのエイリアス。
ssh接続のときはjpn
で日本語表示、ターミナルで直接開いたときはeng
で英語表示にする。
これもtemplateを使う。
たぶんインストールしたばかりのサーバには.bash_aliasesファイルはないので、Workstation側で作る。
alias eng='export LANG=en_US.UTF-8' alias jpn='export LANG=ja_JP.UTF-8'
と書いて、.bash_aliases.erbとして/chef-repo/site-cookbooks/hell/templates/defaultに保存する(この時点ではerbにする意味はないのですが)。
/chef-repo/site-cookbooks/defset/recipes/default.rbに追記する:
template ".bash_aliases" do path "/home/vagrant/.bash_aliases" source ".bash_aliases.erb" mode 0644 end
vim-noxをインストールしてデフォルトエディタにする
vim-noxのインストールのnotifiesからupdate-alternativesを呼び出すようにする(default.rbに追記):
execute "update-alternatives-editor" do command "update-alternatives --set editor /usr/bin/vim.nox" action :nothing end package "vim-nox" do action :install notifies :run, "execute[update-alternatives-editor]", :immediately end
etckeeperとgitとtigのインストール
Chefで完全管理して冪等性が保たれているのにetckeeperもなにもないだろう、という気もしますが、なければないで不安なので、入れます。
vim-noxのときのように、actionに:nothingを指定しておいて、他から呼び出すように書いてもいいのだけれど、どれかが何かのはずみでインストールされてしまうと、他がインストールされなくってめんどくさいので、個別に書きます:
package "etckeeper" do action :install end package "tig" do action :install end package "git" do action :install end
もちろんvim-noxのところでやったように
package "git" do action :install notifies :install, "package[tig]", :immediately end
とやってもよいでしょう(tigのactionは:nothingに)。
/etc/etckeeper/etckeeper.confの編集
.bashrcのときと同じように、ssh mychef3
したコンソールのタブで、
cp /etc/etckeeper/etckeeper.conf /vagrant/etckeeper.conf.erb
でコピーしておく。
このファイルを/chef-repo/site-cookbooks/defset/templates/defaultディレクトリにペーストします。
次の部分を書き換えます:
# The VCS to use. #VCS="hg" VCS="git" #VCS="bzr" #VCS="darcs"
これも、この時点ではerbにする意味はないですが(変数の埋め込みがないので)、念の為にerbファイルにしてtemplateとして扱うのがベターかと思います。
伊藤直也本でもそう述べられています。
template "etckeeper.conf" do path "/etc/etckeeper/etckeeper.conf" source "etckeeper.conf.erb" mode 0644 end
ntpをインストール
package "ntp" do action :install end
ntpはサービスですが、Ubuntuは「インストールしたサービスは、常時動いている。止めたきゃアンインストールせよ」という方針のOSなので、基本的にはサービスのスタートを考えなくてよいとも言えます。
時刻が著しくズレていて同期がとれなくなった場合のことを考えて、設定ファイルを書き換えてもよいかもしれません:
service "ntp" do supports :status => true, :start => true, :stop => true, :restart => true, :reload => true action :nothing end execute "ntpdate" do command "ntpdate ntp.nict.jp" action :nothing notifies :start, "service[ntp]", :immediately end template "ntp.conf" do path "/etc/ntp.conf" source "ntp.conf.erb" mode 0644 notifies :stop, "service[ntp]", :immediately notifies :run, "execute[ntpdate]", :immediately end
この場合もあらかじめ
$ cp /etc/ntp.conf /vagrant/ntp.conf.erb
でコピーをもってきて、次のように書き換えるか:
server ntp.nict.jp #server 0.ubuntu.pool.ntp.org #server 1.ubuntu.pool.ntp.org #server 2.ubuntu.pool.ntp.org #server 3.ubuntu.pool.ntp.org
デフォルトをコメントアウトせずにntp.nict.jpの行を書き加えるだけにするか、どちらでもよいでしょう。
あるいは設定ファイルは書き換えずに、installと同時にstopしてntpdateしてstartする、というだけでもいいかもしれません(ぼくはそうしています)。
パスワード認証の無効化(/etc/ssh/sshd_config)
sshd_configファイルをテンプレート化します。
ssh mychef3
してあるタブで:
$ cp /etc/ssh/sshd_config /vagrant/sshd_config.erb
手元にきたコピーを/templates以下にペースト:
#ポート番号を変数化しておく Port <%= node['sshd_config']['port'] %> #'#PasswordAuthentication yes'の行を書き換える <%= node['sshd_config']['passauth'] %> #'UsePam yes'の行を書き換える <%= node['sshd_config']['usepam'] %>
mychef3.jsonファイルに変数を追記:
"sshd_config":{ "port": 22, "passauth": "PasswordAuthentication no", "usepam": "UsePam no" },
default.rbファイルに追記:
service "ssh" do supports :status => true, :start => true, :stop => true, :restart => true, :reload => true action :nothing end template "sshd_config" do path "/etc/ssh/sshd_config" source "sshd_config.erb" mode 0644 notifies :restart, "service[ssh]", :immediately end
UFW有効化、「OpenSSHへのWorkstationからの許可およびそれ以外からのリミット」ルール作成
UFW(Uncomplicated FireWall)をあつかうのに便利なFirewallリソースが公開されているのですが、この記事を書いている時点で、Travis CIのテストがFailしているので、ひとまず避けておくことにします。
ここではより原始的な方法で。
execute "ufw-allow-openssh" do command 'ufw insert 1 allow from 192.168.33.0/24 to any app OpenSSH' action :nothing end execute "ufw-limit-openssh" do command 'ufw limit OpenSSH' action :nothing notifies :run, "execute[ufw-allow-openssh]", :immediately end execute "ufw-enable" do command 'printf y | ufw enable' notifies :run, "execute[ufw-limit-openssh]", :immediately end
ufw enable
したときに対話的に入力を求められるので(-yオプションがきかない)、printf y
で渡しています。
apache2インストール
UbuntuのAPTで配布されているApache2も、バージョンが2.4系統になったようです。
execute "ufw-allow-apache" do command 'ufw allow "Apache Full"' action :nothing end package "apache2" do action :install notifies :run, "execute[ufw-allow-apache]", :immediately end
Workstationのブラウザからhttp://192.168.33.10(Vagrantfileで設定したプライベートネットワーク)に接続して"Apache2 Ubuntu Default Page"が表示されれば成功です。
以前の簡素な"It works!"ページからだいぶ様変わりしていてびっくりしました。
ドキュメントルートを/vagrantにしたwwwサイトを作ってa2enable、000-defaultをa2disable
まずデフォルトの設定ファイルをコピー(いつのまにか.confという拡張子が付くようになりました):
$ cp /etc/apache2/sites-available/000-default.conf /vagrant/www.conf.erb $ echo "from vagrant" > /vagrant/index.html
2.2ではデフォルトのドキュメントルートが/var/wwwでしたが、設定ファイルを開くとわかるように、2.4では/var/www/htmlになっています(Ubuntu)。
また、Directoryディレクティブが書かれていないので(apache2.confに書かれている)、書き加える必要があります。
www.conf.erbファイルをtemplatesディレクトリにペースト、次のように記述:
DocumentRoot <%= node['wwwconf']['documentroot'] => <Directory <%= node['wwwconf']['directory'] %>> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory>
"wwwconf":{ "documentroot": "/vagrant", "directory": "/vagrant" },
レシピの記述:
service "apache2" do supports :status => true, :start => true, :stop => true, :restart => true, :reload => true action :nothing end execute "a2dissite-default" do command 'a2dissite 000-default' action :nothing notifies :reload, "service[apache2]", :immediately end execute "a2ensite-www" do command 'a2ensite www' action :nothing notifies :run, "execute[a2dissite-default]", :immediately end template "www.conf" do path "/etc/apache2/sites-available/www.conf" source "www.conf.erb" mode 0644 notifies :run, "execute[a2ensite-www]", :immediately end
新しい設定ファイルwwwをensiteすると同時にデフォルトの000-defaultをdissiteするのがポイントです。
mod_sslをa2enmod、apache2リロード
テンプレート用設定ファイルをコピーします:
$ cp /etc/apache2/sites-available/default-ssl.conf /vagrant/www-ssl.conf.erb
書き換えるところはありませんが(DocumentRootを書き換えたければお好きに)、templates/defaultにコピーします。
レシピ:
execute "a2ensite-ssl" do command 'a2ensite www-ssl' action :nothing notifies :reload, "service[apache2]", :immediately end execute "a2enmod-ssl" do command 'a2enmod ssl' action :nothing notifies :run, "execute[a2ensite-ssl]", :immediately end template "www-ssl.conf" do path "/etc/apache2/sites-available/www-ssl.conf" source "www-ssl.conf.erb" mode 0644 notifies :run, "execute[a2ensite-ssl]", :immediately end
service[apache2]はすでに定義してあるものを使います。
WorkstationのChromeでhttps://192.168.33.10にアクセスしてデフォルトページが表示されれば成功です(証明書が自己証明なので警告メッセージが出ます)。
rbenvとruby-build
rubyのReadline6.3に対応してない問題(https://bugs.ruby-lang.org/issues/9578)があって、rbenvからのインストールが難航していたのですが、この問題に対するパッチが適用されたバージョンならインストール(ビルド)可能です。
最近のものだと:
- 2.1.2 (OK)
- 2.1.1 (既知の不具合があるためインストールすべきでない)
- 2.0.0-p481 (OK)
1.9.3系統はたぶん大丈夫かと……(わかんないですが、ぼくの環境では1.9.3-p392がビルドエラー出ませんでした。Bug#9548をみると1.9.3もRequiredになってますが)。
>gem install berkshelf
Windowsだと死ぬほど時間がかかりますが……。
リポジトリトップに"Berksfile"というファイル名のファイルを作ります:
source "https://api.berkshelf.com" cookbook 'ruby_build' cookbook 'rbenv', github: "fnichol/chef-rbenv"
Berkshelfのv0.3系統からBerksfileの書き方も変わったので、注意。
cookbookをインストールします:
>berks vendor
現在のリポジトリにberks-cookbooksというディレクトリがつくられて、そこにインストールされます。
ちなみにv0.2のときみたいにberks install
すると、デフォルトでは~/.berkshelf/cookbooksにインストールされます(設定によると思いますが)。
>berks vendor cookbooks
だとcookbooksにインストールしようと試みますが、すでに存在するディレクトリだと怒られます。なので、必要があれば、cookbooksディレクトリを削除してからやりましょう。
/chef-repo/.chef/knife.rbを修正します:
cookbook_path ["cookbooks", "site-cookbooks", "berks-cookbooks"]
自動的に追加してくれればいいのに……。
mychef3.jsonに追記:
(省略) "rbenv": { "user_installs": [ { "user": "vagrant", "rubies": ["2.1.2"], "global": "2.1.2" } ] }, "run_list":[ "recipe[defset]", "ruby_build", "rbenv::user" ] }
>knife solo cook mychef3
必要な依存パッケージも自動的にじゃんじゃかインストールしていってくれます。超楽チン。
>ssh mychef3 $ ruby -v ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-linux] $ gem -v 2.2.2 $ rbenv versions system * 2.1.2 (set by /home/vagrant/.rbenv/version)
ふう~大変だった。。。(Readline6.3問題を知らなかったので)