本エントリの目的
ローカル環境で開発をしているとデータベースやその他諸々のサービスをlocalhostで参照できて設定が楽というメリットはありますが、WebサーバとDBサーバの分かれた本番環境と構成が異なるのが気になります。
せめて本番にデプロイする前にステージング環境で確認をしておきたいところですが、個人開発ではお金を節約したいのでわざわざ本番サーバと同じVPSやAWSは使いたくありません。そこでVirtualboxの仮想マシンにVagrantとAnsibleを使って環境を構築することにします。
- Virtualbox、Vagrant、Ansibleのインストール方法、使い方などは説明しません。
- 使用したファイルはGithubに上げています。
環境
- ホストマシン: MacOSX El Capitan
- Vagrant v1.9.1
- Ansible v2.0.2.0
- Virtualbox v5.0.24 r108355
仮想マシン構成・要件
仮想マシン構成
- Webサーバ
- DBサーバにアクセス可能
- DBサーバ
- mysqlを稼働
- Webサーバからアクセス可能
上記2サーバを"ゲスト"と呼ぶのに対し、仮想環境を構築するマシンを"ホスト"と呼びます。
要件
- ホストはゲストにSSH接続可能
- DBサーバのDBにもアクセス可能
- ゲストWebサーバのポート80はポートフォワーディングでホストから接続可能
- 要はWebサーバで動かしているアプリをホストのブラウザから見られるようにする
- サーバ構築はAnsibleで行う
ディレクトリ構成
- Vagrantfile
-
groupvars
- all.yml
-
roles
- mysql
- staging // inventoryファイル
- site.yml // vagrantから実行するplaybook
- dbservers.yml // DBサーバ用playbook
Vagrantfileはディレクトリでvagrant init
コマンド実行で作成されるものです
その他はansibleで使用するファイルですが、このあたりの構成は人によって異なると思います。
今回ansibleはDBサーバにmysqlを立てるためにしか使わないのでだいぶ簡略化しています。
groupvars/all.ymlにはmysqlのユーザ作成に使用するための値を設定しています。
roles/mysqlはこちらのリポジトリから拝借して自分用に適当に改変したものです。
ともかく、ansibleファイルの構成はinventoryファイルを本番環境用のものに差し替えればそのまま同じように実行できることが重要だと思います。
VagrantFileの記述
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
VAGRANT_VM_PROVIDER = "virtualbox"
machineNames = ["example.com.web", "example.com.db"]
config.vm.box = "centos/7"
N = 1
(0..N).each do |index|
config.vm.define machineNames[index] do |machine|
# 仮想マシンのネットワーク設定
machine.vm.hostname = machineNames[index]
machine.vm.network "forwarded_port", guest: 80, host: 10020 + index, guest_ip: "192.168.33.#{10+index}"
machine.vm.network "private_network", ip: "192.168.33.#{10+index}", virtualbox__intnet: "example.com"
machine.vm.network "private_network", ip: "192.168.33.#{10+index}"
# ansibleでのprovisioning. ループの最後で実行される
if index == N
machine.vm.provision :ansible do |ansible|
ansible.limit = "all"
ansible.playbook = "site.yml"
ansible.inventory_path = "staging"
end
end
end
end
end
Vagrantのドキュメントを参考にループを回してWeb, DBサーバそれぞれに異なるIPアドレスを割り当てています。
仮想マシンのネットワーク設定の部分ではゲストで実行するアプリをホスト側で確認するためのforwarded_port、仮想マシン間で通信するためのprivate_networkを設定しています。
Vagrant up してみる
ansible以外の仮想マシン構築タスクがうまく動作確認するためにとりあえず vagrant up
してみましょう。Vagrantとansibleを使うと途中でエラーになっても再実行が簡単なので楽です。
Vagrantによる仮想マシン構築はうまく行ったのでansibleのタスクだけ実行したいという場合は vagrant provision
コマンドが使えます。
なんか変になったので仮想マシンごと削除したい場合は vagrant destroy
コマンドです。一回のコマンドで各サーバについて削除するか聞かれます。
example.com.db: Are you sure you want to destroy the 'example.com.db' VM? [y/N] y
==> example.com.db: Forcing shutdown of VM...
==> example.com.db: Destroying VM and associated drives...
example.com.web: Are you sure you want to destroy the 'example.com.web' VM? [y/N] y
==> example.com.web: Forcing shutdown of VM...
==> example.com.web: Destroying VM and associated drives...
vagrant destroy example.com.web
のように指定することも可能です。
ホストでWebアプリの稼働を確認する
疎通確認のためワンライナーでサーバを起動します。
ポート80を指定しているのはVagrantfileでforwarded_portにしているからです。
# Webサーバで実行
sudo python -m SimpleHTTPServer 80
ホストのブラウザで http://localhost:10020 にアクセスしてみます。
ホストからDBに接続する
Sequel ProからDBに接続するときの設定です。
SSH Keyには.vagrantフォルダ配下にあるキーを指定します。
.vagrant/machines/example.com.db/virtualbox/private_key
ゲストサーバ間でアクセスする
Vagrantfileのprivate_networkに指定したipアドレスでアクセスすることができます。
とりあえず簡易的にpingが通るかどうかで確認してみます。
トラブルシューティング
本エントリの元にした個人プロジェクト用環境をセットアップしたときはなかったのですが、記事を執筆するために手順を再現しているとうまくいかないことがありました。詳しくないので原因ははっきりしていません。
1. ホストのブラウザから localhost:10020 につながらない
まずVirtualboxのマシン一覧からWebサーバ → setting → network → Adaptor3 を確認します。
ここで指定されているNetwork Adaptor(ここではvboxnet4)をVirtualboxの環境設定で確認します。
上の画像は問題が解決したあとの設定です。解決する前はvboxnet4のIPv4 Addressが別の値になっていました(記録し忘れました)。
2. ゲストサーバ間でpingが通らない
原因ははっきりしませんが再起動をかけると直ったりします。