スクラップ・アンド・ビルド方式で Ansible の Playbook を開発する場合に、Bootstrapping / Provisioning / Testing に掛かる時間を短縮するために試したことのメモ
準備
-
Ansible + Vagrant 以外でホストにインストールされているもの
./Gemfilesource 'https://rubygems.org' gem 'rake' gem 'serverspec' gem 'highline' gem 'test-kitchen' gem 'kitchen-ansible' gem 'kitchen-vagrant', :github => 'test-kitchen/kitchen-vagrant', :branch => 'master' gem 'busser-rspec'
vagrant_plugin_listvagrant-share (1.1.3, system) vagrant-vbguest (0.10.0)
-
- VM の VirtualBox Guest Additions のインストール状況を確認して、必要があれば自動的にインストールしてくれるプラグイン
インストールvagrant plugin install vagrant-vbguest
-
-
実行時間を計測するために用意したもの
- test-kitchen + kitchen-vagrant + kitchen-ansible で利用するもの
- VMのベースイメージとして、hansode/centos-6.6-x86_64を利用する
- CentOS-6.6-x86_64-minimal + VirtualBox Guest Additions (4.3.20) + その他
- VMのベースイメージとして、hansode/centos-6.6-x86_64を利用する
./.kitchen.yml--- driver: name: vagrant provision: true vagrantfiles: - ./Vagrantfile.rb box: hansode/centos-6.6-x86_64 vm_hostname: kitchen-vagrant customize: cpuexecutioncap: 90 memory: 2048 provisioner: name: ansible_playbook platforms: - name: centos6 suites: - name: provisioning provisioner: hosts: kitchen-vagrant playbook: provisioning.yml
./Vagrantfile.rbVagrant.configure('2') do |c| end # ここでは特に設定が追加されていない状態
./provisioning.yml--- - hosts: 127.0.0.1 connection: local user: vagrant sudo: yes tasks: - name: install the 'Development tools' yum: name="@Development tools" state=latest - name: install the latest version of Apache yum: name=httpd state=latest - name: start service httpd, if not running service: name=httpd state=started - name: enable service httpd, and not touch the running state service: name=httpd enabled=yes
- test-kitchen + busser-rspec + Serverspec で利用するもの
- Serverspec のテストコードはある程度の実行時間が必要となるように適当に作成した
./test/integration/provisioning/rspec/でserverspec-initを実行serverspec-init ---------------------------------- Select OS type: 1) UN*X 2) Windows Select number: 1 Select a backend type: 1) SSH 2) Exec (local) Select number: 2 + spec/ + spec/localhost/ + spec/localhost/sample_spec.rb + spec/spec_helper.rb + Rakefile + .rspec -----------------------------------
./test/integration/provisioning/rspec/Gemfilesource 'https://rubygems.org' gem 'serverspec'
./test/integration/provisioning/rspec/spec/localhost/provisioning_spec.rbrequire 'spec_helper' enable_service = %w(acpid auditd crond ip6tables iptables kdump mdmonitor netfs network nfslock ntpd ntpdate rpcbind rpcgssd rsyslog sshd sysstat udev-post vboxadd vboxadd-service vboxadd-x11) unable_service = %w(htcacheclean netconsole nfs postfix rdisc restorecond rpcsvcgssd saslauthd svnserve) enable_service.each do |service| describe service("#{service}") do it { should be_enabled.with_level(3) } end end unable_service.each do |service| describe service("#{service}") do it { should_not be_enabled.with_level(3) } end end command("rpm -qai |grep Name |grep Relocations |awk '{print $3}'").stdout.each_line do |pkg| describe package("#{pkg.chomp}") do it { should be_installed } end end describe command('ls -al /') do its(:stdout) { should match /bin/ } end describe file('/etc/passwd') do it { should be_file } end describe file('/var/log/httpd') do it { should be_directory } end describe file('/etc/httpd/conf/httpd.conf') do its(:content) { should match /^#ServerName www\.example\.com\:80$/ } end describe file('/') do it { should be_mounted } end command("awk -F\":\" '{ print $1}' /etc/passwd").stdout.each_line do |user| describe user("#{user.chomp}") do it { should exist } end end command("awk -F\":\" '{ print $1}' /etc/group").stdout.each_line do |group| describe group("#{group.chomp}") do it { should exist } end end describe interface('eth0') do it { should exist } end
- test-kitchen + kitchen-vagrant + kitchen-ansible で利用するもの
実行時間の計測方法
test-kitchen を利用して実行時間を計測する
-
VagrantでVMを起動するだけ
- => kitchen create
kitchen_createkitchen create
-
VagrantでVMを起動してAnsibleのPlaybookを実行する
- => kitchen create => kitchen setup
kitchen_setupkitchen setup
-
VagrantでVMを起動してAnsibleのPlaybookを実行してServerspecでテストを実施する
- => kitchen create => kitchen setup => kitchen verify
kitchen_testkitchen test --destroy=never
最初の状態
-
計測結果
kitchen_create1回目: Kitchen is finished. (3m20.09s) 2回目: Kitchen is finished. (2m5.09s) 3回目: Kitchen is finished. (1m57.72s)
kitchen_setup1回目: Kitchen is finished. (14m19.28s) 2回目: Kitchen is finished. (10m6.04s) 3回目: Kitchen is finished. (10m17.32s)
kitchen_test1回目: Kitchen is finished. (12m41.69s) => Finished verifying <provisioning-centos6> (1m45.20s). 2回目: Kitchen is finished. (12m31.62s) => Finished verifying <provisioning-centos6> (1m41.59s). 3回目: Kitchen is finished. (12m15.51s) => Finished verifying <provisioning-centos6> (1m45.45s). # kitchen verify によるテストの部分だけに限れば、 1m40s ~ 1m45s くらい
-
課題 (2015/03/02の時点では)
- kitchen_create / kitchen_setup / kitchen_test 共通
- vagrant-vbguest プラグインによって、 VirtualBox Guest Additions がアップデート (4.3.22) されている
- 依存しているパッケージファイルのアップデート
- 旧バージョンをアンインストール
- 新バージョンをインストール
- vagrant-vbguest プラグインによって、 VirtualBox Guest Additions がアップデート (4.3.22) されている
- kitchen_setup / kitchen_test 共通
- kitchen-ansible プラグインによって、 Ansible がインストールされている
- yum に epel リポジトリを追加
- epel リポジトリのメタデータをキャッシュする
- Python などの依存しているパッケージファイルをインストール
- Ansible のインストール
- test-kitchen によって Chef がインストールされている
- オムニバスインストーラーが実行されている
- thor がインストールされている
- busser がインストールされている
- kitchen-ansible プラグインによって、 Ansible がインストールされている
- kitchen_test
- bundle install が実行されている
- ./test/integration/provisioning/rspec/Gemfile によって Serverspec などがインストールされている
- bundle install が実行されている
- kitchen_setup
- Ansible が ./provisioning.yml から yum groupinstall -y 'Development tools' を実行している
- yum リポジトリからメタデータをダウンロードしている
- Ansible が ./provisioning.yml から yum groupinstall -y 'Development tools' を実行している
- kitchen_create / kitchen_setup / kitchen_test 共通
test-kitchen 専用の Vagrant Box Image を作成する
-
Vagrant Box Image に chef をオムニバスインストールする
-
chef/vagrant-omnibus
- VM の Chef インストール状況を確認し、必要に応じて自動的にインストールしてくれるプラグイン
インストールvagrant plugin install vagrant-omnibus
-
chef/vagrant-omnibus
-
Vagrant Box Image を作成するための Vagrantfile を用意する
./vagrant_package/VagrantfileVagrant.configure('2') do |c| ## Vagrant Box Base Image c.vm.box = "hansode/centos-6.6-x86_64" ## Plugin if Vagrant.has_plugin?("vagrant-omnibus") c.omnibus.chef_version = :latest end ## Provision c.vm.provision "shell",inline: "yum clean all && yum update -y && yum install -y libyaml" c.vm.provision "shell",inline: "rpm -ivh http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm" c.vm.provision "shell",inline: "yum install -y ansible" c.vm.provision "shell",inline: "yum clean all" c.vm.provision "shell",inline: "sh -c 'BUSSER_ROOT=\"/tmp/busser\" GEM_HOME=\"/tmp/busser/gems\" GEM_PATH=\"/tmp/busser/gems\" GEM_CACHE=\"/tmp/busser/gems/cache\" ; export BUSSER_ROOT GEM_HOME GEM_PATH GEM_CACHE; if ! sudo -E /opt/chef/embedded/bin/gem list busser -i >/dev/null; then sudo -E /opt/chef/embedded/bin/gem install busser serverspec --no-rdoc --no-ri; fi; gem_bindir=`/opt/chef/embedded/bin/ruby -rrubygems -e \"puts Gem.bindir\"`; sudo -E ${gem_bindir}/busser setup; sudo -E /tmp/busser/bin/busser plugin install busser-rspec'" end
-
Vagrant Box Image を作成する
boxイメージの作成コマンドと登録コマンドの実行cd ./vagrant_package vagrant up vagrant reload vagrant halt vagrant package vagrant box add -f libero18/test-kitchen ./package.box rm -f ./package.box vagrant destroy -f cd .. # libero18/test-kitchen は任意の名前で登録済みのものは、 vagrant box list で確認可能
-
作成した Vagrant Box Image を test-kitchen から利用する
./.kitchen.yml--- driver: name: vagrant provision: true vagrantfiles: - ./Vagrantfile.rb box: libero18/test-kitchen vm_hostname: kitchen-vagrant customize: cpuexecutioncap: 90 memory: 2048 provisioner: name: ansible_playbook platforms: - name: centos6 suites: - name: provisioning provisioner: hosts: kitchen-vagrant playbook: provisioning.yml
-
計測結果
kitchen_create1回目: Kitchen is finished. (0m57.50s) 2回目: Kitchen is finished. (0m59.78s) 3回目: Kitchen is finished. (0m53.06s)
kitchen_setup1回目: Kitchen is finished. (2m43.31s) 2回目: Kitchen is finished. (2m42.10s) 3回目: Kitchen is finished. (2m58.98s)
kitchen_test1回目: Kitchen is finished. (2m59.55s) => Finished verifying <provisioning-centos6> (0m25.64s). 2回目: Kitchen is finished. (3m11.04s) => Finished verifying <provisioning-centos6> (0m25.00s). 3回目: Kitchen is finished. (3m3.56s) => Finished verifying <provisioning-centos6> (0m25.15s). # kitchen verify によるテストの部分だけに限れば、 0m25s ~ 0m26s くらい
-
この段階での残課題 (2015/03/02の時点では)
-
kitchen_create / kitchen_setup / kitchen_test 共通-
vagrant-vbguest プラグインによって、 VirtualBox Guest Additions がアップデート (4.3.22) されている依存しているパッケージファイルのアップデート旧バージョンをアンインストール新バージョンをインストール
-
-
kitchen_setup / kitchen_test 共通-
kitchen-ansible プラグインによって、 Ansible がインストールされているyum に epel リポジトリを追加epel リポジトリのメタデータをキャッシュするPython などの依存しているパッケージファイルをインストールAnsible のインストール
-
test-kitchen によって Chef がインストールされているオムニバスインストーラーが実行されているthor がインストールされているbusser がインストールされている
-
-
kitchen_test-
bundle install が実行されている./test/integration/provisioning/rspec/Gemfile によって Serverspec がインストールされている
-
- kitchen_setup
- Ansible が ./provisioning.yml から yum groupinstall -y 'Development tools' を実行している
- yum リポジトリからメタデータをダウンロードしている
- Ansible が ./provisioning.yml から yum groupinstall -y 'Development tools' を実行している
-
パッケージ管理システムのメタデータなどをホストにキャッシュして VM とディレクトリ共有する
-
インストール
vagrant plugin install vagrant-cachier
-
test-kitchen から作成した VM で vagrant-cachier プラグインを利用するように設定を追加する
./Vagrantfile.rbVagrant.configure('2') do |c| ## Plugin if Vagrant.has_plugin?("vagrant-cachier") c.cache.scope = :box end end
-
計測結果
kitchen_create1回目: Kitchen is finished. (1m0.70s) 2回目: Kitchen is finished. (0m58.51s) 3回目: Kitchen is finished. (0m58.22s)
kitchen_setup1回目: Kitchen is finished. (2m24.12s) 2回目: Kitchen is finished. (2m22.79s) 3回目: Kitchen is finished. (2m26.45s) # 数値のみで判断すると誤差と言える程度だが、ネットワークやリポジトリの影響でダウンロード時間にバラツキが出ないことが最大のメリット
kitchen_test1回目: Kitchen is finished. (2m49.35s) => Finished verifying <provisioning-centos6> (0m25.15s). 2回目: Kitchen is finished. (2m45.61s) => Finished verifying <provisioning-centos6> (0m23.86s). 3回目: Kitchen is finished. (2m46.16s) => Finished verifying <provisioning-centos6> (0m24.27s). # テスト時間の短縮化について、 vagrant-cachier プラグインの導入による影響はない
-
この段階での残課題 (2015/03/02の時点では)
-
kitchen_create / kitchen_setup / kitchen_test 共通-
vagrant-vbguest プラグインによって、 VirtualBox Guest Additions がアップデート (4.3.22) されている依存しているパッケージファイルのアップデート旧バージョンをアンインストール新バージョンをインストール
-
-
kitchen_setup / kitchen_test 共通-
kitchen-ansible プラグインによって、 Ansible がインストールされているyum に epel リポジトリを追加epel リポジトリのメタデータをキャッシュするPython などの依存しているパッケージファイルをインストールAnsible のインストール
-
test-kitchen によって Chef がインストールされているオムニバスインストーラーが実行されているthor がインストールされているbusser がインストールされている
-
-
kitchen_test-
bundle install が実行されている./test/integration/provisioning/rspec/Gemfile によって Serverspec がインストールされている
-
-
kitchen_setup-
Ansible が ./provisioning.yml から yum groupinstall -y 'Development tools' を実行しているyum リポジトリからメタデータをダウンロードしている
-
-
その他
上記のやり方では Ansible および Serverspec は、ローカルモードで実行されるため SSH 経由で実行する場合には意味がないので、その場合は以下のようなものを試してみると良さそう
ただし、個人的には test-kitchen/kitchen-vagrant の代わりに test-kitchen/kitchen-ec2 や test-kitchen/kitchen-digitalocean などの driver を使ってリモートのインスタンスを相手に実行できる仕組みに変えた方が開発環境としては幸せだと思うのでここでの細かい説明などは省略
-
Ansible
- 並列化
- 転送速度の最適化
- pipelining => SSH 経由の場合は必須なレベル
-
Serverspec