画像

[2014-01-09-1] からmasutaka.netのCIを開始したが、残念ながら
masutaka.netに直接serverspecする、なんちゃってCIだった。
masutaka.netにcookしてからPRを出して、WerckerにCIさせていた。

WerckerとAWSを連携させて、テストのたびにサーバをまっさらな状態から
作り、終わったら破棄することが可能になったので、ここに記録しておく。

去年くらいに話題になったこの辺の話。
Vagrant + Chef Solo + serverspec + Jenkins でサーバー構築を CI - naoyaのはてなダイアリー
naoya/circleci-serverspec

なんで今までやらなかったかというと、cookが一発で通らないレシピになっ
ていたから。。気づいてはいたんだけど、本番サーバのテストが通りさえ
すればよかったし。。。

インフラ系技術の流れ - Gosuke Miyashita

こちらの記事でいうところの、Orchestrationの仕事までChefにやらせてい
たのが敗因。GitHubのprivateリポジトリにおいてあるdotfilesや、
growthforecast、tiarra、mobircまでもChefにインストールさせていた。

ユーザmasutakaに依存しないレシピに変更して、手元の
Vagrant+VirtualBoxで一発でspecが通るまでがステップ1。

次に手元のVagrant+AWSで同じことが出来るまでがステップ2。

これをWercker上で実行できるようにwercker.ymlを書き換えたのがステッ
プ3。

最終的なVagrantfileとwercker.ymlは以下のとおり。

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.define :local do |local|
local.vm.box = "ubuntu/trusty64"
local.vm.network "private_network", ip: "192.168.50.13"
local.ssh.forward_agent = true
local.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", "2048"]
end
end
config.vm.define :ec2 do |ec2|
ec2.vm.box = 'dummy'
ec2.vm.box_url = 'https://raw.githubusercontent.com/mitchellh/vagrant-aws/master/dummy.box'
ec2.vm.provider :aws do |aws, override|
aws.access_key_id = ENV['AWS_ACCESS_KEY_ID']
aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
aws.region = 'ap-northeast-1'
aws.instance_type = 't2.micro'
aws.ami = 'ami-a1124fa0'
aws.security_groups = ['default']
aws.keypair_name = 'ec2'
aws.tags = { 'Name' => 'vagrant' }
override.ssh.username = 'ubuntu'
override.ssh.private_key_path = '~/.ssh/ec2.pem'
end
end
end
view raw Vagrantfile hosted with ❤ by GitHub
box: wercker/rvm
# Build definition
# See the Ruby section on the wercker devcenter:
# http://devcenter.wercker.com/articles/languages/ruby.html
build:
# The steps that will be executed on build
steps:
- rvm-use:
version: ruby-2.1.2
# A step that executes `bundle install` command
- bundle-install
# A custom script step, name value is used in the UI
# and the code value contains the command that get executed
- script:
name: echo ruby information
code: |
echo "ruby version $(ruby --version) running"
echo "from location $(which ruby)"
echo -p "gem list: $(gem list)"
# Add more steps here:
- script:
name: create ~/.ssh
code: install -d -m 755 ~/.ssh
- create-file:
name: create ~/.ssh/ec2.pem
filename: $HOME/.ssh/ec2.pem
overwrite: true
hide-from-log: true
content: $EC2_SSH_KEY_PRIVATE
- script:
name: set permission for ~/.ssh/ec2.pem
code: chmod 400 $HOME/.ssh/ec2.pem
- script:
name: install vagrant
code: |
wget https://dl.bintray.com/mitchellh/vagrant/vagrant_1.6.5_x86_64.deb
sudo dpkg -i vagrant_1.6.5_x86_64.deb
which vagrant
vagrant -v
vagrant plugin install vagrant-aws unf
- script:
name: vagrant up
code: vagrant up ec2 --provider=aws
- script:
name: create ~/.ssh/config
code: |
vagrant ssh-config --host=ec2 ec2 > ~/.ssh/config
chmod 644 ~/.ssh/config
- script:
name: cook
code: bundle exec knife solo bootstrap ec2
- script:
name: serverspec
code: bundle exec rake spec:ec2
- script:
name: vagrant destroy
code: vagrant destroy -f ec2
view raw wercker.yml hosted with ❤ by GitHub

いくつかハマったけど、凡ミスだったので特には触れない。上の設定に従
えば同じことは出来るはず。(CircleCIだと各インスタンスにssh出来るの
で、調査は早かったんだろうと夢想。)

でも一点だけad hocな対応をしていて、plenvやrbenvを使ったPerl/Rubyの
インストールはビルド済みのtar ballを展開するだけに変更した。
Werckerはビルドが5分間止まると失敗だと見なすから。ビルド全体の時間
は25分までOK。

そもそもImmutable Infrastructure的にplenvやrbenvを使うのはどうなの?
という節もあって、そこは今後変えるかもしれない。

wercker.ymlも毎回Vagrantをインストールして、vagrant upするという無
駄なことをしているので、Docker使って時短させるかもしれない。

とりあえずCI出来るようになったので、今回はこれで良しとする。