vagrant + ansible + digitalocean で最強テスト環境を構築

[

表題の件、最近のお気に入りです。
しかも安い。早い。うまい。と3拍子そろっています。


DigitalOceanのデータセンターはシンガポール(2014年9月現在)、ディスクは、SSD 20GB のため国内サーバとパフォーマンスは遜色ないです。今回紹介する構築手順をためすのに1ドルほどしかかかってません。

唯一の弱点はドロップレットと呼ばれるAWSでいうEC2インスタンスが一つしか作成できないこと。
(いちおう理由を申請すれば複数のドロップレットを起動できるようにしてもらえるらしいが、デジタルじゃないおぉ。)

あと、いまのところsnapshotが無料です。

最近ガシガシ開発することはないんだけど、カリカリのプログラマさんだけでなく、
デザイナーさんやディレクターさんなど、エンジニア以外の人にとってもこれは便利なんじゃないかと思います。

というわけで、vagrant経由でansibleを使ってprovisioningを行い、Virtual Host を使った主要CMSの開発環境を
作成してみましたので、かいつまんで説明します。

CentOS 6.5に
CMS: wordpress, movabletype, drupal

をインストールするというシナリオです。
また、おまけで Varnish もインストールします。
作業はMBPで行っています。


1. Vagrant + DigitalOceanの環境をセットアップ


このあたりを参照すれば問題なくいけるでしょう。
http://blog.glidenote.com/blog/2013/12/05/digital-ocean-with-vagrant/
http://qiita.com/msykiino/items/d45cab7f520a3288862a

ただ、DigitalOceanのAPIが新しくなって少しはまったところだけここに貼付けておきます。
少し前は、api_key をつかっていたのが、tokenを使うようになっています。

$cat Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Dotenv.load

# change default provider to digital_ocean
ENV['VAGRANT_DEFAULT_PROVIDER'] = "digital_ocean"

# 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.provider :digital_ocean do |provider, override|
    override.vm.hostname          = "vagrant-do"
    override.vm.box               = "digital_ocean"
    override.vm.box_url           = "https://github.com/smdahlen/vagrant-digitalocean/raw/master/box/digital_ocean.box"
    override.ssh.username         = ENV['DO_SSH_USERNAME']
    override.ssh.private_key_path = ENV['DO_SSH_KEY']

    provider.token                = ENV['DO_API_TOKEN']
    provider.region               = "sgp1"    
    provider.image                = "CentOS 6.5 x64"
    provider.size                 = "512MB" # 512MB | 1GB | 2GB | 4GB | 8GB | 16GB 
    provider.private_networking   = true
    provider.ca_path              = "/usr/local/share/ca-bundle.crt"
    provider.setup                = true
    provider.ssh_key_name         = ENV['DO_SSH_KEYNAME']

    # disable synced_folder: rsync is not installed on DigitalOcean's base image
    override.vm.synced_folder "./", "/vagrant", disabled: true

  end

  config.vm.provision "ansible" do |ansible|
      ansible.sudo = true
      ansible.playbook = "./provision/vagrant.yml"
  end
  config.ssh.forward_agent = true

end


ちなみにvagrantディレクトリ構成は下記のような感じです。
はじめはansibleのお作法をちゃんと勉強するのが面倒で単一のplaybook.ymlに書いていましたが、
vagrantで複数のplaybookを実行するために、お作法にのっとってフォルダ分けしました。
こっちのほうが、整理できててよいですね。


├── README.md
├── Vagrantfile
├── ansible.cfg
└── provision
├── common
│   ├── handlers
│   ├── tasks
│   │   └── main.yml
│   ├── templates
│   │   ├── common.conf.j2
│   │   ├── htaccess.j2
│   │   └── simpleweb.conf.j2
│   └── vars
│   └── main.yml
├── drupal
│   ├── handlers
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   ├── templates
│   │   └── drupal.conf.j2
│   └── vars
│   └── main.yml
├── mt
│   ├── handlers
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   ├── templates
│   │   ├── mt-readme.html.j2
│   │   └── mt.conf.j2
│   └── vars
│   └── main.yml
├── vagrant.yml
├── varnish
│   ├── handlers
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   ├── templates
│   │   ├── default.vcl
│   │   └── etc-sysconfig-varnish
│   └── vars
│   └── main.yml
└── wordpress
├── handlers
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
│   ├── wordpress.conf.j2
│   └── wp-config.php.j2
└── vars
└── main.yml


2. ansibleのplaybookを書いていきます。

$ cat provision/vagrant.yml

- hosts: all
  roles:
          - common
          - wordpress
          - drupal
          - mt
          - varnish

簡単に説明しておくと、
common, wordpress, drupal, mt , varnish の順にplaybookを実行することを定義しています。
ちなみに commonではhttpdなど共通ミドルなどをインストールしていますが、
各playbookが単体でも動くように、冗長に記述しました。

commonのplaybookを抜粋すると、

  • yumのパッケージをすべてアップデート
  • epelのレポジトリを設定
  • htpasswd ファイルを作成するために、python-passlibをインストール
  • httpd をインストール
  • ドキュメントルートを作成
  • vhostの設定を反映

といったことをしています。

- name: upgrade all yum packages
  yum: name=* state=latest

- name: get epel-repo rpm RHEL6
  get_url: dest=/tmp/epel-release.rpm  url=http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm

- name: install epel-repo rpm
  yum: pkg=/tmp/epel-release.rpm state=installed

- name: be sure python libraries are installed
  yum: name={{item}} state=installed
  with_items:
         - python-passlib

- name: be sure httpd is installed
   yum: name=httpd state=latest

- name: create document root
  file: dest={{ work_dir }} state=directory owner=apache group=apache mode=0755

- name: be sure httpd is configured
  template: src=common.conf.j2 dest=/etc/httpd/conf.d/common.conf


何となくみていると、どういうことができるのかパッとわかるのではないでしょうか。
サーバセットアップに必要な大概のことはansibleのコマンドで実現可能ですので、
独自にスクリプトを組んだりといった必要がありません(なんて透明性なんでしょう!)。

MovableTypeのようにたくさんのCPAN モジュールに依存している場合は
セットアップ手順などをちまちま作るのはとても面倒です。
プレイブックとして記述しておけると手順書として納品物としてしまっても良い気が個人的にはしています。


template コマンドが中でも便利で、vars/main.yml に定義された変数をsrcファイルに適用したうえで、dest で指定されたパスに反映してくれます。ステキ。

その後、wordpressなどのCMSインストールを実行します。
昨今のOSSはたいていgitレポジトリにあるので、そちらをcloneしてビルドするのが簡単で、必要に応じて、タグを指定して希望のバージョンを自由にインストールことも可能です。


また、wordpressでは、下記のようにgit clone でいっぱつインストールできます。

- name: download wordpress package
  git : repo=https://github.com/WordPress/WordPress.git dest="{{docroot}}" version={{version}}

楽ちんですね!


3. プレイブックが書けたら、vagrant upします。

$ vagrant up --provider=digital_ocean --provision


さらに、これをJenkinsから行えるようにすれば、クリップ一発で好きな環境を
立ち上げることができます。


便利な世の中になったものです。ホント。
今回作成したplaybookは整理できたらgithubにでもアップしようかと思います。


4. いざサイトにアクセス

私の場合、MBPのhostsに

128.199.xxx.xx   default-do	default-do
128.199.xxx.xx   mt-do	mt-do
128.199.xxx.xx   drupal-do	drupal-do
128.199.xxx.xx   wordpress-do	wordpress-do


に書いて、アクセスできるようにしています。




Ansible is usable!
Enjoy!