はじめに
本記事はこれからはじめるChefのチュートリアル 基本編の続編です。
はじめにこれからはじめるChefのチュートリアル 基本編を実施してから進めてください。
環境構築 その5 パッケージインストール
パッケージをインストールしてみます。
今回はnginx
を例にするので以下のクックブックを作成します。
$ bundle exec knife cookbook create nginx -o site-cookbooks/
内容を記載します。
# yum install nginx
package "nginx"
以下のようにも記載できます。
package "nginx" do
action :install
end
node
に追加します。
{
"run_list": [
"ruby",
"nginx"
]
}
サーバーに反映します。
簡単ですね!
$ bundle exec knife solo cook chef-centos65
と、思ったら以下のエラーが発生しました。
No candidate version available for nginx
前回の記事で定義したyum-epel
がここで役立ちます。
node
にyum-epel
を追加します。
これによってEPELリポジトリ
が使えるようになります。
{
"run_list": [
"ruby",
"yum-epel",
"nginx"
]
}
この状態にして再実行します。
$ bundle exec knife solo cook chef-centos65
確認してみます。
$ ssh chef-centos65
$ service nginx status
nginx is stopped
$ exit
パッケージが入りました。
環境設定 その6 パッケージの設定
この状態ではnginx
は起動してません。
早速起動する命令を書きましょう
package "nginx"
service "nginx" do
# 使用できるオプションを指定
supports status: true, restart: true, reload: true
# 実際に行うコマンド
action [:enable, :start]
end
この状態にして再実行します。
$ bundle exec knife solo cook chef-centos65
確認してみます。
$ ssh chef-centos65
$ service nginx status
nginx (pid 12345) is running...
$ exit
起動してますね。
ここからnginx
の設定を書いていきます。
※サーバーに入り込んで設定を追加していっても良いのですが、前回にも書いたように冪等性を保てなくなります。
ここは全てchef
でやりましょう。
まず以下のファイルを作成します。
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/vhost.d/*.conf;
}
上記のものはインストールされたnginx.conf
に記載されていた設定ファイルから、コメント部分を取り除いてinclude /etc/nginx/vhost.d/*.conf;
を追加したものになります。
Nginxの設定内容を知りたい方はこちらを読んでください。
今回は設定ファイルの書き換えなどの方法を学ぶためのものなので、内容は何でも良いです。
このファイルを実際に配置します。
package "nginx"
service "nginx" do
supports status: true, restart: true, reload: true
action [:enable, :start]
end
# テンプレート機能を使用
template "nginx.conf" do
# 配置する箇所(上記の"nginx.conf"部分に以下を記載してもOK)
path "/etc/nginx/nginx.conf"
# 使用するテンプレートを指定
source "nginx.conf.erb"
# 権限を指定
owner "root"
group "root"
mode 0644
# 配置後に再起動を促します。
notifies :reload, "service[nginx]"
end
# ヴァーチャルホストの設定を配置するディレクトリを作成しておきます。
directory '/etc/nginx/vhost.d' do
owner 'root'
group 'root'
mode 0755
end
この状態にして再実行します。
$ bundle exec knife solo cook chef-centos65
確認してみます。
$ ssh chef-centos65
$ service nginx status
nginx (pid 12345) is running...
$ cat /etc/nginx/nginx.conf
上記で記載した内容が表示される。
$ ls -l /etc/nginx/
# vhost.dが指定した権限で作成されている。
drwxr-xr-x. 2 root root 4096 12月 3 09:00 2015 vhost.d
$ exit
このようにchef
のレシピではファイルの作成やディレクトリの作成ができます。
また、権限の指定などもできます。
深い階層のディレクトリを作る場合
深いディレクトリを作るときには以下の方法で行えます。
directory '/dir1/dir2/dir3' do
owner 'root'
group 'root'
mode '0600'
# このメソッドを指定すると「mkdir -p」のように作成できる。
recursive true
end
ただし、この方法では最後のディレクトリのみ権限が付与されるので間のディレクトリにも権限を付与させたい場合は以下のように行う。
%w[
/dir1
/dir1/dir2
/dir1/dir2/dir3
].each do |path|
directory path do
owner 'root'
group 'root'
mode '0600'
end
end
環境構築 その7 設定ファイルの汎用化
ruby
を知っている人は気づいたかもしれませんが、template
で使用しているファイルはerb
ファイルになってます。
なので、この中でもプログラムを書くことができます。
今回は変更できる事を確認するためにworker_processes
を変更してみます。
{
"nginx": {
"worker_processes": 2
},
"run_list": [
"ruby",
"yum-epel",
"nginx"
]
}
template
を一部変更します。
user nginx;
worker_processes <%= node["nginx"]["worker_processes"] %>;
...(略)
テンプレートの中身を変えてchef
を実施します。
$ bundle exec knife solo cook chef-centos65
...
--- /etc/nginx/nginx.conf 2015-12-02 09:14:33.395852109 +0000
+++ /etc/nginx/.nginx.conf20151203-15729-niu7bb 2015-12-03 01:51:58.174817582 +0000
@@ -1,5 +1,5 @@
user nginx;
-worker_processes 1;
+worker_processes 2;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
...
このように変更点を教えてくれます!
素晴らしいですね。
実際に確認してみます。
$ ssh chef-centos65
$ cat /etc/nginx/nginx.conf
user nginx;
worker_processes 2;
...
$ exit
変更されてますね。
あとは、未設定の場合の対応を行います。
default["nginx"]["worker_processes"] = 1
だいぶ色々な事ができるようになってきました。
ここまでできればほとんどのサーバー構築はできるようになっているかと思います。
環境構築 その8 ユーザー作成
初めのユーザーをそのまま使っても良いのですが、chefが操作するユーザーは強力なのでできれば他のユーザーを用意したいところです。
なので、ユーザーを追加するレシピを作成します。
ここでは鍵認証で接続できるユーザーを作成します。
鍵の作成
まずは鍵を作成します。
鍵を作るときに~/.ssh/id_rsa
を上書きしないように注意してください。
上書きすると取り返しがつかない事になると思いますので、注意してください。
# 鍵を配置するフォルダを作成します。
$ mkdir ssh
# 鍵を作成します。
$ ssh-keygen -t rsa
# この質問に対してEnterを押さないこと。「ssh/id_rsa」を入力してください。
Enter file in which to save the key (/Users/ユーザー名/.ssh/id_rsa): ssh/id_rsa
# パスフレーズは不要です。Enterを押してください。
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
# 公開鍵を表示します。
$ cat ssh/id_rsa.pub
ssh-rsa AAAAB3***.local
作成した鍵は後で使用します。
ssh-rsa AAAAB3***.local
と書かれた長い文字列をコピーしておきます。
ユーザー作成のレシピを作成
ユーザー作成用のレシピを作成します。
$ bundle exec knife cookbook create user -o site-cookbooks/
ユーザー作成のレシピを作成します。
# 適当なグループを作成します。
group "test_grp" do
gid 403
end
# SSHでログインするためのユーザーを作成します。
user "ssh_user" do
uid 403
gid 403
end
# 公開鍵を設置するフォルダを作成します。
directory "/home/ssh_user/.ssh" do
mode 0755
owner "ssh_user"
end
# 公開鍵を設置します。
file "/home/ssh_user/.ssh/authorized_keys" do
mode 0644
owner "ssh_user"
# 先ほどの公開鍵を貼り付けます。
content "ssh-rsa AAAAB3***.local"
end
# オーナーを変更しておきます。
directory "/home/ssh_user" do
mode 0755
owner "ssh_user"
end
作成したレシピをnodeに追加します。
{
"run_list": [
"user",
"ruby",
"yum-epel",
"nginx"
]
}
それではchef
を実施してみます。
$ bundle exec knife solo cook chef-centos65
現在作成したユーザーがログインできるか確認します。
$ ssh ssh_user@192.168.33.10 -i ssh/id_rsa
[ssh_user@localhost ~]$
$ exit
ログインできることが確認できました。
これで、ユーザー作成も完成です。
※今回はパスワードを設定しないのでruby-shadow
は使用してません。
汎用化
今回は説明を割愛しますが、今まで同様で必要に応じて汎用化しておくとレシピが使いやすくなります。
Capistranoを使う方へ
Capistrano
を使う方は、ここで作成した鍵を使用する事になると思います。
なので、ディレクトリ構成も少し考えると良いと思います。
例えば、以下のような構成にするなどの工夫をすると環境用構築一式を管理できるようになります。
・アプリ名のディレクトリ(git管理)
∟chef・・・アプリのサーバーを構築するchefレシピを保管
∟capistrano・・・アプリをデプロイするcapistranoを保管
∟user・・・デプロイユーザーの鍵を保管
sudoやssh制限について
今までの知識があれば/etc/sudoers
を変更する事も簡単に行えると思います。
また、rootユーザーのSSH禁止(/etc/ssh/sshd_config
)などもできるようになっていると思います。
本記事では扱いませんが、必要に応じてやってみてください。
いままではSSH制限やrootユーザーに関わる変更はとても怖い変更でした。
しかしchef
を使っていれば、事前に仮想OSで実験する事ができる上にその後失敗する事がありません。
こういう利点を生かしてchef
をどんどん使っていけると良いですね。
クックブックの探し方
ここまでできればサーバー構築で困ることはほとんどないはずです。
その気になれば自前で全て書くこともできると思います。
しかし、それは車輪の再発明
になるかもしれません。
世の中のクックブックはここから探せます。
CHEF SUPERMARKET
ここまで作成した過程でBerkshelf
を入れているので、積極的に活用していきましょう!
roleの使い方
最後になりますが、roleの説明を簡単にします。
今までのチュートリアルのやり方だとnode
ファイルが膨大になる可能性があります。
小規模で使うならrole
は不要ですが、大規模で使用する場合はrole
を使うとうまくまとめてレシピを管理することができます。
例えば以下のような構成のときに微妙に違うnode
を書く必要が出てきます。
webサーバー2台・・・ユーザー設定とapacheやtd_agentなどを入れたい。
アプリサーバー2台・・・ユーザー設定とnginxやruby、mysql::clientなどを入れたい。
DBサーバー1台・・・ユーザー設定とmysql::serverなどを入れたい。
監視サーバー・・・ユーザー設定とnginxやrubyなどを入れたい。
このようなサーバー構築をすると、基本的に導入するレシピは同じだけど上乗せしているレシピがちょっとづつ違うなどでnode
を書くのが大変になってくる。
例えば以下のような長いnode
を書いて、各サーバーに合わせて増減する・・・なんてぞっとしないだろうか?
{
"run_list": [
"yum",
"yum-epel",
"ntp",
"monit",
"nagios",
...
"user",
"ruby",
"nginx",
"apache",
"mysql",
"imagemagick"
]
}
このような時はrole
を使うと便利だ。
role
はこのようなレシピをまとめてくれる存在だ。
roleの分け方
role
はroles/
配下に配置できる。
例えば基本的な構成はbase.json
に書いて、Webサーバー用の構成はweb.json
に書くなどとすれば先ほどのnode
は以下のように短くなる。
{
"run_list": [
"role[base]",
"role[web]"
"imagemagick"
]
}
このように目的別にrole
を作っておくとレシピの管理が楽にできる。
また、roleにもdefault_attributes
と言う項目があり、汎用的に使用している変数を定義することができる。
そして、その値をnode
で上書きすることもできるので、便利だ。
作ってみる
とりあえず、今まで作ってたものをrole
に移してみよう。
{
"run_list": [
"user",
"ruby",
"yum-epel",
"nginx"
]
}
あんまり恩恵がないけど、ruby
以外のレシピをserver
ロールとして作ってみる。
{
"name": "server",
"description": "this is test",
"chef_type": "role",
"json_class": "Chef::Role",
"default_attributes": {
"nginx": {
"worker_processes": 3
}
},
"run_list": [
"user",
"yum-epel",
"nginx"
]
}
nginxのworker_processesを3
にしてrole
を作成するロールを作る。
node
でロールを読み込む
{
"run_list": [
"ruby",
"role[server]"
]
}
それではchef
を実施してworker_processesが変更されることを確認する。
$ bundle exec knife solo cook chef-centos65
中身を確認してみる。
$ ssh chef-centos65
$ cat /etc/nginx/nginx.conf
user nginx;
worker_processes 3;
...
変更されてますね。
念のためnode
で上書きができるかチェックしてみます。
{
"nginx": {
"worker_processes": 2
},
"run_list": [
"ruby",
"role[server]"
]
}
実行すると以下のように変更されることが確認できます。
$ bundle exec knife solo cook chef-centos65
$ ssh chef-centos65
$ cat /etc/nginx/nginx.conf
user nginx;
worker_processes 2;
...
roleの設定項目について
roleの設定項目は基本的に以下の形式になると思います。
(というか、僕自身が他をしらない・・・)
"name": "server",
"description": "this is test",
"chef_type": "role",
"json_class": "Chef::Role",
- name・・・このロールの名前を入れます。半角スペースなど使えない文字があるので注意してください。
- description・・・ロールの説明を記載します。
まとめ
いかがだったでしょうか?
chef
にはまだまだ様々な機能がありますが、このチュートリアルをひととり行えば大抵の事には対応できるようになると思います。
本記事が誰かの役に立てれば幸いです。
筆者について
筆者はTownsoftを屋号に活躍(?)しているフリーランスです。
お仕事の依頼なども受けてますので、お気軽にご連絡ください。