EagleLand

2015.01.10

VagrantでCentOSの仮想環境を作ってAnsibleで遊ぶ

Vagrantは今更説明するまでもないけど、仮想環境の作成や起動・破棄を自動化したりするツール。VagrantはChefやAnsibleといったようなプロビジョニングツールとも連携可能なのでそれも少し。

Vagrantで仮想環境を作る

自身には仮想化する機能を備えておらず、仮想化ソフトウェアとしてVirtualBoxやVMWareなどを使う。今回はVagrant + VirtualBoxでCentOSの仮想環境を作ってみる。

以下のサイトに環境ごとのインストーラがあるので、ダウンロードしてインストールする。

CentOS 6のBoxファイルをダウンロード

今度はどのOSで仮想化するか決める。VagrantではOSイメージをBoxと呼ばれる形式で管理する。有志で配布されているBoxの一覧はVagrantbox.esにあるので、違うOSで試したい場合はそちらを。

# boxファイルのダウンロード
$ vagrant box add centos6 https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box

# Vagrantに保持されてるboxのリスト
$ vagrant box list

# ダウンロードしてきたcentos6を使って初期化
$ vagrant init centos6

centos6というキーに対して.boxファイルが紐づいて、そのダウンロードしてきたBoxファイルでVagrantプロジェクトの初期化をしている。これでVagrantfileが作成され、仮想環境の起動の準備が完了してしまう。簡単すぎる。

起動と終了と削除と仮想環境へのログイン

起動と終了はuphaltで行う。起動するとデフォルトだと2222ポートで仮想環境が立ち上がり、VirtualBoxを見るとインスタンスが追加されているのが確認できる。

# 仮想環境の起動
$ vagrant up

# 仮想環境の終了
$ vagrant halt

# 仮想環境の終了と削除
$ vagrant destroy

ログインはsshコマンド。vagrantユーザーでログインし、もちろんルートにもスイッチできる。sudo su -とか。

# 仮想環境へSSHログイン
$ vagrant ssh

Vagrantfileの中身

vagrant initで作成されたファイルは設定可能な箇所が色々とコメントアウトされている。コメントアウトされている内容が、各項目の初期値におおよそなっている。以下は抜粋。

Vagrant.configure(2) do |config|
  # vagrant box addで取得したboxの指定
  config.vm.box = "centos6"

  # ローカルの8080へのアクセスが仮想環境の80へポートフォワードされる
  config.vm.network "forwarded_port", guest: 80, host: 8080

  # 仮想環境のプライベートIPアドレスを指定
  config.vm.network "private_network", ip: "192.168.33.10"

  # 仮想環境に同期(マウント)させたいローカル環境のディレクトリ
  # デフォルトでカレントディレクトリが仮想環境の/vagrantにマウントされる
  # config.vm.synced_folder "../data", "/vagrant_data"
end

ここまで出来たら、仮想環境にログインして、煮るなり焼くなりしてOK。間違えて環境を壊しても、vagrant destroyで削除して、指定したBoxとVagrantfileでの設定までは何度でも適用できる。

詳しい設定は公式ドキュメントをどうぞ。

Ansibleでプロビジョニング

プロビジョニングにはAnsibleを使ってみる。AnsibleはHomebrewなどでインストールしておくこと。

$ brew install ansible

プロビジョニングツールとしてはChefやらPuppetやらもあって、それらとも連携出来る。ChefとAnsibleの両方を使ったの感想として、ChefはRubyのコードベースで色々出来るので設定の自由度等は高いけど、学習コスト高め且つ設定等も複雑で膨らみがちな印象。Ansibleは、YAMLでコマンドラインベースの命令を設定するので、シンプルでわかりやすかった。僕はインフラ屋じゃないので、使い込む必要性を問われていないっていう背景はありつつ、やった範囲ではAnsibleで出来ないことがなかったのでAnsibleの感触が良かったっていうだけ。Chefがイケてないとかではない。

VagrantfileでAnsibleを使う準備

ホスト名の指定config.vm.hostnameと、プロビジョニングの設定をconfig.vm.provisionに書いている。Ansibleにおいて指定環境に適用させたい設定はプレイブックと呼ばれ、ここではvagrant-centos6.ymlとしておく。ansible.inventory_pathにはhostsというファイル名を指定しているが、設定を適用させるホストを列挙したインベントリーファイルというものになる。hostsという名前でなくとも良い。

Vagrant.configure(2) do |config|

  config.vm.box = "centos6"
  config.vm.hostname = "vagrant-centos6"

  config.vm.network "forwarded_port", guest: 80, host: 8080
  config.vm.network "private_network", ip: "192.168.33.10"

  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "vagrant-centos6.yml"
    ansible.inventory_path = "hosts"
    ansible.limit = "all"
    ansible.verbose = "v"
  end

end

インベントリーファイル

今回はhostsというファイル名で、以下のようにVagrantで用意した仮想環境のホスト名を指定した。

[vagrant-centos6]

192.168.33.10

プレイブック

vagrant-centos6.ymlの中身は以下のようになっている。

- hosts: vagrant-centos6

  sudo: yes
  tasks:
    - debug: This is a message in tasks
  roles:
    - common

hostsは適用先のホスト名で、sudoは管理者実行するかどうか。設定の実行はtasksないし、それらを分割管理するrolesという属性に指定する。tasksには実行したいことをシェルっぽく書ける。yumを実行したいのであれば、以下の様な雰囲気。

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

タスクを羅列するだけでも良いけど、項目ごとに単位化したくなるのがエンジニアの性なので、rolesを使う。今回はcommonというロールを作った。このロールの構成には、roles/common/tasksというフォルダ階層が要る。その中に、実行のエントリポイントとなるmain.ymlを配置するだけ。このmain.ymltasksと同じ要領で記述出来る。

Ansibleとしては、他のタスクをインクルード出来たり、変数宣言等が可能。詳細は公式サイトを確認してください。

また、今回やったような最低限の連携を少し応用して、WebPageTestを仮想環境に立てるサンプルが1000ch/webpagetest-localに置いてある。と、言っても、テストエージェントとの疎通まではしておらず、Webアプリ側だけ閲覧可能というだけだけど、悪しからず。