ネットワークエンジニアのための 
Puppet / Chef 
Tetsuhiro Sato
自己紹介 
• 某ネットワークベンダでSDN 的な仕事をしてます 
• 基本的にRubyist 
– 仕事では、OpenDaylight やルータをいじるSDK 関連でJava 
も使ってます 
– Node.js で遊ぶのにCoffeeScript を使ってます 
– 科学計算用途でPython を使ってみたいと思っています
今日のお題目 
• ネットワークエンジニアがネットワークエンジニア向 
けにPuppet / Chef を語る 
• その上で、ネットワークでPuppet / Chef が使えた 
らうれしいかどうか、(ユーザーの気持ちになって) 
考えてみる
Open Source Provisioning Toolchain 
アプリケーションサービス導入 
システム設定 
Cloud or VM 
イメージ起動 
OS 
インストール 
オーケストレーション 
コンフィグレーション 
ブートストラッピング 
Open Source Provisioning Toolchain 
http://cdn.oreillystatic.com/en/assets/1/event/48/Provisioning%20Toolchain%20Presentation.pdf 
プロビジョニングアクティビティ 
Capistrano 
Fabric 
Maven 
CFEngine 
Puppet 
Chef 
Ansible 
Kickstart 
Vagrant 
Docker 
← ここ
Infrastructure as Code 
• インフラをコードで記述 
Puppet 
package { 'nginx' 
ensure => installed, 
} 
service { 'nginx' 
ensure => running, 
enable => true, 
} 
Chef 
package 'nginx' do 
action :install 
end 
service 'nginx' do 
action [ :enable, :start ] 
end
宣言的 
• 手順ではなく、「あるべき状態」を記述 
命令的(Shell) 
$ sudo yum install –y nginx 
$ sudo /sbin/chkconfig –level 2345 nginx on 
$ sudo service nginx start 
宣言的(Chef) 
package 'nginx' do 
action :install 
end 
service 'nginx' do 
action [ :enable, :start ] 
end
冪等性 
• ある操作を何度実行しても同じ状態に収束すること 
– あるパッケージがインストールされていなかったらインストールする、インストー 
ルされていたら何もしない 
– あるサービスが起動していなかったら起動する、起動していたら何もしない 
• どのような状態(インストール済み、未インストール、異なるバージョ 
ンがインストール済み)から実行されても、「望ましい状態」に収束 
させるために冪等性が重要 
• Puppet / Chef のリソースプロバイダの実装で冪等性を担保する 
必要がある
どのへんがうれしいの? 
• 一昔前: インフラの構成を自動化 
– アプリケーションの実行環境をいつでも再現 
• 作業手順書の不備、更新し忘れの心配なし 
– 大規模化、複雑化に対応 
• 作業漏れ、人為的なミスの心配なし 
• 可読性の高いマニフェスト(Puppet)やレシピ(Chef)に一元化することで、大規模、 
複雑なシステムの運用を助ける 
• 現在: インフラの状態をコード化 
– アプリケーション開発の方法論をインフラにも適用できる 
• バージョン管理 
• 変更のトレース(誰が、いつ、何を) 
• インフラのコードレビュー 
• テスト駆動インフラ 
– インフラへの変更の正しさがテストで確証されるので、インフラの変更やリファクタリングが怖くなく 
なり、結果として、アジャイルなサービス提供が可能に! 
• インフラCI(継続的インテグレーション)
Puppet
Puppet 
• Ruby 実装のコンフィグレーション管理ツール 
• 米国Puppet Labs 社が開発保守 
• Apache 2.0 ライセンス 
• 2005年、プロジェクト開始 
• 独自言語のマニフェストでシステムリソースを管理 
• 商用版(Puppet Enterprise)とオープンソース版
利用形態 
Server/Client Standalone 
Git レポジトリ 
Manifest 
Puppet Client 
Puppet Master 
Manifest 
puppetd 
Puppet Client 
puppetmasterd 
puppetd 
puppet 
• ローカルのマニフェストを適用 
↓ こちらをベースに解説 
XMLRPC 
over HTTPS 
• Puppet マスターからマニフェストの取得 
• マニフェストの適用 
• 適用結果をPuppet マスターへレポート(オプショナル)
環境セットアップ 
*どこで行っている作業かはプロンプトで区別(puppetm はマスター、puppetc はクライアント) 
• Yum レポジトリの追加(CentOS 6.5 の場合) 
$ sudo rpm -ivh http://yum.puppetlabs.com/el/6/products/x86_64/puppetlabs-release- 
6-7.noarch.rpm 
• Puppet マスターのインストール(CentOS 6.5 の場合) 
puppetm$ sudo yum install puppet-server 
• Puppet クライアントのインストール(CentOS 6.5 の場合) 
puppetc$ sudo yum install puppet 
• その他、マスターとクライアントでお互いに名前解決できるようにしておく
SSLv3 認証 
• Puppet マスターとPuppet クライアントの間ではSSLv3 認証を実施 
• Puppet クライアントからPuppet マスターへ初回のアクセス時に、CSR を作成し、CA を兼ねるマス 
ターに署名してもらうようにリクエスト(この時点では未登録であるため、初回アクセス自体はエラー 
終了) 
puppetc$ sudo puppet agent --test --server puppetm 
Info: Caching certificate for ca 
Info: csr_attributes file loading from /etc/puppet/csr_attributes.yaml 
Info: Creating a new SSL certificate request for puppetc 
Info: Certificate Request fingerprint (SHA256): 
D1:5D:B9:97:7A:A3:90:B8:0B:E9:0F:0B:82:92:39:6F:9A:C6:25:5B:CA:EF:43:E4:8A:21:29:0A:86:7E:A0:03 
Info: Caching certificate for ca 
Exiting; no certificate found and waitforcert is disabled 
• マスターでリクエストを確認 
puppetm$ sudo puppet cert list 
"puppetc" (SHA256) 
D1:5D:B9:97:7A:A3:90:B8:0B:E9:0F:0B:82:92:39:6F:9A:C6:25:5B:CA:EF:43:E4:8A:21:29:0A:86:7E:A0:03 
• リクエストに署名すると、次回からのアクセスは成功するようになる 
puppetm$ sudo puppet cert sign puppetc 
Notice: Signed certificate request for puppetc 
Notice: Removing file Puppet::SSL::CertificateRequest puppetc at 
'/var/lib/puppet/ssl/ca/requests/puppetc.pem'
マニフェスト(1) 
• 管理対象のサーバはノードと呼ばれる 
• puppetc に対して、次頁のNginx に関するマニフェストを適用 
/etc/puppet/manifests/site.pp 
import './nginx.pp' 
node ‘puppetc’ { 
include nginx 
} 
} 
nginx クラスをインクルード
レシピ(2) 
• Nginx をインストールしてサービスを起動するマニフェストの例 
/etc/puppet/manifests/nginx.pp 
class nginx { 
yumrepo { 'nginx': 
descr => 'nginx yum repository', 
baseurl => 'http://nginx.org/packages/centos/6/$basearch/', 
enabled => 1, 
gpgcheck => 0, 
} 
package { 'nginx': 
ensure => installed, 
require => Yumrepo['nginx'], 
} 
$port = 80 
file { '/etc/nginx/nginx.conf': 
ensure => present, 
owner => 'root', 
group => 'root', 
mode => '0644', 
content => template('/etc/puppet/manifests/nginx.conf.erb'), 
require => Package['nginx'], 
notify => Service['nginx'], 
} 
service { 'nginx': 
enable => true, 
ensure => running, 
hasrestart => true, 
require => File['/etc/nginx/nginx.conf'], 
} 
} 
Nginx 用のYum レポジトリの設定 
上記のYum レポジトリからNginx をインストール 
Nginx の設定ファイル(/etc/nginx.conf)の作成 
コンテンツとして、テンプレート(nginx.conf.erb) 
を指定している 
Nginx サービスの起動 
テンプレートに渡す変数
テンプレート 
• Nginx の設定ファイル(nginx.conf)は、ERB 形式のテンプレートに記述 
• テンプレートにはマニフェスト内で定義した変数をパラメータとして渡たすことができる 
(以下の例では、ポート番号@port の情報をマニフェストから渡している) 
/etc/puppet/manifests/nginx.conf.erb 
user nginx; 
worker_processes 1; 
error_log /var/log/nginx/error.log; 
pid /var/run/nginx.pid; 
events { 
worker_connections 1024; 
} 
http { 
include mime.types; 
default_type application/octet-stream; 
server { 
listen <%= @port %>; 
server_name localhost; 
location / { 
root /usr/share/nginx/html; 
index index.html index.htm; 
} 
} 
}
サービスの開始 
• Puppet サーバのサービスを開始 
puppetm$ sudo service puppetmasterd start 
• Puppet クライアントのサービスを開始 
puppetc$ sudo service puppetd start
確認 
• Puppet クライアントにアクセスして、サービスのステータスを確認 
$ service nginx status 
nginx (pid 28547) is running... 
$ netstat -ant | grep 80 
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 
• 外部から実際にアクセス
Chef
Chef 
• Ruby 実装のコンフィグレーション管理ツール 
• 米国Chef 社(旧Opscode社)が開発保守 
• Apache 2.0 ライセンス 
• 2009年に最初のリリース 
• Ruby DSL のレシピでシステムリソースを管理 
• 商用版のEnterprise Chef(Hosted / Private)とオープンソース版 
• 最新リリースはChef12(*本スライドでは、普及しているChef11 
をベースに解説)
利用形態 
Server/Client Chef Solo(Standalone) 
Git レポジトリ 
Node Node 
Cookbook Git レポジトリ 
/ Recipe 
Cookbook 
/ Recipe 
Cookbook 
/ Recipe 
Cookbook 
/ Recipe 
Cookbook 
/ Recipe 
Chef Node 
Chef Server 
Workstation 
Workstation 
Chef Solo + Knife Solo 
Cookbook 
/ Recipe 
↑ これをベースに解説 
Chef Node
管理ワークステーションの環境セットアップ 
• Chef-DK 0.3.0 (for Windows) を利用 
– Chef を利用するのに必要な環境が一通り 
インストールされる 
• Chef Client (v11.16.0) 
• Knife (v11.16.0) 
• Berkshelf (v3.15) 
• Test Kitchen (v1.2.1) 
• etc. 
– Chef を動かすためのRuby も同梱 
• Knife-Solo だけ、個別にインストール 
$ gem install knife-solo 
https://downloads.getchef.com/chef-dk/
Knife Solo 
• 管理ワークステーションで 
Cookbook/Recipe を一括管理 
– Git リポジトリに保存 
• リモートからNode を管理 
– SSH でNode にログインして、Chef 
Client をインストール 
– Node へcookbook/recipe をRsync で 
コピー 
– SSH でChef Solo を実行 
• 簡素なChef Solo 構成を維持しつ 
Node Node 
つ、中規模のサーバを管理できるCookbook Git レポジトリ 
/ Recipe 
Cookbook 
/ Recipe 
Cookbook 
/ Recipe 
Workstation
knife solo init 
作業ディレクトリの作成 
$ mkdir hoge 
$ cd hoge/ 
Knife Solo 環境を初期化 
$ knife solo init . 
Creating kitchen... 
Creating knife.rb in kitchen... 
Creating cupboards... 
Setting up Berkshelf... 
以下のようなファイルおよびフォルダが作成される 
hoge/ 
├ Berksfile 
├ .chef/ 
├ cookbooks/ 
├ data_bags/ 
├ environments/ 
├ nodes/ 
├ roles/ 
├ site-cookbooks/
knife solo prepare 
• hoge というNode にChef Client をインストール 
*管理されるノード側では、hoge という名前でパスワードなしにSSH でログインできて、SSH アクセスするユーザーにパス 
ワードなしにsudo できる権限を付与しておく設定が事前に必要 
$ knife solo prepare hoge --bootstrap-version 11.16.0 
Bootstrapping Chef... 
% Total % Received % Xferd Average Speed Time Time Time Current 
Dload Upload Total Spent Left Speed 
100 16519 100 16519 0 0 14182 0 0:00:01 0:00:01 --:--:-- 37458 
Downloading Chef 11.16.0 for el... 
downloading 
https://www.opscode.com/chef/metadata?v=11.16.0&prerelease=false&nightlies=false&p=el&pv=6&m=x86_64 
to file /tmp/install.sh.2244/metadata.txt 
trying wget... 
url https://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chef-11.16.0-1.el6.x86_64.rpm 
md5 5c8cfdbab2684148e2bb859b736b6827 
sha256 e4d0236cc495d080f8e7a01704e2ef554e12088687e4fe946ee8027b79871bbb 
downloaded metadata file looks valid... 
downloading https://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chef-1 
1.16.0-1.el6.x86_64.rpm 
to file /tmp/install.sh.2244/chef-11.16.0-1.el6.x86_64.rpm 
trying wget... 
Comparing checksum with sha256sum... 
Installing Chef 11.16.0 
installing with rpm... 
warning: /tmp/install.sh.2244/chef-11.16.0-1.el6.x86_64.rpm: Header V4 DSA/SHA1 
Signature, key ID 83ef826a: NOKEY 
Preparing... ########################################### [100%] 
1:chef ########################################### [100%] 
Thank you for installing Chef! 
Generating node config 'nodes/hoge.json'...
Berkshelf 
• Berkshelf はChef のCookbook とその依存関係を管理するユーティリティ 
• Linux パッケージ管理のYum やRuby ライブラリ管理のRubygems みたいなもの 
• Nginx パッケージはCentOS 6.X の標準リポジトリに含まれないので、 
EPEL リポジトリを追加するためのコミュニティCookbook の利用を設定 
hoge/Berksfile 
source 'https://api.berkshelf.com' 
cookbook 'yum-epel'
knife cookbook (nginx) 
• Nginx のCookbook/Recipe を用意 
$ knife cookbook create nginx -o site-cookbooks 
** Creating cookbook nginx 
** Creating README for cookbook: nginx 
** Creating CHANGELOG for cookbook: nginx 
** Creating metadata for cookbook: nginx 
hoge/site-cookbook/nginx/recipes/default.rb 
package 'nginx' do 
action :install 
end 
service 'nginx' do 
action [:enable, :start] 
supports :status => true, :restart => true, :reload => true 
end 
template 'nginx.conf' do 
owner 'root' 
path '/etc/nginx/nginx.conf' 
group 'root' 
mode 0644 
notifies :reload, 'service[nginx]' 
end
テンプレート 
• Nginx の設定ファイル(nginx.conf)は、ERB 形式のテンプレートに記述 
• 個々の管理対象サーバに依存する情報(IPアドレス、ポート番号等)はパラメータとして渡す(後述) 
hoge/site-cookbook/nginx/templates/default/nginx.conf.erb 
user nginx; 
worker_processes 1; 
error_log /var/log/nginx/error.log; 
pid /var/run/nginx.pid; 
events { 
worker_connections 1024; 
} 
http { 
include mime.types; 
default_type application/octet-stream; 
server { 
listen <%= node['nginx']['port'] %>; 
server_name localhost; 
location / { 
root html; 
index index.html index.htm; 
} 
} 
}
knife cookbook (iptables) 
• CentOS では初期状態でiptables サービスが動作しているので、それを無効にするためのCookbook 
を作成(後々にインフラのテストを実行するため) 
$ knife cookbook create iptables -o site-cookbooks 
** Creating cookbook iptables 
** Creating README for cookbook: iptables 
** Creating CHANGELOG for cookbook: iptables 
** Creating metadata for cookbook: iptables 
hoge/site-cookbook/nginx/recipes/default.rb 
service 'iptables' do 
action [:disable, :stop] 
end
Nodes 
• 管理対象サーバのことをノードと呼ぶ 
• ノード毎に実行するレシピやノード毎に渡すパラメータはここで記述 
hoge/nodes/hoge.json 
{ 
"nginx": {"port": 80}, 
"run_list": [ 
"yum-epel", 
"nginx", 
"iptables" 
], 
"automatic": { 
"ipaddress": "hoge" 
} 
}
knife solo cook 
$ knife solo cook hoge 
Running Chef on hoge... 
Checking Chef version... 
Installing Berkshelf cookbooks to 'cookbooks'... 
Resolving cookbook dependencies... 
Using yum (3.4.0) 
Using yum-epel (0.5.1) 
Vendoring yum (3.4.0) to d:/vagrant/hoge/cookbooks/yum 
Vendoring yum-epel (0.5.1) to d:/vagrant/hoge/cookbooks/yum-epel 
Uploading the kitchen... 
Generating solo config... 
Running Chef... 
Starting Chef Client, version 11.16.0 
Compiling Cookbooks... 
Converging 5 resources 
Recipe: yum-epel::default 
* yum_repository[epel] action create 
* template[/etc/yum.repos.d/epel.repo] action create 
- create new file /etc/yum.repos.d/epel.repo 
- update content in file /etc/yum.repos.d/epel.repo from none to b89733 
--- /etc/yum.repos.d/epel.repo 2014-10-21 05:28:17.150023239 +0000 
<snip> 
Recipe: nginx::default 
* package[nginx] action install 
- install version 1.0.15-5.el6 of package nginx 
* service[nginx] action enable 
- enable service service[nginx] 
* service[nginx] action start 
- start service service[nginx] 
* template[nginx.conf] action create 
Recipe: iptables::default 
* service[iptables] action disable 
- disable service service[iptables] 
* service[iptables] action stop (up to date) 
Recipe: nginx::default 
* service[nginx] action reload 
- reload service service[nginx] 
Running handlers: 
Running handlers complete 
Chef Client finished, 10/11 resources updated in 135.449743347 seconds 
• hoge にcookbook を適用
確認 
• hoge にアクセスしてサービスのステータス確認 
$ service nginx status 
nginx (pid 2816) is running... 
$ netstat -ant | grep 80 
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 
• 管理ワークステーションから実際にアクセス
テスト駆動インフラ 
/ インフラCI
Serverspec 
• サーバの状態をテストするためのフレームワーク 
• サーバに直接アクセス(Exec、SSH)してコマンドを実行するので、(Puppet とかChef とか)設定管理 
ツールに依存しない 
• 内部でRSpec を利用していて、宣言的にテストコードが書ける 
http://serverspec.org/ 
... 
describe package('httpd') do 
it { should be_installed } 
end 
describe service('httpd') do 
it { should be_enabled } 
it { should be_running } 
end 
describe port(80) do 
it { should be_listening } 
end 
httpd パッケージが 
インストールされているか? 
httpd サービスが 
動作しているか? 
80番ポートが 
Listen か?
Serverspec のインストールおよび初期化 
• Serverspec をインストール 
$ gem install serverspec 
• Serverspec の初期化 
$ 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: hoge 
+ spec/ 
+ spec/hoge/ 
+ spec/hoge/sample_spec.rb 
+ spec/spec_helper.rb 
+ Rakefile 
+ .rspec
テストコード 
• 初期化時に作成されるサンプルを削除 
$ rm spec/hoge/sample_spec.rb 
• Nginx パッケージ・サービスをテストコードを作成 
spec/hoge/nginx_spec.rb 
require 'spec_helper' 
describe package('nginx') do 
it { should be_installed } 
end 
describe service('nginx') do 
it { should be_enabled } 
it { should be_running } 
end 
describe port(80) do 
it { should be_listening } 
end
Serverspec の実行 
• テストの実行(成功時の例) 
$ rake spec 
c:/opscode/chefdk/embedded/bin/ruby.exe - 
I'c:/opscode/chefdk/embedded/lib/ruby/gems/2.0.0/gems/rspec-support- 
3.1.1/lib';'c:/opscode/chefdk/embedded/lib/ruby/gems/2.0.0/gems/rspec-core-3.1.5/lib' 
c:/opscode/chefdk/embedded/lib/ruby/gems/2.0.0/gems/rspec-core-3.1.5/exe/rspec --pattern 
'spec/hoge/*_spec.rb' 
Package "nginx" 
should be installed 
Service "nginx" 
should be enabled 
should be running 
Port "80" 
should be listening 
Finished in 2.08 seconds (files took 1.61 seconds to load) 
4 examples, 0 failures
Test Kitchen 
• テストハーネスツール 
• テスト用のSandbox 環境の構築、(Chef 等の)構成管 
理ツールの実行、テストの実行、Sandbox 環境の破棄を 
一気通貫で管理 
• Sandbox 環境として様々な仮想化テクノロジやクラウドプ 
ロバイダが利用できる 
– Vagrant、Docker、LXC、OpenStack 
– Amazon EC2、Cloudstack、Degital Ocean、Rackspace 
• 様々なテストフレームワークに対応 
– Serverspec、Bats 
create 
converge 
setup 
verify 
destroy 
http://kitchen.ci/ 
• テスト用Sandbox 環境 
の構築 
• 構成管理ツールの実行 
• テスト環境のセットアップ 
• テストの実行 
• テスト用Sandbox 環境 
の破棄
環境 
• テストを実行するSandbox 環境として、Vagrant + VirtualBox を利用 
• Chef Soloでサーバのプロビジョニング 
• Serverspec でインフラのテストを実行 
① Sandbox 環境の構築 
Sandbox 
② プロビジョニング 
③ インフラのテスト 
全体をコーディネート
Test Kitchen の初期化 
• 作業ディレクトリの作成(hoge/ とfuga/ は同じ階層) 
$ mkdir fuga 
$ cd fuga/ 
• Test Kitchen環境を初期化 
$ kitchen init 
create .kitchen.yml 
create test/integration/default 
run gem install kitchen-vagrant from "." 
Successfully installed kitchen-vagrant-0.15.0 
Parsing documentation for kitchen-vagrant-0.15.0 
Done installing documentation for kitchen-vagrant after 0 seconds 
1 gem installed
Test Kitchen 
• Test Kitchen 環境を設定(赤字が初期値からの変更箇所) 
fuga/.kitchen.yml 
--- 
driver: 
name: vagrant 
provisioner: 
name: chef_solo 
platforms: 
- name: centos-6.5 
suites: 
- name: default 
run_list: 
- yum-epel 
- nginx 
- iptables 
attributes:
Berkshelf 
• Berksfile を作成 
• Test Kitchen 利用時は、コミュニティCookbook だけでなく、自作Cookbook もBerkshelf で管理する必要 
がある 
fuga/Berksfile 
source 'https://api.berkshelf.com' 
cookbook 'yum-epel' 
cookbook 'nginx', path: '../hoge/site-cookbooks/nginx' 
cookbook 'iptables', path: '../hoge/site-cookbooks/iptables' 
• 今回は、nodes の設定経由でテンプレートにパラメータを渡せないので、attributes を使う 
hoge/site-cookbooks/nginx/attributes/default.rb (* hoge/ であることに注意) 
default['nginx'] = { 
port: 80 
}
テストコード 
• テストコードを用意 
fuga/test/integration/default/serverspec/nginx_spec.rb 
require 'serverspec' 
set :backend, :exec 
describe package('nginx') do 
it { should be_installed } 
end 
describe service('nginx') do 
it { should be_enabled } 
it { should be_running } 
end 
describe port(80) do 
it { should be_listening } 
end
kitchen create 
• テスト用のVM を起動 
$ kitchen create 
-----> Starting Kitchen (v1.2.1) 
-----> Creating <default-centos-65>... 
Bringing machine 'default' up with 'virtualbox' provider... 
==> default: Importing base box 'opscode-centos-6.5'... 
==> default: Matching MAC address for NAT networking... 
==> default: Setting the name of the VM: default-centos-65_default_1413889162414_90686 
==> default: Clearing any previously set network interfaces... 
==> default: Preparing network interfaces based on configuration... 
default: Adapter 1: nat 
==> default: Forwarding ports... 
default: 22 => 2222 (adapter 1) 
==> default: Booting VM... 
==> default: Waiting for machine to boot. This may take a few minutes... 
default: SSH address: 127.0.0.1:2222 
default: SSH username: vagrant 
default: SSH auth method: private key 
default: Warning: Connection timeout. Retrying... 
default: Warning: Remote connection disconnect. Retrying... 
==> default: Machine booted and ready! 
==> default: Checking for guest additions in VM... 
==> default: Setting hostname... 
==> default: Machine not provisioning because `--no-provision` is specified. 
Vagrant instance <default-centos-65> created. 
Finished creating <default-centos-65> (0m52.44s). 
-----> Kitchen is finished. (0m53.07s) 
• ステータスを確認 
$ kitchen list 
Instance Driver Provisioner Last Action 
default-centos-65 Vagrant ChefSolo Created
kitchen converge 
• Chef のCookbook/Recipe を適用 
$ kitchen converge 
-----> Starting Kitchen (v1.2.1) 
-----> Converging <default-centos-65>... 
Preparing files for transfer 
Resolving cookbook dependencies with Berkshelf 3.1.5... 
Removing non-cookbook files before transfer 
-----> Installing Chef Omnibus (true) 
downloading https://www.getchef.com/chef/install.sh 
to file /tmp/install.sh 
trying wget... 
trying curl... 
<snip> 
Installing Chef 
installing with rpm... 
<snip> 
Compiling Cookbooks... 
Converging 5 resources 
<snip> 
Chef Client finished, 10/11 resources updated in 134.641277799 seconds 
Finished converging <default-centos-65> (2m53.56s). 
-----> Kitchen is finished. (2m56.37s) 
• ステータスを確認 
$ kitchen list 
Instance Driver Provisioner Last Action 
default-centos-65 Vagrant ChefSolo Converged
kitchen setup 
• テスト用の仮想マシンに必要なパッケージをセットアップ 
$ kitchen setup 
-----> Starting Kitchen (v1.2.1) 
-----> Setting up <default-centos-65>... 
Fetching: thor-0.19.0.gem (100%) 
Fetching: busser-0.6.2.gem (100%) 
Successfully installed thor-0.19.0 
Successfully installed busser-0.6.2 
2 gems installed 
-----> Setting up Busser 
Creating BUSSER_ROOT in /tmp/busser 
Creating busser binstub 
Plugin serverspec installed (version 0.5.3) 
-----> Running postinstall for serverspec plugin 
Finished setting up <default-centos-65> (0m29.77s). 
-----> Kitchen is finished. (0m32.89s) 
• ステータスを確認 
$ kitchen list 
Instance Driver Provisioner Last Action 
default-centos-65 Vagrant ChefSolo <Not Created>
kitchen verify 
• テストを実行 
$ kitchen verify 
-----> Starting Kitchen (v1.2.1) 
-----> Verifying <default-centos-65>... 
Removing /tmp/busser/suites/serverspec 
Uploading /tmp/busser/suites/serverspec/nginx_spec.rb (mode=0644) 
-----> Running serverspec test suite 
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -I/tmp/busser 
/gems/gems/rspec-support-3.1.2/lib:/tmp/busser/gems/gems/rspec-core-3.1.7/lib /o 
pt/chef/embedded/bin/rspec --pattern /tmp/busser/suites/serverspec/**/*_spec. 
rb --color --format documentation --default-path /tmp/busser/suites/serverspec 
Package "nginx" 
should be installed 
Service "nginx" 
should be enabled 
should be running 
Port "80" 
should be listening 
Finished in 0.1954 seconds (files took 0.31729 seconds to load) 
4 examples, 0 failures 
Finished verifying <default-centos-65> (0m1.89s). 
-----> Kitchen is finished. (0m4.71s) 
• ステータスを確認 
$ kitchen list 
Instance Driver Provisioner Last Action 
default-centos-65 Vagrant ChefSolo Verified
kitchen destroy 
• テスト用のVM を破棄 
$ kitchen destroy 
-----> Starting Kitchen (v1.2.1) 
-----> Destroying <default-centos-65>... 
==> default: Forcing shutdown of VM... 
==> default: Destroying VM and associated drives... 
Vagrant instance <default-centos-65> destroyed. 
Finished destroying <default-centos-65> (0m6.75s). 
-----> Kitchen is finished. (0m9.74s) 
• ステータスを確認 
$ kitchen list 
Instance Driver Provisioner Last Action 
default-centos-65 Vagrant ChefSolo Verified
kitchen test 
• kitchen test コマンドでこれまでの作業を一気通貫に実行できる 
$ kitchen test 
-----> Cleaning up any prior instances of <default-centos-65> 
-----> Destroying <default-centos-65>... 
... 
-----> Starting Kitchen (v1.2.1) 
... 
-----> Creating <default-centos-65>... 
... 
-----> Converging <default-centos-65>... 
... 
-----> Setting up <default-centos-65>... 
... 
-----> Verifying <default-centos-65>... 
... 
-----> Destroying <default-centos-65>... 
... 
-----> Kitchen is finished. (4m20.90s) 
clean up 
create 
converge 
setup 
verify 
destroy
インフラCI 
オンプレミスクラウド 
①通知(server side hook) 
Git レポジトリGit レポジトリ 
②ローカルもしくはリモートで 
“kitchen test” を実行 
git push/merge 
git push/merge 
or Pull request 
② “kitchen test” を実行 
テスト用VM には 
クラウドサービスを利用 
クラウドサービス 
外部CI ツール 
CI ツール 
①通知(web hook)
最後に、 
ネットワークで 
構成管理ツールが使えたら 
うれしいか?
各ベンダ共、設定管理ソリューションを謳っている 
A社C社 
C社J社
ネットワークでPuppet/Chef が使えたら、、、 
• 「インフラの構成を自動化」の観点 
– そこそこ、うれしいかな。。。(特にサーバもChef/Puppet で管理している場 
合) 
• 「インフラの状態をコード化」の観点 
– バージョン管理はできる 
– 簡単にテストする環境およびツールがそろっていない 
• せっかく、Chef/Puppet で行った設定をTCL/Expect 経由で取得したshow コ 
マンドの結果を正規表現で解析したくない、、、 
• そもそも、Vagrant やDocker のように簡単にテスト用のSandBox を用意でき 
ない、、、 
• 原理的に不可能なわけではないので、ベンダーさんの頑張りに期待 
• (´・ω・`) ショボーン
ネットワーク固有のうれしさ 
• ネットワーク機器の設定は重複が多い 
– インターフェイス 
– ルーティングプロトコル(インターフェイス毎、ネイバー毎の設定など) 
– トンネルテクノロジ(IPsec、L2TP など) 
• Chef/Puppet のテンプレートエンジン的な側面を駆使するとことで、 
用途毎(アクセススイッチ、コアスイッチ)にネットワークの設定から 
重複を排除できる! 
– 結果として、設定を変更する際に、変更すべき箇所が劇的に分かりやすく 
なる 
• (`・ω・´) シャキーン
Quagga Chef Provider の例 
Quagga OSPF Chef Provider による設定 
spine_ports = ["lo:1","swp21","swp22","swp23","swp24"] 
spine_ports_options = ["ip ospf area #{node.quagga.ospf.area}","ip ospf network point-to-point"] 
# merging the options into spine_ports 
ospf = {} 
spine_ports.each do |i| 
ospf[i]=spine_ports_options 
end 
# implement ospf unnumbered interfaces 
spine_ports.each do |port| 
ifconfig "#{node.quagga.loopback}/32" do 
device "#{port}" 
end 
end 
# remove these interfaces from being passive 
ospf_options=[] 
spine_ports.each do |i| 
ospf_options << "no passive-interface #{i}" 
end 
quagga_ospf "#{node.quagga.ospf.area}" do 
loopback node.quagga.loopback 
interfaces ospf 
protocols ["static"] 
ospf_op 
end 
Network Management and Automation with Chef (by Bao Nguyen) 
http://engineering.ooyala.com/blog/network-management-and-automation-chef 
インターフェイス周りの設定 
OSPF 周りのの設定
ご清聴、ありがとうございました 
m(_ _)m
参考文献 
• Puppet 
– オープンソースなシステム自動管理ツールPuppet (gihyo.jp) 
http://gihyo.jp/admin/serial/01/puppet 
• Chef 
– Chef実践入門~ コードによるインフラ構成の自動化(WEB+DB PRESS 
plus) 
• テスト駆動インフラ/ インフラCI 
– チーム開発実践入門~ 共同作業を円滑に行うツール・メソッド(WEB+DB 
PRESS plus)

ネットワークエンジニアのための Puppet / Chef

  • 1.
  • 2.
    自己紹介 • 某ネットワークベンダでSDN的な仕事をしてます • 基本的にRubyist – 仕事では、OpenDaylight やルータをいじるSDK 関連でJava も使ってます – Node.js で遊ぶのにCoffeeScript を使ってます – 科学計算用途でPython を使ってみたいと思っています
  • 3.
    今日のお題目 • ネットワークエンジニアがネットワークエンジニア向 けにPuppet / Chef を語る • その上で、ネットワークでPuppet / Chef が使えた らうれしいかどうか、(ユーザーの気持ちになって) 考えてみる
  • 4.
    Open Source ProvisioningToolchain アプリケーションサービス導入 システム設定 Cloud or VM イメージ起動 OS インストール オーケストレーション コンフィグレーション ブートストラッピング Open Source Provisioning Toolchain http://cdn.oreillystatic.com/en/assets/1/event/48/Provisioning%20Toolchain%20Presentation.pdf プロビジョニングアクティビティ Capistrano Fabric Maven CFEngine Puppet Chef Ansible Kickstart Vagrant Docker ← ここ
  • 5.
    Infrastructure as Code • インフラをコードで記述 Puppet package { 'nginx' ensure => installed, } service { 'nginx' ensure => running, enable => true, } Chef package 'nginx' do action :install end service 'nginx' do action [ :enable, :start ] end
  • 6.
    宣言的 • 手順ではなく、「あるべき状態」を記述 命令的(Shell) $ sudo yum install –y nginx $ sudo /sbin/chkconfig –level 2345 nginx on $ sudo service nginx start 宣言的(Chef) package 'nginx' do action :install end service 'nginx' do action [ :enable, :start ] end
  • 7.
    冪等性 • ある操作を何度実行しても同じ状態に収束すること – あるパッケージがインストールされていなかったらインストールする、インストー ルされていたら何もしない – あるサービスが起動していなかったら起動する、起動していたら何もしない • どのような状態(インストール済み、未インストール、異なるバージョ ンがインストール済み)から実行されても、「望ましい状態」に収束 させるために冪等性が重要 • Puppet / Chef のリソースプロバイダの実装で冪等性を担保する 必要がある
  • 8.
    どのへんがうれしいの? • 一昔前:インフラの構成を自動化 – アプリケーションの実行環境をいつでも再現 • 作業手順書の不備、更新し忘れの心配なし – 大規模化、複雑化に対応 • 作業漏れ、人為的なミスの心配なし • 可読性の高いマニフェスト(Puppet)やレシピ(Chef)に一元化することで、大規模、 複雑なシステムの運用を助ける • 現在: インフラの状態をコード化 – アプリケーション開発の方法論をインフラにも適用できる • バージョン管理 • 変更のトレース(誰が、いつ、何を) • インフラのコードレビュー • テスト駆動インフラ – インフラへの変更の正しさがテストで確証されるので、インフラの変更やリファクタリングが怖くなく なり、結果として、アジャイルなサービス提供が可能に! • インフラCI(継続的インテグレーション)
  • 9.
  • 10.
    Puppet • Ruby実装のコンフィグレーション管理ツール • 米国Puppet Labs 社が開発保守 • Apache 2.0 ライセンス • 2005年、プロジェクト開始 • 独自言語のマニフェストでシステムリソースを管理 • 商用版(Puppet Enterprise)とオープンソース版
  • 11.
    利用形態 Server/Client Standalone Git レポジトリ Manifest Puppet Client Puppet Master Manifest puppetd Puppet Client puppetmasterd puppetd puppet • ローカルのマニフェストを適用 ↓ こちらをベースに解説 XMLRPC over HTTPS • Puppet マスターからマニフェストの取得 • マニフェストの適用 • 適用結果をPuppet マスターへレポート(オプショナル)
  • 12.
    環境セットアップ *どこで行っている作業かはプロンプトで区別(puppetm はマスター、puppetcはクライアント) • Yum レポジトリの追加(CentOS 6.5 の場合) $ sudo rpm -ivh http://yum.puppetlabs.com/el/6/products/x86_64/puppetlabs-release- 6-7.noarch.rpm • Puppet マスターのインストール(CentOS 6.5 の場合) puppetm$ sudo yum install puppet-server • Puppet クライアントのインストール(CentOS 6.5 の場合) puppetc$ sudo yum install puppet • その他、マスターとクライアントでお互いに名前解決できるようにしておく
  • 13.
    SSLv3 認証 •Puppet マスターとPuppet クライアントの間ではSSLv3 認証を実施 • Puppet クライアントからPuppet マスターへ初回のアクセス時に、CSR を作成し、CA を兼ねるマス ターに署名してもらうようにリクエスト(この時点では未登録であるため、初回アクセス自体はエラー 終了) puppetc$ sudo puppet agent --test --server puppetm Info: Caching certificate for ca Info: csr_attributes file loading from /etc/puppet/csr_attributes.yaml Info: Creating a new SSL certificate request for puppetc Info: Certificate Request fingerprint (SHA256): D1:5D:B9:97:7A:A3:90:B8:0B:E9:0F:0B:82:92:39:6F:9A:C6:25:5B:CA:EF:43:E4:8A:21:29:0A:86:7E:A0:03 Info: Caching certificate for ca Exiting; no certificate found and waitforcert is disabled • マスターでリクエストを確認 puppetm$ sudo puppet cert list "puppetc" (SHA256) D1:5D:B9:97:7A:A3:90:B8:0B:E9:0F:0B:82:92:39:6F:9A:C6:25:5B:CA:EF:43:E4:8A:21:29:0A:86:7E:A0:03 • リクエストに署名すると、次回からのアクセスは成功するようになる puppetm$ sudo puppet cert sign puppetc Notice: Signed certificate request for puppetc Notice: Removing file Puppet::SSL::CertificateRequest puppetc at '/var/lib/puppet/ssl/ca/requests/puppetc.pem'
  • 14.
    マニフェスト(1) • 管理対象のサーバはノードと呼ばれる • puppetc に対して、次頁のNginx に関するマニフェストを適用 /etc/puppet/manifests/site.pp import './nginx.pp' node ‘puppetc’ { include nginx } } nginx クラスをインクルード
  • 15.
    レシピ(2) • Nginxをインストールしてサービスを起動するマニフェストの例 /etc/puppet/manifests/nginx.pp class nginx { yumrepo { 'nginx': descr => 'nginx yum repository', baseurl => 'http://nginx.org/packages/centos/6/$basearch/', enabled => 1, gpgcheck => 0, } package { 'nginx': ensure => installed, require => Yumrepo['nginx'], } $port = 80 file { '/etc/nginx/nginx.conf': ensure => present, owner => 'root', group => 'root', mode => '0644', content => template('/etc/puppet/manifests/nginx.conf.erb'), require => Package['nginx'], notify => Service['nginx'], } service { 'nginx': enable => true, ensure => running, hasrestart => true, require => File['/etc/nginx/nginx.conf'], } } Nginx 用のYum レポジトリの設定 上記のYum レポジトリからNginx をインストール Nginx の設定ファイル(/etc/nginx.conf)の作成 コンテンツとして、テンプレート(nginx.conf.erb) を指定している Nginx サービスの起動 テンプレートに渡す変数
  • 16.
    テンプレート • Nginxの設定ファイル(nginx.conf)は、ERB 形式のテンプレートに記述 • テンプレートにはマニフェスト内で定義した変数をパラメータとして渡たすことができる (以下の例では、ポート番号@port の情報をマニフェストから渡している) /etc/puppet/manifests/nginx.conf.erb user nginx; worker_processes 1; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; server { listen <%= @port %>; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } } }
  • 17.
    サービスの開始 • Puppetサーバのサービスを開始 puppetm$ sudo service puppetmasterd start • Puppet クライアントのサービスを開始 puppetc$ sudo service puppetd start
  • 18.
    確認 • Puppetクライアントにアクセスして、サービスのステータスを確認 $ service nginx status nginx (pid 28547) is running... $ netstat -ant | grep 80 tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN • 外部から実際にアクセス
  • 19.
  • 20.
    Chef • Ruby実装のコンフィグレーション管理ツール • 米国Chef 社(旧Opscode社)が開発保守 • Apache 2.0 ライセンス • 2009年に最初のリリース • Ruby DSL のレシピでシステムリソースを管理 • 商用版のEnterprise Chef(Hosted / Private)とオープンソース版 • 最新リリースはChef12(*本スライドでは、普及しているChef11 をベースに解説)
  • 21.
    利用形態 Server/Client ChefSolo(Standalone) Git レポジトリ Node Node Cookbook Git レポジトリ / Recipe Cookbook / Recipe Cookbook / Recipe Cookbook / Recipe Cookbook / Recipe Chef Node Chef Server Workstation Workstation Chef Solo + Knife Solo Cookbook / Recipe ↑ これをベースに解説 Chef Node
  • 22.
    管理ワークステーションの環境セットアップ • Chef-DK0.3.0 (for Windows) を利用 – Chef を利用するのに必要な環境が一通り インストールされる • Chef Client (v11.16.0) • Knife (v11.16.0) • Berkshelf (v3.15) • Test Kitchen (v1.2.1) • etc. – Chef を動かすためのRuby も同梱 • Knife-Solo だけ、個別にインストール $ gem install knife-solo https://downloads.getchef.com/chef-dk/
  • 23.
    Knife Solo •管理ワークステーションで Cookbook/Recipe を一括管理 – Git リポジトリに保存 • リモートからNode を管理 – SSH でNode にログインして、Chef Client をインストール – Node へcookbook/recipe をRsync で コピー – SSH でChef Solo を実行 • 簡素なChef Solo 構成を維持しつ Node Node つ、中規模のサーバを管理できるCookbook Git レポジトリ / Recipe Cookbook / Recipe Cookbook / Recipe Workstation
  • 24.
    knife solo init 作業ディレクトリの作成 $ mkdir hoge $ cd hoge/ Knife Solo 環境を初期化 $ knife solo init . Creating kitchen... Creating knife.rb in kitchen... Creating cupboards... Setting up Berkshelf... 以下のようなファイルおよびフォルダが作成される hoge/ ├ Berksfile ├ .chef/ ├ cookbooks/ ├ data_bags/ ├ environments/ ├ nodes/ ├ roles/ ├ site-cookbooks/
  • 25.
    knife solo prepare • hoge というNode にChef Client をインストール *管理されるノード側では、hoge という名前でパスワードなしにSSH でログインできて、SSH アクセスするユーザーにパス ワードなしにsudo できる権限を付与しておく設定が事前に必要 $ knife solo prepare hoge --bootstrap-version 11.16.0 Bootstrapping Chef... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 16519 100 16519 0 0 14182 0 0:00:01 0:00:01 --:--:-- 37458 Downloading Chef 11.16.0 for el... downloading https://www.opscode.com/chef/metadata?v=11.16.0&prerelease=false&nightlies=false&p=el&pv=6&m=x86_64 to file /tmp/install.sh.2244/metadata.txt trying wget... url https://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chef-11.16.0-1.el6.x86_64.rpm md5 5c8cfdbab2684148e2bb859b736b6827 sha256 e4d0236cc495d080f8e7a01704e2ef554e12088687e4fe946ee8027b79871bbb downloaded metadata file looks valid... downloading https://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chef-1 1.16.0-1.el6.x86_64.rpm to file /tmp/install.sh.2244/chef-11.16.0-1.el6.x86_64.rpm trying wget... Comparing checksum with sha256sum... Installing Chef 11.16.0 installing with rpm... warning: /tmp/install.sh.2244/chef-11.16.0-1.el6.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY Preparing... ########################################### [100%] 1:chef ########################################### [100%] Thank you for installing Chef! Generating node config 'nodes/hoge.json'...
  • 26.
    Berkshelf • BerkshelfはChef のCookbook とその依存関係を管理するユーティリティ • Linux パッケージ管理のYum やRuby ライブラリ管理のRubygems みたいなもの • Nginx パッケージはCentOS 6.X の標準リポジトリに含まれないので、 EPEL リポジトリを追加するためのコミュニティCookbook の利用を設定 hoge/Berksfile source 'https://api.berkshelf.com' cookbook 'yum-epel'
  • 27.
    knife cookbook (nginx) • Nginx のCookbook/Recipe を用意 $ knife cookbook create nginx -o site-cookbooks ** Creating cookbook nginx ** Creating README for cookbook: nginx ** Creating CHANGELOG for cookbook: nginx ** Creating metadata for cookbook: nginx hoge/site-cookbook/nginx/recipes/default.rb package 'nginx' do action :install end service 'nginx' do action [:enable, :start] supports :status => true, :restart => true, :reload => true end template 'nginx.conf' do owner 'root' path '/etc/nginx/nginx.conf' group 'root' mode 0644 notifies :reload, 'service[nginx]' end
  • 28.
    テンプレート • Nginxの設定ファイル(nginx.conf)は、ERB 形式のテンプレートに記述 • 個々の管理対象サーバに依存する情報(IPアドレス、ポート番号等)はパラメータとして渡す(後述) hoge/site-cookbook/nginx/templates/default/nginx.conf.erb user nginx; worker_processes 1; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; server { listen <%= node['nginx']['port'] %>; server_name localhost; location / { root html; index index.html index.htm; } } }
  • 29.
    knife cookbook (iptables) • CentOS では初期状態でiptables サービスが動作しているので、それを無効にするためのCookbook を作成(後々にインフラのテストを実行するため) $ knife cookbook create iptables -o site-cookbooks ** Creating cookbook iptables ** Creating README for cookbook: iptables ** Creating CHANGELOG for cookbook: iptables ** Creating metadata for cookbook: iptables hoge/site-cookbook/nginx/recipes/default.rb service 'iptables' do action [:disable, :stop] end
  • 30.
    Nodes • 管理対象サーバのことをノードと呼ぶ • ノード毎に実行するレシピやノード毎に渡すパラメータはここで記述 hoge/nodes/hoge.json { "nginx": {"port": 80}, "run_list": [ "yum-epel", "nginx", "iptables" ], "automatic": { "ipaddress": "hoge" } }
  • 31.
    knife solo cook $ knife solo cook hoge Running Chef on hoge... Checking Chef version... Installing Berkshelf cookbooks to 'cookbooks'... Resolving cookbook dependencies... Using yum (3.4.0) Using yum-epel (0.5.1) Vendoring yum (3.4.0) to d:/vagrant/hoge/cookbooks/yum Vendoring yum-epel (0.5.1) to d:/vagrant/hoge/cookbooks/yum-epel Uploading the kitchen... Generating solo config... Running Chef... Starting Chef Client, version 11.16.0 Compiling Cookbooks... Converging 5 resources Recipe: yum-epel::default * yum_repository[epel] action create * template[/etc/yum.repos.d/epel.repo] action create - create new file /etc/yum.repos.d/epel.repo - update content in file /etc/yum.repos.d/epel.repo from none to b89733 --- /etc/yum.repos.d/epel.repo 2014-10-21 05:28:17.150023239 +0000 <snip> Recipe: nginx::default * package[nginx] action install - install version 1.0.15-5.el6 of package nginx * service[nginx] action enable - enable service service[nginx] * service[nginx] action start - start service service[nginx] * template[nginx.conf] action create Recipe: iptables::default * service[iptables] action disable - disable service service[iptables] * service[iptables] action stop (up to date) Recipe: nginx::default * service[nginx] action reload - reload service service[nginx] Running handlers: Running handlers complete Chef Client finished, 10/11 resources updated in 135.449743347 seconds • hoge にcookbook を適用
  • 32.
    確認 • hogeにアクセスしてサービスのステータス確認 $ service nginx status nginx (pid 2816) is running... $ netstat -ant | grep 80 tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN • 管理ワークステーションから実際にアクセス
  • 33.
  • 34.
    Serverspec • サーバの状態をテストするためのフレームワーク • サーバに直接アクセス(Exec、SSH)してコマンドを実行するので、(Puppet とかChef とか)設定管理 ツールに依存しない • 内部でRSpec を利用していて、宣言的にテストコードが書ける http://serverspec.org/ ... describe package('httpd') do it { should be_installed } end describe service('httpd') do it { should be_enabled } it { should be_running } end describe port(80) do it { should be_listening } end httpd パッケージが インストールされているか? httpd サービスが 動作しているか? 80番ポートが Listen か?
  • 35.
    Serverspec のインストールおよび初期化 •Serverspec をインストール $ gem install serverspec • Serverspec の初期化 $ 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: hoge + spec/ + spec/hoge/ + spec/hoge/sample_spec.rb + spec/spec_helper.rb + Rakefile + .rspec
  • 36.
    テストコード • 初期化時に作成されるサンプルを削除 $ rm spec/hoge/sample_spec.rb • Nginx パッケージ・サービスをテストコードを作成 spec/hoge/nginx_spec.rb require 'spec_helper' describe package('nginx') do it { should be_installed } end describe service('nginx') do it { should be_enabled } it { should be_running } end describe port(80) do it { should be_listening } end
  • 37.
    Serverspec の実行 •テストの実行(成功時の例) $ rake spec c:/opscode/chefdk/embedded/bin/ruby.exe - I'c:/opscode/chefdk/embedded/lib/ruby/gems/2.0.0/gems/rspec-support- 3.1.1/lib';'c:/opscode/chefdk/embedded/lib/ruby/gems/2.0.0/gems/rspec-core-3.1.5/lib' c:/opscode/chefdk/embedded/lib/ruby/gems/2.0.0/gems/rspec-core-3.1.5/exe/rspec --pattern 'spec/hoge/*_spec.rb' Package "nginx" should be installed Service "nginx" should be enabled should be running Port "80" should be listening Finished in 2.08 seconds (files took 1.61 seconds to load) 4 examples, 0 failures
  • 38.
    Test Kitchen •テストハーネスツール • テスト用のSandbox 環境の構築、(Chef 等の)構成管 理ツールの実行、テストの実行、Sandbox 環境の破棄を 一気通貫で管理 • Sandbox 環境として様々な仮想化テクノロジやクラウドプ ロバイダが利用できる – Vagrant、Docker、LXC、OpenStack – Amazon EC2、Cloudstack、Degital Ocean、Rackspace • 様々なテストフレームワークに対応 – Serverspec、Bats create converge setup verify destroy http://kitchen.ci/ • テスト用Sandbox 環境 の構築 • 構成管理ツールの実行 • テスト環境のセットアップ • テストの実行 • テスト用Sandbox 環境 の破棄
  • 39.
    環境 • テストを実行するSandbox環境として、Vagrant + VirtualBox を利用 • Chef Soloでサーバのプロビジョニング • Serverspec でインフラのテストを実行 ① Sandbox 環境の構築 Sandbox ② プロビジョニング ③ インフラのテスト 全体をコーディネート
  • 40.
    Test Kitchen の初期化 • 作業ディレクトリの作成(hoge/ とfuga/ は同じ階層) $ mkdir fuga $ cd fuga/ • Test Kitchen環境を初期化 $ kitchen init create .kitchen.yml create test/integration/default run gem install kitchen-vagrant from "." Successfully installed kitchen-vagrant-0.15.0 Parsing documentation for kitchen-vagrant-0.15.0 Done installing documentation for kitchen-vagrant after 0 seconds 1 gem installed
  • 41.
    Test Kitchen •Test Kitchen 環境を設定(赤字が初期値からの変更箇所) fuga/.kitchen.yml --- driver: name: vagrant provisioner: name: chef_solo platforms: - name: centos-6.5 suites: - name: default run_list: - yum-epel - nginx - iptables attributes:
  • 42.
    Berkshelf • Berksfileを作成 • Test Kitchen 利用時は、コミュニティCookbook だけでなく、自作Cookbook もBerkshelf で管理する必要 がある fuga/Berksfile source 'https://api.berkshelf.com' cookbook 'yum-epel' cookbook 'nginx', path: '../hoge/site-cookbooks/nginx' cookbook 'iptables', path: '../hoge/site-cookbooks/iptables' • 今回は、nodes の設定経由でテンプレートにパラメータを渡せないので、attributes を使う hoge/site-cookbooks/nginx/attributes/default.rb (* hoge/ であることに注意) default['nginx'] = { port: 80 }
  • 43.
    テストコード • テストコードを用意 fuga/test/integration/default/serverspec/nginx_spec.rb require 'serverspec' set :backend, :exec describe package('nginx') do it { should be_installed } end describe service('nginx') do it { should be_enabled } it { should be_running } end describe port(80) do it { should be_listening } end
  • 44.
    kitchen create •テスト用のVM を起動 $ kitchen create -----> Starting Kitchen (v1.2.1) -----> Creating <default-centos-65>... Bringing machine 'default' up with 'virtualbox' provider... ==> default: Importing base box 'opscode-centos-6.5'... ==> default: Matching MAC address for NAT networking... ==> default: Setting the name of the VM: default-centos-65_default_1413889162414_90686 ==> default: Clearing any previously set network interfaces... ==> default: Preparing network interfaces based on configuration... default: Adapter 1: nat ==> default: Forwarding ports... default: 22 => 2222 (adapter 1) ==> default: Booting VM... ==> default: Waiting for machine to boot. This may take a few minutes... default: SSH address: 127.0.0.1:2222 default: SSH username: vagrant default: SSH auth method: private key default: Warning: Connection timeout. Retrying... default: Warning: Remote connection disconnect. Retrying... ==> default: Machine booted and ready! ==> default: Checking for guest additions in VM... ==> default: Setting hostname... ==> default: Machine not provisioning because `--no-provision` is specified. Vagrant instance <default-centos-65> created. Finished creating <default-centos-65> (0m52.44s). -----> Kitchen is finished. (0m53.07s) • ステータスを確認 $ kitchen list Instance Driver Provisioner Last Action default-centos-65 Vagrant ChefSolo Created
  • 45.
    kitchen converge •Chef のCookbook/Recipe を適用 $ kitchen converge -----> Starting Kitchen (v1.2.1) -----> Converging <default-centos-65>... Preparing files for transfer Resolving cookbook dependencies with Berkshelf 3.1.5... Removing non-cookbook files before transfer -----> Installing Chef Omnibus (true) downloading https://www.getchef.com/chef/install.sh to file /tmp/install.sh trying wget... trying curl... <snip> Installing Chef installing with rpm... <snip> Compiling Cookbooks... Converging 5 resources <snip> Chef Client finished, 10/11 resources updated in 134.641277799 seconds Finished converging <default-centos-65> (2m53.56s). -----> Kitchen is finished. (2m56.37s) • ステータスを確認 $ kitchen list Instance Driver Provisioner Last Action default-centos-65 Vagrant ChefSolo Converged
  • 46.
    kitchen setup •テスト用の仮想マシンに必要なパッケージをセットアップ $ kitchen setup -----> Starting Kitchen (v1.2.1) -----> Setting up <default-centos-65>... Fetching: thor-0.19.0.gem (100%) Fetching: busser-0.6.2.gem (100%) Successfully installed thor-0.19.0 Successfully installed busser-0.6.2 2 gems installed -----> Setting up Busser Creating BUSSER_ROOT in /tmp/busser Creating busser binstub Plugin serverspec installed (version 0.5.3) -----> Running postinstall for serverspec plugin Finished setting up <default-centos-65> (0m29.77s). -----> Kitchen is finished. (0m32.89s) • ステータスを確認 $ kitchen list Instance Driver Provisioner Last Action default-centos-65 Vagrant ChefSolo <Not Created>
  • 47.
    kitchen verify •テストを実行 $ kitchen verify -----> Starting Kitchen (v1.2.1) -----> Verifying <default-centos-65>... Removing /tmp/busser/suites/serverspec Uploading /tmp/busser/suites/serverspec/nginx_spec.rb (mode=0644) -----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -I/tmp/busser /gems/gems/rspec-support-3.1.2/lib:/tmp/busser/gems/gems/rspec-core-3.1.7/lib /o pt/chef/embedded/bin/rspec --pattern /tmp/busser/suites/serverspec/**/*_spec. rb --color --format documentation --default-path /tmp/busser/suites/serverspec Package "nginx" should be installed Service "nginx" should be enabled should be running Port "80" should be listening Finished in 0.1954 seconds (files took 0.31729 seconds to load) 4 examples, 0 failures Finished verifying <default-centos-65> (0m1.89s). -----> Kitchen is finished. (0m4.71s) • ステータスを確認 $ kitchen list Instance Driver Provisioner Last Action default-centos-65 Vagrant ChefSolo Verified
  • 48.
    kitchen destroy •テスト用のVM を破棄 $ kitchen destroy -----> Starting Kitchen (v1.2.1) -----> Destroying <default-centos-65>... ==> default: Forcing shutdown of VM... ==> default: Destroying VM and associated drives... Vagrant instance <default-centos-65> destroyed. Finished destroying <default-centos-65> (0m6.75s). -----> Kitchen is finished. (0m9.74s) • ステータスを確認 $ kitchen list Instance Driver Provisioner Last Action default-centos-65 Vagrant ChefSolo Verified
  • 49.
    kitchen test •kitchen test コマンドでこれまでの作業を一気通貫に実行できる $ kitchen test -----> Cleaning up any prior instances of <default-centos-65> -----> Destroying <default-centos-65>... ... -----> Starting Kitchen (v1.2.1) ... -----> Creating <default-centos-65>... ... -----> Converging <default-centos-65>... ... -----> Setting up <default-centos-65>... ... -----> Verifying <default-centos-65>... ... -----> Destroying <default-centos-65>... ... -----> Kitchen is finished. (4m20.90s) clean up create converge setup verify destroy
  • 50.
    インフラCI オンプレミスクラウド ①通知(serverside hook) Git レポジトリGit レポジトリ ②ローカルもしくはリモートで “kitchen test” を実行 git push/merge git push/merge or Pull request ② “kitchen test” を実行 テスト用VM には クラウドサービスを利用 クラウドサービス 外部CI ツール CI ツール ①通知(web hook)
  • 51.
  • 52.
  • 53.
    ネットワークでPuppet/Chef が使えたら、、、 •「インフラの構成を自動化」の観点 – そこそこ、うれしいかな。。。(特にサーバもChef/Puppet で管理している場 合) • 「インフラの状態をコード化」の観点 – バージョン管理はできる – 簡単にテストする環境およびツールがそろっていない • せっかく、Chef/Puppet で行った設定をTCL/Expect 経由で取得したshow コ マンドの結果を正規表現で解析したくない、、、 • そもそも、Vagrant やDocker のように簡単にテスト用のSandBox を用意でき ない、、、 • 原理的に不可能なわけではないので、ベンダーさんの頑張りに期待 • (´・ω・`) ショボーン
  • 54.
    ネットワーク固有のうれしさ • ネットワーク機器の設定は重複が多い – インターフェイス – ルーティングプロトコル(インターフェイス毎、ネイバー毎の設定など) – トンネルテクノロジ(IPsec、L2TP など) • Chef/Puppet のテンプレートエンジン的な側面を駆使するとことで、 用途毎(アクセススイッチ、コアスイッチ)にネットワークの設定から 重複を排除できる! – 結果として、設定を変更する際に、変更すべき箇所が劇的に分かりやすく なる • (`・ω・´) シャキーン
  • 55.
    Quagga Chef Providerの例 Quagga OSPF Chef Provider による設定 spine_ports = ["lo:1","swp21","swp22","swp23","swp24"] spine_ports_options = ["ip ospf area #{node.quagga.ospf.area}","ip ospf network point-to-point"] # merging the options into spine_ports ospf = {} spine_ports.each do |i| ospf[i]=spine_ports_options end # implement ospf unnumbered interfaces spine_ports.each do |port| ifconfig "#{node.quagga.loopback}/32" do device "#{port}" end end # remove these interfaces from being passive ospf_options=[] spine_ports.each do |i| ospf_options << "no passive-interface #{i}" end quagga_ospf "#{node.quagga.ospf.area}" do loopback node.quagga.loopback interfaces ospf protocols ["static"] ospf_op end Network Management and Automation with Chef (by Bao Nguyen) http://engineering.ooyala.com/blog/network-management-and-automation-chef インターフェイス周りの設定 OSPF 周りのの設定
  • 56.
  • 57.
    参考文献 • Puppet – オープンソースなシステム自動管理ツールPuppet (gihyo.jp) http://gihyo.jp/admin/serial/01/puppet • Chef – Chef実践入門~ コードによるインフラ構成の自動化(WEB+DB PRESS plus) • テスト駆動インフラ/ インフラCI – チーム開発実践入門~ 共同作業を円滑に行うツール・メソッド(WEB+DB PRESS plus)