構築環境
参考先
リポジトリのディレクトリレイアウト
$ tree /home/vagrant/ <P46,P87>
/home/vagrant/
|-- Berksfile berkshelfの設定ファイル
|-- .berkshelf/cookbooks コミュニティクックブックのダウンロード先
|-- data_bags クックブック内で利用したい任意のデータを格納する場所
|-- environments 開発用・本番用の設定を切り分けたい場合、関連する各種変数をなどを格納する
|-- nodes Nodeオブジェクトを記述したJSONファイルの格納場所
| `-- chef1.example.com.json このnodeに固有の属性をまとめておく
|-- roles ロールの設定
`-- site-cookbooks ここに自作のクックブックを置くのが慣習になっている
`-- apache apacheのクックブック
|-- CHANGELOG.md
|-- README.md
|-- attributes
| `-- default.rb attributeの初期値を設定
|-- definitions
|-- files
| `-- default
|-- libraries
|-- metadata.rb
|-- providers
|-- recipes
| `-- default.rb クックブック作成時に生成されるレシピファイルの雛型
|-- resources
`-- templates
`-- default
`-- httpd.conf.erb レシピにその設定ファイルを配置するよう書き組む事でchef実行時に配置されるtemplateリソース
はじめに。chefを動かしてみる
≫ chef-solo ChefServer/ChefClientモデルが中央集権のサーバやデータベースを必要としているのに対して、
chef-soloはサーバもクライアントも必要としないただのコマンドとして実装されている
■chef-soloインストール(オムニバスインストーラ) $ curl -L https://www.opscode.com/chef/install.sh | sudo bash $ chef-solo -v Chef: 12.15.19
≫ chef-soloでのプロビジョニングの基本手順 1. knifeコマンドによるクックブックの作成
2. レシピを書く 3. chef-soloコマンドを実行 ≫ レシピ コードで書いたサーバ設定の手順 ≫ クックブック 特定のレシピに必要なデータやファイルをまとめる入れ物がクックブック ≫ リポジトリ クックブック群を含むchefの実行に必要な一連のファイルをまとめた入れ物がリポジトリ デフォルトではchefのリポジトリは/var/chefが使われる リポジトリ>クックブック>レシピ ≫ knife リポジトリを操作するためのツール。knifeコマンドを使ってクックブックを作成する
■knifeコマンドによるクックブックの作成 $ sudo knife cookbook create hello -o /var/chef/cookbooks ■レシピを編集 $ sudo vi /var/chef/cookbooks/hello/recipes/default.rb log "Hello, World!" ■chef-soloコマンドを実行 $ sudo chef-solo -o hello Recipe: hello::default * log[Hello, World!] action write
■dstatパッケージをインストール 1. クックブックの作成 $ sudo knife cookbook create dstat -o /var/chef/cookbooks 2. レシピを編集 $ sudo vi /var/chef/cookbooks/dstat/recipes/default.rb package "dstat" do action :install end 3. chef-soloを実行 $ sudo chef-solo -o hello,dstat Recipe: hello::default * log[Hello, World!] action write Recipe: dstat::default * yum_package[dstat] action install - install version 0.7.0-2.el6 of package dstat 4. 確認 $ rpm -qa | grep dstat dstat-0.7.0-2.el6.noarch
Knife-soloでchef-soloをリモート実行
≫ knife-solo knife-soloを使うと、手元で作ったクックブックをリモートのサーバに転送して chef-soloコマンドを実行するといった一連の作業を自動化できる。 ≫ gem gem(じぇむ)はRuby 用のパッケージ管理ツール。gem のおかげで、Ruby用ライブラリのインストール、アンインストール、 バージョン管理などを簡単に実行することができるknife-soloパッケージのインストールにgemが必要 ≫ berkshelf berkshelfはクックブックの依存関係を管理するツール ≫ knife solo bootstrapコマンド chefのインストールを行ったあとにnodeオブジェクトを見て、実際にchef-soloを実行する ゲストOSを破棄して起動したあと当コマンドを打つと、破棄する直前の状態までnodeが構築される $ knife solo bootstrap chef1.example.com
■gemをインストール CentOS6に新しいバージョンのrubyをインストールする手順 http://zacodesign.net/blog/?p=1952 ■knife-soloをインストール # gem install knife-solo ■berkshelfをインストール(後述「クックブックの活用」で登場) # gem install berkshelf ■knife-soloでリポジトリを作る knife-soloでchef-soloを利用するにあたってchefリポジトリをローカル側に作成 $ knife solo init . ■knife-soloでchef-soloをインストールする 1. ssh Nodeサーバー名でログイン出来るようにしておく(後述「Nodeの再構築」参照)
2. Nodeにchef-soloをインストール $ knife solo bootstrap chef1.example.com
3. Nodeにインストールされたか確認 $ ssh chef1.example.com $ chef-solo -v Chef: 12.15.19
≫ Nodeオブジェクト 任意のNodeの状態を記述するための設定ファイル。適用したいレシピや色々な属性を定義する Nodeオブジェクトはbootstrap時にnodesディレクトリ下にノード名.jsonで作成される
パッケージのインストール
■Nodeに以下をインストールする <P36>
・dstat
・Apache
・MySQL
1. カレントディレクトリー上の関連ディレクトリ
$ ls ~ | egrep 'nodes|site' nodes site-cookbooks 2. クックブックを作成する(Chefでは自作クックブックをsite-cookbooksに置くのが習慣になっている) $ knife cookbook create dstat -o site-cookbooks $ knife cookbook create apache -o site-cookbooks $ knife cookbook create mysql -o site-cookbooks $ ls site-cookbooks/ apache dstat mysql 3. Nodeオブジェクトでサーバの状態を記述する。設定したレシピ(サーバ設定手順)が当該Nodeに適用される。 $ vi nodes/chef1.example.com.json { "run_list": [ "recipe[dstat]", 行挿入 "recipe[apache]", 行挿入 "recipe[mysql]" 行挿入 ], "automatic": { "ipaddress": "chef1.example.com" } } 4. レシピを編集する $ vi site-cookbooks/dstat/recipes/default.rb package "dstat" do action :install end $ vi site-cookbooks/apache/recipes/default.rb package "httpd" do action :install end service "httpd" do action [ :enable, :start] end $ vi site-cookbooks/mysql/recipes/default.rb package "mysql-server" do action :install end service "mysqld" do action [ :enable, :start] end 5. Knife-soloでNode上のchef-soloを実行する $ knife solo cook chef1.example.com 5. Nodeにインストールされたか確認 $ rpm -q {dstat,httpd,mysql-server} dstat-0.7.0-2.el6.noarch httpd-2.2.15-54.el6.centos.x86_64 mysql-server-5.1.73-7.el6.x86_64
$ chkconfig --list httpd; sudo service httpd status httpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off httpd (pid 2009) を実行中... $ chkconfig --list mysqld; sudo service mysqld status mysqld 0:off 1:off 2:on 3:on 4:on 5:on 6:off mysqld (pid 2316) を実行中...
≫erb拡張子 Rubyの標準ライブラリにおけるテンプレートエンジンであるERBの拡張子。 ERBを使うと任意のテキストファイルにRubyスクリプトを埋め込み実行できる。 ≫templateディレクトリ クックブック内で設定ファイルなどを扱う場合、templateディレクトリに設定ファイルを置き、 chef実行時にその設定ファイルが望んだパスに配置するようレシピにtemplateリソースを記述する。
confファイルの定義。Nodeオブジェクトでattributeを設定
■Apacheのhttpd.confをchefで取り扱う <P40,P82> 1. カレントディレクトリー上の関連ディレクトリ
$ ls ~ | grep site site-cookbooks
2. Nodeオブジェクトでattributeを設定 $ vi nodes/chef1.example.com.json { "httpd": { "docroot": "/home/vagrant" }, "run_list": [ "recipe[apache]" ] } 3. nodeのhttpd.confをテンプレートとして親機のtemplates/defaultに拡張子で.erbでSCP $ scp 192.168.33.123:/etc/httpd/conf/httpd.conf site-cookbooks/apache/templates/default/httpd.conf.erb 4. テンプレートを修正。Nodeオブジェクトで設定したattributeが設定される様に変更 $ vi site-cookbooks/apache/templates/default/httpd.conf.erb ServerName chef1.example.com:80 DocumentRoot <%= node['httpd']['docroot'] %> 5. レシピにtemplateリソースを記述 $ vi site-cookbooks/apache/recipes/default.rb template "httpd.conf" do path "/etc/httpd/conf/httpd.conf" owner "root" group "root" mode 0644 notifies :reload, 'service[httpd]' end 6. Knife-soloでchef-soloをリモート実行 $ knife solo cook chef1.example.com
レシピの書き方
≫Attribute テンプレートやレシピの中で参照できる、さまざまなkey-valueの値を管理するしくみ ・chefがシステムから抽出したAttributeをレシピで参照する場合は、node[:platform] ・chefがシステムから抽出したAttributeをテンプレートで参照する場合は、<%= node[:platform] %> ・nodeオブジェクに定義したAttributeを参照する場合は、node['httpd']['port'] ≫Ohai OSから各種情報を集めてAttributeを構成する。ohai [key]で確認できる $ ohai platform [ "centos" ] レシピ内で使う場合は node[:platform] などと書いて取得する ≫リソース ノード内の何かしらの資源(service, package, template, etc)のこと レシピで定義されている主なリソース ・group ・user ・directory ・apt_repository ・yum_repository ・template ・package ・service
・git ≫Data Bag 各ノードに共有するようなデータを扱う。例えば各ノードに複数ユーザがいる状態を定義したい場合など
レシピ名「lesson」で主要なリソースを試してみる
[ 準備 ] <P70>
・Nodeオブジェクトにレシピ「lesson」を追加しておく。 $ vi nodes/chef1.example.com.json "recipe[dstat]" ・クックブック「lesson」を作成する $ knife cookbook create lesson -o site-cookbooks
[ 各リソース毎にこの手順を実行 ]
・レシピを編集する $ vi site-cookbooks/lesson/recipes/default.rb
・実行
$ knife solo cook chef1.example.com
■ directory
directory '/home/vagrant/lesson/' do owner 'vagrant' group 'vagrant' mode '755' action :create end
■ cookbook_file
cookbook_file "#{Chef::Config[:file_cache_path]}/nkf-2.1.4.tar.gz" do mode 644 end
[解説]ファイルを配置する
site-cookbooks/lesson/files/default/nkf-2.1.4.tar.gz
↓
/home/vagrant/chef-solo/local-mode-cache/cache/nkf-2.1.4.tar.gz
■ script
bash "install nkf" do cwd '/home/vagrant/chef-solo/local-mode-cache/cache' code <<-EOC tar xvfz nkf-2.1.4.tar.gz cd nkf-2.1.4 make cp nkf /usr/bin/ EOC not_if { File.exists?("/usr/bin/nkf") } end
[解説]nkfをインストールするスクリプト。/usr/bin/nkf が存在していたら実行されない
以下はwgetしてインストールまでの処理つなげたスクリプト
bash 'install nkf' do user 'root' cwd '/usr/local/src' code <<-EOC wget https://osdn.jp/projects/nkf/downloads/64158/nkf-2.1.4.tar.gz tar xvfz nkf-2.1.4.tar.gz cd nkf-2.1.4 make cp nkf /usr/bin/ EOC not_if { File.exists?("/usr/bin/nkf") } end
クックブックの活用
≫コミュニティクックブック
chef社のサイトで公開されている再利用を前提としたクックブック。
■クックブックを探す <P92>
$ knife cookbook site search <cookbook_name>
■クックブックの詳細を見る
$ knife cookbook site show apache2
■クックブックの一覧
$ knife cookbook site list
≫Berkshelfツール chefにおける外部クックブックを管理するツール。BerksfileファイルはBerkshelfツールの設定ファイル Ruby でいうところの Bundler に該当するもの。 以下の手順でコミュニティクックブックがNodeに転送される 1. Berksfileファイルにインポートするクックブックを記載 2. berksコマンドを実行する 3. Nodeのランリスト(Nodeオブジェクト)に追加する 4. knife solo cook でNodeにレシピを適用する (knife solo cookを実行するとBerkshelfが実行され、外部クックブックが取り込まれ、それらクックブックが全てNodeに転送される) ≫Berkshelf.lock berksコマンド実行時に作成、または更新される。利用するクックブックのバージョンが記載される。 以降同リポジトリ内で利用するクックブックのバージョンは固定/統一される。 ≫.chef/knife.rb cookbook_path 自作クックブックとコミュニティクックブックの名前が同じ場合、採用するクックブックの優先度を設定 knife[:berkshelf_path] Berkshelfが依存関係のあるクックブックをダウンロードするパス
■BerkshelfでクックブックをインポートしてNodeに適用する <P94> 1. Berksfileファイルにインポートするクックブックを記載 $ vi ~/Berksfile source "https://api.berkshelf.com" cookbook 'yum-epel' 行挿入 cookbook 'apache2' 行挿入 cookbook 'mysql' 行挿入 2. berksコマンドを実行 $ berks Resolving cookbook dependencies... Fetching cookbook index from https://api.berkshelf.com... Installing apache2 (3.2.2) from https://api.berkshelf.com/ ([opscode] https://supermarket.chef.io:443/api/v1) Installing compat_resource (12.16.2) from https://api.berkshelf.com/ ([opscode] https://supermarket.chef.io:443/api/v1) Installing mysql (8.2.0) from https://api.berkshelf.com/ ([opscode] https://supermarket.chef.io:443/api/v1) Installing yum-epel (2.0.0) from https://api.berkshelf.com/ ([opscode] https://supermarket.chef.io:443/api/v1) berksコマンドを実行する事によって以下の動作が行わえる ○ .berkshelf/cookbooksディレクトリ内にクックブックがダウンロードされる
※保存先を指定しないと ./berks-cookbooks ディレクトリを作成しその中にcookbookをダウンロード
依存関連のあるクックブックもダウンロードされる $ tree -ad -L 2 .berkshelf/cookbooks/ .berkshelf/cookbooks/ |-- apache2-3.2.2 | |-- attributes | |-- definitions | |-- files | |-- libraries | |-- recipes | `-- templates |-- compat_resource-12.16.2 | |-- files | `-- libraries |-- mysql-8.2.0 | |-- libraries | `-- templates `-- yum-epel-2.0.0 |-- attributes `-- recipes ○ Berksfile.lockが作成、もしくは更新される $ vi Berksfile.lock DEPENDENCIES apache2 mysql yum-epel GRAPH apache2 (3.2.2) compat_resource (12.16.2) mysql (8.2.0) yum-epel (2.0.0) compat_resource (>= 12.14.6) 3. Nodeオブジェクトへクックブックを追加 $ vi nodes/chef1.example.com.json "run_list": [ "recipe[yum-epel]" ], 4. knife solo cook コマンドを実行 $ knife solo cook chef1.example.com
■ロールの設定 <P103> $ vi roles/web.json { "name": "web", "chef_type": "role", "json_class": "Chef::Role", "run_list": [ "recipe[dstat]", "recipe[apache2]", "recipe[yum-epel]" ] } ロールを適用する(複数roleの指定可、recipeとの混同指定可) $ vi nodes/chef{1,2}.example.com.json { "run_list": [ "role[web]" ] } 複数NodeへChef Soloを実行する $ echo chef1.example.com chef2.example.com | xargs -n 1 knife solo cook
≫Attributeの優先度
・クックブック内のAttributeファイル
・レシピの中で定義されたAttribute
・Environments
・ロール
・Nodeオブジェクト
の順で、上から下へ優先度が高くなる。
Bundlerでnginxを導入する
参考先
≫bundler
Rubyにはgem管理のためのBundlerというツールがあり、Gemfileに書かれたgemの依存関係を解決してくれる。
1. bundlerを導入 <P138> $ sudo su - # gem install bundler 2. 作業ディレクトリを作成 $ mkdir env_php $ cd env_php 3. Bundlerで chef, knife-solo, berkshelf をインストール $ vi Gemfile source 'https://rubygems.org' gem 'chef' gem 'knife-solo' gem 'berkshelf' $ bundler install 4. knife-soloでリポジトリを作る $ bundle exec knife solo init . 5. 自作のクックブックを作成 $ bundle exec knife cookbook create nginx -o ./site-cookbooks 6. レシピを作成 $ vi site-cookbooks/nginx/recipes/default.rb include_recipe "yum-epel" package "nginx" do action :install end service "nginx" do action [ :enable, :start ] supports :status => true, :restart => true, :reload => true end 7. berksfileにクックブックの依存関係を定義 $ vi Berksfile site :opscode cookbook "yum-epel" cookbook "nginx", path: "./site-cookbooks/nginx" 8. コミュニティクックブックをinstall
$ bundle exec berks vendor ./cookbooks 9. ssh Nodeサーバー名でログイン出来るようにして、Nodeにchef-soloをインストール $ bundle exec knife solo bootstrap chef1.example.com 10. Nodeオブジェクトでサーバの状態を記述する $ vi nodes/chef1.example.com.json { "run_list": [ "recipe[yum-epel]", "recipe[nginx]" ] } 11. Knife-soloでNode上のchef-soloを実行する $ bundle exec knife solo cook chef1.example.com 12. 確認 http://192.168.33.123/
■Nodeオブジェクトの作成 & 疎通
コマンドプロンプト centos>vagrant up chef1 --provision 公開鍵設定
親機>
$ ssh-keygen -t rsa $ sudo vi /etc/hosts 192.168.33.123 chef1.example.com $ scp .ssh/id_rsa.pub chef1.example.com:~/ Node>
$ ssh chef1.example.com
$ cat id_rsa.pub > .ssh/authorized_keys 親機>
$ ssh chef2.example.com ■Nodeオブジェクトを追加 $ cp nodes/chef1.example.com.json nodes/chef2.example.com.json $ vi nodes/chef2.example.com.json "ipaddress": "chef2.example.com" $ knife solo bootstrap chef2.example.com