<akagisho@gmail.com>
Sep. 10, 2015
Ansible ではじめる
インフラのコード化入門
• Ansible、Vagrant、Serverspec などを用いた 「インフ
ラ ※ のコード化」 手法について、初心者向けに解説
します。
概要
※ インフラ: 今回は 「サーバインフラ」 のこと。
2
• 環境
• 開発環境: OS X or Linux
• 本番環境: Linux
• 各種ツールのインストール手順は省略します。
• Ansible, Vagrant, VirtualBox etc.
前提
3
こんな人向け
サーバ構築職人の朝は早い。
◯◯社で使われるサーバは、職人が一つ一つ手作業で構築している。
そのため日に数台が限度だという。
「まぁ好きではじめた仕事ですから」
最近は手順が複雑だと愚痴をこぼした。
職人の一日は、まず手順書の入念なチェックから始まる。
「一つ一つ仕上がりに微妙な差が出る。機械では出来ない」
さりげなく語るが、そこには年季と、確たる信念が見えた。
4
インフラのコード化
5
サーバの構築どうやってますか?
6
インフラのコード化
• Infrastructure as Code
• サーバの “あるべき状態” をプログラミング言語な
どの “コード” で書くことにより、構築や更新を自動
化すること
• インストールするべきパッケージ
• 各種設定 etc.
• “構成管理ツール” を用いて実現する
7
インフラをコード化するメリット
• 手作業との決別
• あいまいな手順書の駆逐
• 構築、更新作業がスケール
• だれがやっても同じものができる
• 品質の担保、オペミスの低減
• 手順を再利用しやすい
• 手順をバージョン管理できる
8
構成管理ツール
• Infrastructure as Code を実現するためのフレーム
ワーク
Chef Puppet Ansible
言語 Ruby Ruby Python
書式 Ruby DSL ※1 外部 DSL ※2 YAML
エージェント 要 要 不要
冪等性 ◯ ◯ ◯
※1 DSL (Domain Specific Language): 特定の用途向けに設計された言語
※2 外部 DSL: つまり独自の書式
9
冪等性 (べきとうせい)
• 「ある操作を1回行っても複数回行っても結果が同
じである」 という数学的概念
• e.g.
• abs(x) == abs(abs(x)) == abs(abs(abs(x))) == ...
• 構成管理とどう関係が?
Wikipedia より引用: https://ja.wikipedia.org/wiki/冪等 10
構成管理における冪等性
• e.g.)
• 2回以上実行すると、都度追記される
• つまり意図した状態とならない
# echo “UseDNS no” >> /etc/ssh/sshd_config
11
∴ この処理には冪等性がない
構成管理における冪等性
• e.g.)
• 1回目: Nginx がインストールされる
• 2回目以降: インストール済みだと表示され、ス
キップされる
何回実行しても、実行後は
「nginx がインストールされている」
という状態
$ sudo apt-get install -y nginx
12
∴ この処理には冪等性がある
構成管理における冪等性
• 先に挙げたような構成管理ツールも、各操作にお
いて冪等性が保たれるように設計されている
• 何回実行しても OK
• 構成管理ツールは
「サーバを構築する」
というより
「サーバをあるべき状態に収束させる」
という考え方であるといえる
13
Ansible
14
Ansible
• Python 製の構成管理ツール
• エージェントレス
• 対象サーバに余計なものを入れなくて良い
• ただし使用する Ansible モジュールによっては、
Python モジュールに依存関係がある
• YAML で記述
• とっつきやすい
• ただし条件分岐や繰り返し処理をしづらい
• Ansible 2 で改良される気配
15http://docs.ansible.com/
Ansible
• 標準モジュールが充実
• よくある操作はだいたいできる
• 冪等性がある
• 一部モジュールでは例外あり
16
Ansible の動作要件
SSH
・UNIX or Linux
・Ansible
(・Python 2.6 or 2.7)
Control Machine
Managed Node
provisioning
17
鍵認証
パスなしで sudo
・sshd
・Python 2.5+
Ansible の各種ファイル
• Inventory (必須)
• 対象ホストを定義するファイル
• ここに書かれていないホストは操作できない
• 対象ホストを動的に指定することも可能
(Dynamic Inventory; 今回は説明しない)
• Playbook
• Ansible の動作を定義するファイル
18
Inventory
• 対象ホストを列挙するファイル (ini 形式)
mail.example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com ansible_ssh_port=10022
[all:vars]
ansible_ssh_user=provuser
ssh ユーザ、ポート番号、
秘密鍵などを指定可
ホストのグループ化
19
グループに対しても指定可
• 単一の Ansible モジュールを実行する
• e.g.
ansible コマンド
20
10.200.19.201 ansible_ssh_user=vagrant
hosts
$ ansible -i hosts -m command -a uptime all
10.200.19.201 | success | rc=0 >>
00:05:35 up 3 min, 1 user, load average: 0.17, 0.18, 0.08
モジュール名 引数
対象ホスト実行結果
• Ansible の動作を定義するファイル
• タスクを列挙
• タスク = モジュール + 引数
• タスクは上から順に実行
Playbook
Playbook
└ tasks
├ modules
└ arguments
---
- hosts: all
sudo: yes
tasks:
- name: ensure nginx is installed
apt: pkg=nginx state=latest
- name: ...
モジュール名
引数
対象ホスト
21
• Playbook を実行する
ansible-playbook コマンド
22
$ ansible-playbook -i hosts main.yml
PLAY [all]
********************************************************************
GATHERING FACTS
***************************************************************
ok: [10.200.19.201]
TASK: [ensure nginx is installed]
*********************************************
changed: [10.200.19.201]
PLAY RECAP
********************************************************************
10.200.19.201 : ok=2 changed=1 unreachable=0 failed=0
実行結果
Inventory Playbook
• もう1回実行すると…
ansible-playbook コマンド
23
$ ansible-playbook -i hosts main.yml
PLAY [all]
********************************************************************
GATHERING FACTS
***************************************************************
ok: [10.200.19.201]
TASK: [ensure nginx is installed]
*********************************************
ok: [10.200.19.201]
PLAY RECAP
********************************************************************
10.200.19.201 : ok=2 changed=0 unreachable=0 failed=0
変更が発生しなかったので
“changed=0” になった
実行結果
Inventory Playbook
モジュール (の一部) 紹介
24
モジュール名 内容
copy ローカルのファイルをリモートにコピーする。
file ファイルの属性や所有者などを設定する。
template
ローカルのテンプレートファイル (Jinja2) をリ
モートでビルドする。
lineinfile リモートのファイルに1行追記する。
apt, yum apt / yum モジュールを管理する。
mysql_db,
mysql_user
MySQL のデータベースやユーザを管理する。
command OS のコマンドを実行する。
shell シェルを実行する。
:
• 目的に合ったモジュールがなくても、これらを使え
ばほぼなんでもできる
• ただし冪等性は自分で考えなければいけない
• 複数回実行しても問題ない書き方を
• register, changed_when などを用いて、変更が
あったときのみ changed になるように
command, shell モジュールの注意点
25
- name: bundle install
shell: >
bundle install --path vendor/bundle
chdir=/var/www/hogeapp
register: result
changed_when: "'Installing' in result.stdout”
Best Practice
• Ansible の各種ファイルの配置パターン (ディレクト
リ構成) の例示
• 詳細は公式ドキュメントを参照
26http://docs.ansible.com/ansible/playbooks_best_practices.html
Vagrant
27
Vagrant
• 仮想環境の構築ツール
• 同じ構成の VM を簡単にたくさん作れる
• “Vagrantfile” で定義されたスペックの VM を自動
で生成
• VirtualBox などに対応
• 仮想環境をパッケージして “box” という単位で管理
28https://www.vagrantup.com/
Vagrant
• ディストリビューション公式から私製まで、様々な
box が公開されている
• Vagrantbox.es
• Vagrant Cloud
• vagrant コマンドで操作
29
Usage: vagrant [options] <command> [<args>]
vagrant コマンドの使い方
30
サブコマンド 内容
box add <title> <url> box イメージを取得
init <title> Vagrantfile を作成
up VM を起動
ssh VM にログイン
suspend VM を一時停止
resume VM を再開
destroy -f VM を破棄
snapshot take 
<vm_name> <snapshot_name>
スナップショットを撮る
snapshot go 
<vm_name> <snapshot_name>
スナップショットに戻す
:
vagrant コマンドの使い方
• e.g.) Ubuntu 14.04 を起動
1. Vagrantfile を作成
1. VM を起動
$ vagrant init ubuntu/trusty64
31
$ vagrant up
Vagrant Cloud 上の box を使うなら
{username}/{title}
これだけで何かしらの OS を起動できる
Vagrant with Ansible
• Vagrant は Ansible でのプロビジョニングに対応
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.define :node1 do |node|
node.vm.box = "ubuntu/trusty64”
node.vm.network :private_network, ip: "10.200.19.13"
end
config.vm.provision "ansible" do |ansible|
ansible.playbook = "site.yml"
ansible.groups = {
"webservers" => ["node1"]
}
ansible.extra_vars = "group_vars/all"
end
end
box 名
Playbook
グループとホストの紐付け
変数
Vagrantfile
32
Vagrant with Ansible
• で、初回起動時に自動でプロビジョニン
グを実行
• 2回目以降は で実行
vagrant up
vagrant provision
33
$ vagrant up
Bringing machine 'node1' up with 'virtualbox' provider...
==> node1: Importing base box 'ubuntu/trusty64'...
(略)
==> node1: Running provisioner: ansible...
(略)
PLAY RECAP
**************************************************************
node1 : ok=28 changed=26 unreachable=0 failed=0
実行結果
• 「Vagrant はわかった。オンプレや KVM 上での OS
インストールも自動化したい」
⇒ 以下のキーワードを調べよう
• PXE ブート, Kickstart, Preseed, Cobbler
• virt-install
• https://gist.github.com/akagisho/0f7fc8b05f78e1dc13bd
• uvtool
• https://gist.github.com/akagisho/5d958e46a9afcf443395
その他の自動化
34
ここまでのおさらい
Ansible
構成管理ツール。インフラのコード化、構築
自動化を実現できる。
Vagrant
仮想環境構築ツール。VirtualBox などの VM
を簡単に作れる。
35
Vagrantfile と Ansible の Playbook さえあれば
vagrant up だけで手元に環境を構築できる!
Serverspec
36
Serverspec
• Ruby 製のサーバ用テストフレームワーク
• “サーバのあるべき状態” を定義する
e.g.
• ◯◯ がインストールされている
• ◯◯ が起動している
• Port◯◯ を listen している etc.
37http://serverspec.org/
Serverspec の使い方
• コマンドで初期設定
38
$ bundle exec serverspec-init
Select OS type:
1) UN*X
2) Windows
Select number: 1
Select a backend type:
1) SSH
2) Exec (local)
Select number: 1
Vagrant instance y/n: n
Input target host name: www.example.jp
実行結果
serverspec-init
• spec ファイルを編集
Serverspec の使い方
39
require 'spec_helper'
describe package('nginx'), :if => os[:family] == 'ubuntu' do
it { should be_installed }
end
describe service('nginx'), :if => os[:family] == 'ubuntu' do
it { should be_enabled }
it { should be_running }
end
describe port(80) do
it { should be_listening }
end
spec/www.example.jp/sample_spec.rb
◯◯がインストール済み
◯◯が起動中
◯◯の自動起動が有効
Port◯◯ を listen
• を実行
Serverspec の使い方
40
$ bundle exec rake spec
Package "nginx"
should be installed
Service "nginx"
should be enabled
should be running
Port "80"
should be listening
Finished in 0.18411 seconds (files took 1.8 seconds
to load)
4 examples, 0 failures
実行結果
テストが通った
rake spec
• Ansible の設定ファイルをもとに、Serverspec のテス
トと対象サーバを紐付けてくれる gem パッケージ
※ Ansible の Playbook からテストを自動生成するわけで
はない
• インストール:
• を実行
• を実行
ansible_spec
41
gem 'rake'
gem 'ansible_spec'
Gemfile
bundle install
https://github.com/volanja/ansible_spec
ansiblespec-init
• Ansible のファイル配置は “Best Practice” のディレ
クトリ構成にしておく
• spec ファイルを以下の位置に作成
• 以下のコマンドでテストを実行
ansible_spec
42
roles/<ロール名>/spec/<適当な名前>_spec.rb
$ PLAYBOOK=<Playbook> INVENTORY=<Inventory> 
bundle exec rake serverspec:<グループ名>
Ansible の Inventory ファイルの
グループごとにテストを実行できる
まとめ
43
• Ansible でインフラのコード化を実現
• Vagrant と組み合わせて、手軽に開発環境を構築
• Serverspec, ansible_spec でインフラのテストを実行
まとめ
44
参考文献
• 入門 Chef Solo / 伊藤 直也 著
• Serverspec / 宮下 剛輔 著
• Software Design 2014年11月号
45
おわり
46

Ansible ではじめるインフラのコード化入門