vagrant + fabric + cuisineで開発環境を自動生成する
はじめに
9/28のDevOps Days Tokyo 2013に参加してきた。
Vagrantをつかってみた というエントリだけでやりっ放しにするのはかっこよくないし、ブログを書くまでがDevOps Daysと幹事の方も言っていたので(意味が違う)、vagrant + fabric + cuisineを使って開発環境を自動生成してみる。
DevOps Days TokyoではChefの話が多かったのだけど、こんなエントリ書いておきながらRubyはまだしっくりきていないし、Pythonのシンプルさが好みなので、Chef-SoloっぽいことができるPythonのライブラリを探してみると fabric というものがあるらしい。
そして、Chefといえば冪等性(何回同じ操作をしても同じ結果になること)だけど、cuisine を組み合わせれば冪等性が少しは担保できるらしい。
目的
- Mac Book Air上に Ubuntu-12.04 LTSの仮想環境が5分で導入できること
- AWSでもUbuntuを使っているので将来見据えて
- git clone + vagrant up の2コマンドで完了できること
- ついでだから Apache + Python (WSGI) でサンプルが動いていると面白い
- 自分はApache厨なので
やってみた
下準備
まずは、Virtual Box/vagrantの確認をしておく。以前、vagrantはruby gemでインストールしていたけれども、いまは Vagrant Downloads からダウンロードすればいい、楽チン。
Virtual Box: 4.2.0
vagrant: 1.3.3
Ubuntu自体は用意されているboxをそのまま利用
$ vagrant box add ubuntu-12.04 http://files.vagrantup.com/precise64.box $ vagrant box list ubuntu-12.04
fabricとcuisineのインストール
pipが入ってなければ、 sudo easy_install pip
でインストールする。
easy_installだとインストールパッケージ一覧を出すのがしんどいし、pipの方が今風だからこっちにする。
$ sudo pip install fabric $ vagrant plugin install vagrant-fabric $ sudo pip install cuisine
Vagrantfile の記載
srcとvagrantディレクトリを作り、vagrantディレクトリの中で vagrant init <box名>
を実行する。実行するとVagrantfileができる。
$ mkdir src vagrant (srcは後述のsynced_folderのところで使い道がある) $ cd vagrant $ vagrant init ubuntu-12.04
以下のようにVagrantfileを書き換える
# -*- mode: ruby -*- # vi: set ft=ruby : VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| # box名 config.vm.box = "ubuntu-12.04" # ローカル環境でIPが使えるようにする config.vm.network :private_network, ip: "192.168.33.10" # synced_folder (親ホストのVagrantfileから見た時の ../src を 仮想環境の /src に割り当てる config.vm.synced_folder "../src", "/src", create: true, owner: 'vagrant', group: 'vagrant', mount_options: ['dmode=777,fmode=666'] # プロビジョニング(パッケージの追加や設定の反映) # provision.py に記載した setup メソッドを実行する config.vm.provision :fabric do |fabric| fabric.fabfile_path = "./provision.py" fabric.tasks = ["setup"] end end
synced_folder
親ホストのディレクトリを仮想ホストのディレクトリを共有する仕組み。
開発は親ホスト上のお好きなエディタやIDEで実施し、仮想サーバで実行することができる。
config.vm.synced_folder "../src", "/src", create: true, owner: 'vagrant', group: 'vagrant', mount_options: ['dmode=777,fmode=666']
例えば前述のVagrantfileに記載した内容の場合、下記のような共有ディレクトリが生成される。
- 親ホストの ../src ディレクトリ(Vagrantfileからみて) と 仮想サーバの /src を共有する
- 仮想サーバに /src が存在しなければ生成する(create: trueのところ)
- ディレクトリオーナーとグループは vagrant にし、パーミッションは777、生成されるファイルのパーミッションは666になる。
ちなみにVagrantfileが設置されるディレクトリは自動的に synced_folder となり仮想サーバの方では /vagrant というディレクトリで参照できる。
なお、synced_folder については、下記記事が分かりやすかった。
プロビジョニングを記載する
Vagrantfileのコメントにも記載している通り、provision.py にプロビジョニングを記載する。
cuisine の *_ensure あたりを使うと冪等性が担保できるし、file I/Oをうまく使えばかなりの割合で冪等なプロビジョニングができると想像できる(sudoでコマンドを流すのは便利だが冪等性を担保しにくくなる。)
from fabric.api import run from fabric.api import sudo from fabric.utils import puts from fabric.colors import red, green from fabric.context_managers import * import cuisine cuisine.select_package("apt") def setup(): _setup_ubuntu() _setup_devtools() _setup_packages() _configuration_apache2() _restart_daemons() # 初期設定系(なんとなく) def _setup_ubuntu(): puts(green('Setting Operation System')) sudo("cp /usr/share/zoneinfo/Japan /etc/localtime") sudo("apt-get update") # 開発パッケージ系 # cuisine.package_ensure がいい感じ def _setup_devtools(): puts(green('Installing Devtools')) cuisine.package_ensure('vim') cuisine.package_ensure('python-setuptools') # アプリケーション def _setup_packages(): puts(green('Installing Packages')) cuisine.package_ensure('libapache2-mod-wsgi') cuisine.package_ensure('apache2-mpm-worker') # Apache2の設定 # 折角なので Apache設定ファイルを file_write で書き込み # 設定ファイルの有効化とreloadをfabricのsudoで実行してみた def _configuration_apache2(): if not cuisine.file_exists('/etc/apache2/sites-enabled/hello'): cuisine.file_write( location = '/etc/apache2/sites-available/hello', content = "WSGIScriptAlias /hello /src/hello.py" "\n" "<Directory /src>\n" " SetHandler wsgi-script\n" "\n" " Order deny,allow\n" " Allow from all\n" "</Directory>\n", mode=None, owner=None, group=None, sudo=True ) sudo('a2ensite hello') sudo('/etc/init.d/apache2 reload') # デーモンの再起動 def _restart_daemons(): puts(green('Restarting Daemons')) cuisine.upstart_ensure('apache2')
../src
ディレクトリには、Apache + mod_wsgi で Hello world が出力されるような hello.py を設置する。
Vagrantfileとprovision.py の設定により、http://192.168.33.10/hello で hello.py が実行される。
def application(environ, start_response): status = "200 OK" response_headers = [("Content-type", "text/plain")] start_response(status, response_headers) return ["Hello world! (mod_wsgi)"]
仮想サーバを起動
vagrant up
を実行すれば、無事に仮想環境が立ち上がる。vagran ssh
でログインすることができる。
$ vagant up $ vagrant ssh or $ ssh vagrant@192.168.33.10 (pwはvagrant)
Vagrantの1.3.0からは、2回目以降の起動時にはプロビジョニングが実行されないので、2度目以降のupの場合は、下記を実行しなくてはならない。
$ vagant up --provision
親ホストの ../src ディレクトリで開発をすると、仮想サーバの /src 以下が自動的に変更されるので開発がらくちん。 ついでに../srcごとgithubにpushしちゃうとアプリケーション+仮想環境ごと複製できて飯がうまいうまい(ということで後述)
git(github)と連携する
githubに上げる時は、Vagrantfileと同じ場所に生成される .vagrant ディレクトリが追加されないように .gitignoreに記載することをお忘れなく(失敗すると面倒なことに)。
下記の通りに実行すると、仮想サーバを構築して Apache + PythonでHello worldが!
$ git clone https://github.com/mikanmarusan/vagrant.git vagrant $ cd vagrant/ubuntu/vagrant (ディレクトリ構成微妙) $ vagrant up
まとめ
- vagrantやっぱり便利
- fabricとcuisineを使うとchef-soloっぽいのができる(けどシェルの高機能版って感じもする)
- githubと連携できるとどこにいても同じ環境が作れる。