自分の誕生日である4/7に表参道.rb #10が開催ということでバースデーLTをしてきました
omotesandorb.connpass.com
例のやつ
www.amazon.co.jp
34歳になりました。もうすぐ定年ですが頑張ります ('A`)
近況
最近はプロビジョニングおじさん業やってます。
itamae, Serverspec, Vagrant などギリギリRuby やってます。
最近送ったPullRequest
Fix. Can not used iam_instance_profile options when spot_instance is enabled by sue445 · Pull Request #2 · KariusDx/vagrant-aws · GitHub
スポットインスタンス 作成時にIAMロールが適用されなかったので適用されるようにした
Support multiple network ids by sue445 · Pull Request #148 · schubergphilis/vagrant-cloudstack · GitHub
CloudStackのAPI 仕様上は複数 network_idを渡せるはずなのにvagrant からだと複数 のnetwork_idを渡せないので複数 渡せるようにした
Add ssh_network_id configuration by sue445 · Pull Request #149 · schubergphilis/vagrant-cloudstack · GitHub
複数 NIC がある場合にeth0以外でssh したかった
スライド版
LTで発表するためにいろいろ削ったダイジェスト版です
http://sue445.github.io/omotesandorb-10/
https://github.com/sue445/omotesandorb-10/blob/master/slides.md (スライドのソース)
完全版
スライドに書ききれなかった諸々の詳しい説明を含めた完全版です
三行まとめ
itamaeについて
レシピ(ミドルウェア のインストール手順など)をgemにしてRubygems .orgで公開することができる
Gemfile
gem " itamae-plugin-recipe-git_now "
recipe.rb
include_recipe " git_now "
git-now がインストールされる
sue445製itamaeプラグイン
暗号化したファイルを転送するプラグイン
sue445.hatenablog.com
tigをビルドするプラグイン
sue445.hatenablog.com
git-nowをビルドするプラグイン
sue445.hatenablog.com
tmuxをビルドするプラグイン
sue445.hatenablog.com
単独にするまでもない雑なレシピ集(今のところdeb ファイルやrpm ファイルをダウンロードしてインストールするレシピだけ)
github.com
itamaeプラグイン のテスト事情
https://rubygems.org/search?utf8=%E2%9C%93&query=itamae-plugin
47個中、テストを書いてるgemは18個 *1
bundle gem
直後の expect(Itamae::Plugin::Recipe::Hoge::VERSION).not_to be nil
しかないやつはノーカン
CIしてるgemは5個(全部自分のやつw)
itamaeプラグイン のIntegration TestのCIの知見を広めたいのが今回の主旨
CIされてることのメリット
複数 OSテストしたい時に動作確認が楽(開発者視点)
リポジトリ のトップにTravis CIとかのバッジが貼ってあれば安心感がある(利用者視点)
常にビルドされているという安心感
PR送った時にビルドの結果が出る安心感
itamaeプラグイン をテストする手順
ローカルでVagrant + VirtualBox 環境構築
自分自身を適用するレシピと、それに対するテストを書く
VirtualBox 内でitamaeのレシピ&Serverspec実行
CIでレシピ&Serverspec実行
今回は https://github.com/sue445/itamae-plugin-recipe-git_now で説明
からバイナリをインストール
自分自身を適用するレシピと、それに対するテストを書く
install.rb
include_recipe " git_now "
git_now_spec.rb
describe file("#{ node[:git_now ][:prefix ]} /bin/git-now " ) do
it { should be_file }
it { should be_executable }
end
Serrverspec だとインフラの構成をrspec でテストすることができる
serverspec.org
Serverspecの中でitamaeのnodeを使う方法は下記を参考にしてください
qiita.com
VirtualBox 内でitamaeのレシピ&Serverspec実行
itamae実行
Serverspec実行
Vagrantfile
https://github.com/sue445/itamae-plugin-recipe-git_now/blob/v0.1.1/Vagrantfile
itamaeやServerspecの実行はRakefile に集約しておくとCIに落としこむ時に楽です
https://github.com/sue445/itamae-plugin-recipe-git_now/blob/v0.1.1/Rakefile
taskを動的生成してますが rake -T
するとこんな感じ
rake itamae:centos70
rake itamae:debian8
rake spec:centos70
rake spec:debian8
Rakefile 中の
HOSTS = %w( centos70 debian8 )
はVagrantfileで使ってるVM に対応しています
https://github.com/sue445/itamae-plugin-recipe-git_now/blob/v0.1.1/Vagrantfile#L25-L41
海外の格安VPS
最低プランなら1時間で$0.007から使える
全部SSD なので速い
ビルドする時だけインスタンス を立ち上げれば費用を抑えることができる
DigitalOceanの設定
API -> Your Tokens -> Generate New Tokenよりアクセストークンを生成
表示されたトークンは後で使うのでブラウザのタブはそのままにしておく
wercker-box-rvm-vagrant -digitalocean
https://github.com/sue445/wercker-box-rvm-vagrant-digitalocean
wercker-box-rvm-vagrant-aws をforkしてrvmとvagrant とvagrant -digitaloceanプラグイン をインストール済のboxを作った
使い方
wercker.yml
box : sue445/rvm-vagrant-digitalocean@1.0.0
Werckerの設定
Classicにする
Infrastructure stackでClassicを選択 *3
ssh keyの生成
Settings -> SSH keysからDigitalOcean用の鍵を作成
Generateを押すと鍵が生成される
Environment variablesの登録
Settings -> Environment variables から環境変数 を登録
DIGITALOCEAN_ACCESS _TOKEN:さっき作ったDigitalOceanのアクセストークンを入力し、Protectedにチェックを入れる
Protectedにチェックが入っていればビルドのコンソールにも出てこなくなる
DIGITALOCEAN_KEY:さっき作ったssh の鍵を選択
werckerのビルドからは DIGITALOCEAN_KEY_PUBLIC
, DIGITALOCEAN_KEY_PRIVATE
のような変数で参照できる
wercker.yml(直列実行版)
https://github.com/sue445/itamae-plugin-recipe-git_now/blob/575ef249811ceaeba5d80ecde830c30cea46395c/wercker.yml
wercker.ymlをかいつまんで説明すると
- rvm-use :
version : 2.3.0
- script :
name : install bundler
code : gem install bundler -v 1.10.6 --no-document
- bundle-install :
jobs : 4
bundlerのバージョンが1.10.6なのは、Vagrant *4 がbundler 1.11系に対応していないため
https://github.com/mitchellh/vagrant/blob/v1.8.1/vagrant.gemspec#L18
WerckerからDigitalOceanに接続するための設定
上の方で生成した秘密鍵 と公開鍵を設置
- script :
name : create .ssh directory
code : mkdir -m 700 -p $HOME/.ssh
- create-file :
name : put private key
filename : $HOME/.ssh/id_rsa.vagrant
overwrite : true
hide-from-log : true
content : $DIGITALOCEAN_KEY_PRIVATE
- create-file :
name : put public key
filename : $HOME/.ssh/id_rsa.vagrant.pub
overwrite : true
hide-from-log : true
content : $DIGITALOCEAN_KEY_PUBLIC
- script :
name : chmod 600 id_rsa
code : chmod 600 $HOME/.ssh/id_rsa.vagrant
ビルド実行
- script :
name : test centos70
code : ./ci/build.sh centos70
- script :
name : test debian8
code : ./ci/build.sh debian8
centos70 -> debian8の順でビルド
build.sh
上の方でRakefile に集約したおかげでビルドスクリプト はシンプルになっています
readonly HOST =$1
vagrant up $HOST --provider=digital_ocean
bundle exec rake itamae:$HOST
bundle exec rake spec:$HOST
vagrant destroy -f $HOST
実はこれだとテストが失敗した時にVM が残り続けるという不具合がありますが後で解決します。(シェルスクリプト の中でエラーハンドリングしてもいいんだけどエラーコードを全部チェックする必要があるのでコードが冗長になる)
ビルドの並列実行
直列実行だと遅い(2つ合わせて5分くらいかかる)ので並列実行できるようにした
Paraduct (parallel + parameterize + product)
.travis .ymlみたいな感じにいい感じにマトリックス テストをするためのgem
2年前に作ったgemなんだけどいろいろ書き直した
詳しい説明
sue445.hatenablog.com
sue445.hatenablog.com
上のエントリだとビルドごとにディレクトリ作ってrsync するようになってますが、v1.0.0ではrsync は任意になってます *5
script : |-
./ci/build.sh ${HOST}
after_script : |-
vagrant destroy -f $HOST
variables :
HOST :
- debian8
- centos70
max_threads : 4
この例だと ./ci/build.sh debian8
と ./ci/build.sh centos70
が並列に実行される
after_script
はビルドが失敗時しても必ず実行されるので確実にVM をdestroyしてくれる
その他の特徴
capistrano みたいにホストごとに色がつくのが特徴
https://app.wercker.com/#buildstep/56f46fa951d1ad950a01ad71
CIで使う時
基本的にはビルドスクリプト で
gem install paraduct
paraduct test
みたいな処理を書くと思いますが、Ruby のプロダクトであればGemfileに
gem " paraduct "
を書いて
bundle exec paraduct test
することでCIサービス側で提供されているbundlerのキャッシュ機能*6 を使うことができ、ビルド時間を短縮することができます
小ネタ
DigitalOceanのregionは当たり外れがある(気がする)
nyc1だとたまにVM 起動後にssh が通らなくて固まることがあるけど、nyc3に変えたら起こらなくなった
ハマったら他のregionに変えてみるとよさげ
不慮の事故でVM が残り続けるのを防ぐために古いVM を削除するスクリプト をheroku schedulerで動かしてる
参考文献
オライリー のServerspec本にDIgitalOceanやWercker周りの説明が載ってる
www.oreilly.co.jp
itamaeやServerspecの wercker.yml
や Vagrantfile
を熟読した
付録
どうしてTravisCI じゃないのか?
こういうパラメータごとの並列ビルドだとWerckerよりも Travis CIが断然便利なのですが、あえて使わなかった理由は2つあります
DigitalOcean vs EC2スポットインスタンス
安いので有名なのはEC2のスポットインスタンス ですが、同じくらいの価格帯でスペックを比較してみました *10
DigitalOcean ($ 0.015 / hr)
EC2 m1.small ($ 0.01くらい)
Memory
1 GB
1.7 GB
CPU
1 Core
1 Core
Disk
30 GB
160 GB
公式ドキュメント
他のプランだといい感じに値段が同じくらいのがなくて1つずつしか比較できなくて申し訳ないですが、ざっと見た感じ同じくらいの値段ならスポットインスタンス の方がスペックはよかったです
難点は vagrant-awsプラグイン がスポットインスタンス に正式対応してないこと
issueには上がってる
github.com
さっきのissueで紹介されてるfork版のブランチを使う
https://github.com/mitchellh/vagrant-aws/issues/32#issuecomment-163228219
github.com
ググる とプラグイン を自分でbuildしろみたいなやつが結構ヒットしますが、CIも考慮すると面倒なので自分は素直にGemfileに書いてます
source " https://rubygems.org "
group :development do
gem " vagrant " , github : " mitchellh/vagrant " , tag : " v1.8.1 "
end
group :plugins do
gem " dotenv "
gem " vagrant-aws " , github : " KariusDx/vagrant-aws " , branch : " spot "
end
Gemfileに書いてるとvagrant プラグイン をforkしてPullRequestする時にも自分のトピックブランチを使えるメリットもあります。(冒頭のPullRequest出してるブランチもGemfileに書いてる)
実行する時
bundle exec vagrant up --provider=aws
最後に
VIDEO youtu.be
「魔法つかいプリキュア 」なのにRuby スタイルでパワー強化なのはRubyist のマサカリの鋭さの現れか(考えすぎ)
重要なのでもう一度例のやつ
www.amazon.co.jp