自分の誕生日である4/7に表参道.rb #10が開催ということでバースデーLTをしてきました
- 例のやつ
- 近況
- スライド版
- 完全版
- 付録
- 最後に
例のやつ
34歳になりました。もうすぐ定年ですが頑張ります ('A`)
近況
最近はプロビジョニングおじさん業やってます。 itamae, Serverspec, VagrantなどギリギリRubyやってます。
最近送ったPullRequest
vagrant-awsプラグイン(のスポットインスタンス対応版のフォーク)
スポットインスタンス作成時にIAMロールが適用されなかったので適用されるようにした
vagrant-cloudstackプラグイン(1つ目)
CloudStackのAPI仕様上は複数network_idを渡せるはずなのにvagrantからだと複数のnetwork_idを渡せないので複数渡せるようにした
vagrant-cloudstackプラグイン(2つ目)
スライド版
LTで発表するためにいろいろ削ったダイジェスト版です
http://sue445.github.io/omotesandorb-10/
https://github.com/sue445/omotesandorb-10/blob/master/slides.md (スライドのソース)
完全版
スライドに書ききれなかった諸々の詳しい説明を含めた完全版です
三行まとめ
- Vagrant
- Wercker
- DigitalOcean
itamaeについて
- https://github.com/itamae-kitchen/itamae
- プロビジョニングツール(ChefとかAnsibleみたいなやつ)
itamaeプラグインについて
レシピ(ミドルウェアのインストール手順など)をgemにしてRubygems.orgで公開することができる
Gemfile
gem "itamae-plugin-recipe-git_now"
recipe.rb
include_recipe "git_now"
git-now がインストールされる
sue445製itamaeプラグイン
暗号化したファイルを転送するプラグイン
tigをビルドするプラグイン
git-nowをビルドするプラグイン
tmuxをビルドするプラグイン
単独にするまでもない雑なレシピ集(今のところdebファイルやrpmファイルをダウンロードしてインストールするレシピだけ)
itamaeプラグインのテスト事情
rubygemsに公開されてるitamaeプラグインを全部見たけど、CIしてるのが自分だけという現実に気づいてしまった。。。(Vagrantfile置いてspec書いてるのは結構あった)
— sue445 (@sue445) March 29, 2016
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)- 自分以外でCIしてるのが1つだけあった( https://github.com/gongo/itamae-plugin-resource-firewalld )ので計6つ *2
bundle gem
直後の .travis.yml しかないやつはノーカン
- 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 で説明
ローカルでVagrant + VirtualBox環境構築
からバイナリをインストール
自分自身を適用するレシピと、それに対するテストを書く
include_recipe "git_now"
describe file("#{node[:git_now][:prefix]}/bin/git-now") do it { should be_file } it { should be_executable } end
Serrverspec だとインフラの構成をrspecでテストすることができる
Serverspecの中でitamaeのnodeを使う方法は下記を参考にしてください
VirtualBox内でitamaeのレシピ&Serverspec実行
itamae実行
Serverspec実行
Vagrantfile
https://github.com/sue445/itamae-plugin-recipe-git_now/blob/v0.1.1/Vagrantfile
Rakefile
itamaeやServerspecの実行はRakefileに集約しておくとCIに落としこむ時に楽です
https://github.com/sue445/itamae-plugin-recipe-git_now/blob/v0.1.1/Rakefile
taskを動的生成してますが rake -T
するとこんな感じ
rake itamae:centos70 # Running itamae to centos70 rake itamae:debian8 # Running itamae to debian8 rake spec:centos70 # Run RSpec code examples rake spec:debian8 # Run RSpec code examples
Rakefile中の
HOSTS = %w(centos70 debian8)
はVagrantfileで使ってるVMに対応しています
https://github.com/sue445/itamae-plugin-recipe-git_now/blob/v0.1.1/Vagrantfile#L25-L41
DigitalOcean
- 海外の格安VPS
- 最低プランなら1時間で$0.007から使える
- 1ドル113円なら0.79円
- $10のクーポンコードもあるので1428時間は無料で使える
- https://m.do.co/c/7978f6d6167e から登録してもらえると$10もらえて、$25課金した時に僕も$25もらえます (チラチラッ
- 全部SSDなので速い
- ビルドする時だけインスタンスを立ち上げれば費用を抑えることができる
DigitalOceanの設定
Access Tokenの生成
API -> Your Tokens -> Generate New Tokenよりアクセストークンを生成
表示されたトークンは後で使うのでブラウザのタブはそのままにしておく
Wercker
- CIサービス(Travis CIやCircle CI的なやつ)
- 「ワーカー」と読むらしい https://twitter.com/wercker/status/449204933481746432
- box(実行環境)やstep(実行コマンド)がプラグインとして提供されているのが特徴
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を作った
使い方
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のビルドからは
wercker.yml(直列実行版)
wercker.ymlをかいつまんで説明すると
Rubyの設定
- 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の順でビルド
上の方でRakefileに集約したおかげでビルドスクリプトはシンプルになっています
#!/bin/bash -xe 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
- Paraduct (parallel + parameterize + product)
- .travis.ymlみたいな感じにいい感じにマトリックステストをするためのgem
- 2年前に作ったgemなんだけどいろいろ書き直した
- v0.0.3 -> v1.0.0
詳しい説明
上のエントリだとビルドごとにディレクトリ作ってrsyncするようになってますが、v1.0.0ではrsyncは任意になってます *5
.paraduct.yml
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を使うことができ、ビルド時間を短縮することができます
小ネタ
参考文献
オライリーのServerspec本にDIgitalOceanやWercker周りの説明が載ってる
itamaeやServerspecの wercker.yml
や Vagrantfile
を熟読した
付録
どうしてTravisCI じゃないのか?
こういうパラメータごとの並列ビルドだとWerckerよりも Travis CIが断然便利なのですが、あえて使わなかった理由は2つあります
- 有料版の https://travis-ci.com/ だと秘密鍵に対応してるが、無料版の https://travis-ci.org/ だと対応していない *7
- Travis CI にはVagrantはインストールされていないのでもし使うとするとビルド中にVagrantとVagrantプラグインをインストールする必要があり、その分ビルドに時間がかかる
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 |
公式ドキュメント
- DigitalOcean
- Pricing | DigitalOcean DigitalOceanのスペックと料金表
- EC2
- スポットインスタンス - Amazon Elastic Compute Cloud スポットインスタンスの仕様
- インスタンスタイプ - Amazon EC2 | AWS 現行世代のスペック一覧
- 旧世代インスタンス - Amazon EC2 | AWS 旧世代のスペック一覧
他のプランだといい感じに値段が同じくらいのがなくて1つずつしか比較できなくて申し訳ないですが、ざっと見た感じ同じくらいの値段ならスポットインスタンスの方がスペックはよかったです
難点は vagrant-awsプラグイン がスポットインスタンスに正式対応してないこと
issueには上がってる
それでもVagrantからスポットインスタンスを使う方法
さっきのissueで紹介されてるfork版のブランチを使う https://github.com/mitchellh/vagrant-aws/issues/32#issuecomment-163228219
ググるとプラグインを自分でbuildしろみたいなやつが結構ヒットしますが、CIも考慮すると面倒なので自分は素直にGemfileに書いてます
source "https://rubygems.org" group :development do gem "vagrant", github: "mitchellh/vagrant", tag: "v1.8.1" end group :plugins do # AWSのAPI keyをVagrantfileに環境変数で埋め込んでいるため gem "dotenv" gem "vagrant-aws", github: "KariusDx/vagrant-aws", branch: "spot" end
Gemfileに書いてるとvagrantプラグインをforkしてPullRequestする時にも自分のトピックブランチを使えるメリットもあります。(冒頭のPullRequest出してるブランチもGemfileに書いてる)
実行する時
bundle exec vagrant up --provider=aws
最後に
今期のプリキュアはRubyがテーマなのでRubyistはみんな見るべき
「魔法つかいプリキュア」なのにRubyスタイルでパワー強化なのはRubyistのマサカリの鋭さの現れか(考えすぎ)
重要なのでもう一度例のやつ
*1:2016年4月時点
*2:ただしUnit TestのみCI
*3:wercker-box-rvm-vagrant-digitaloceanはClassicしか対応していないため。Dockerfileでもよかったんだけど強いこだわりはなかったのでサクッといける方を選択(あとitamaeやserverspecがClassic使ってたので準拠)
*4:1.8.1時点
*5:具体的には .paraduct.yml の work_dir を空にすればカレントディレクトリで実行するのでrsyncもしない
*6:TravisCI, Wercker, CircleCIでは使えるのを確認
*7:https://docs.travis-ci.com/user/private-dependencies/ の「Custom SSH keys are currently only available for private repositories on travis-ci.com.」より
*8:https://docs.travis-ci.com/user/workers/container-based-infrastructure/#Routing-your-build-to-container-based-infrastructure