chef で mysql のユーザやデータベースを管理する

以前、ある環境のデータベースを作ったときは、忙しくて手が回らないという理由で
ユーザやデータベースのセットアップは script リソースを作ってえいやと済ませてしまった tk0miya です。こんにちは。

今回はすべて community cookbook で環境を作る方法をまとめてみました。
やり方が分かってしまえばシンプルに実現できるので、泥臭く script リソースを作らずに済みそうです。

鍵は database cookbook

ユーザやデータベースを作るレシピが mysql cookbook に入っていないため、
公式には提供されていないものといままで諦めていたのですが、
調べてみると mysqll cookbook ではなく database cookbook でリソースが提供されているようです。

以下、README の説明です。

The main highlight of this cookbook is the database and database_user resources
for managing databases and database users in a RDBMS.
Providers for MySQL, PostgreSQL and SQL Server are also provided, see usage documentation below.

ここにもある通り、database cookbook では database リソースと database_user リソースを提供しています。
MySQL 用の provider も用意されているので、これでユーザとデータベースが管理できます。

database cookbook を使ってみよう

まずは Cheffile に database cookbook を書き足します。

cookbook 'mysql'
cookbook 'database'

続いて、ユーザとデータベースを定義するためのレシピを作ります。

$ knife cookbook create app -o site-cookbooks/

metadata.json に depends 行を書き足して

depends 'database'

そして、recipe/database.rb に定義を書いていきます。

include_recipe 'database::mysql'

mysql_connection_info = {:host => "localhost",
                         :username => 'root',
                         :password => node['mysql']['server_root_password']}

mysql_database "my_app" do
  connection mysql_connection_info
  action :create
end

mysql_database_user "admin" do
  connection mysql_connection_info
  password "passw0rd"
  database_name "my_app"
  privileges [:all]
  action [:create, :grant]
end

mysql_database_user "app" do
  connection mysql_connection_info
  password "passw0rd"
  database_name "my_app"
  privileges [:select, :update, :insert, :delete]
  action [:create, :grant]
end

ここでは my_app というデータベースを定義し、
そしてそこに接続可能な 2つのユーザを定義しています。
ひとつはすべての権限をもった admin ユーザ、
もうひとつは select, update, insert, delete だけができる app ユーザです。
(5/2417:15 追記): このサンプルでは recipe に直にパスワードが埋め込まれています。必要に応じて attribute 化する等検討してください。

この例では action [:create, :grant] として、ユーザの作成と権限の付与をひとまとめにしていますが、
複数のデータベースがある場合などは :create と :grant を分けると良さそうです。

最後に solo.json を作ります。

{
  "run_list" : [
    "recipe[mysql::server]",
    "recipe[app::database]"
  ],
  "mysql" : {
    "server_debian_password" : "passw0rd",
    "server_root_password" : "passw0rd",
    "server_repl_password" : "passw0rd"
  }
}

ここでは mysql::server で MySQL サーバをインストールし、app::database でデータベースとユーザを設定しています。
なお、MySQL のパスワード設定は chef-solo 用のものなので、chef-server を使ってる人はリファレンスを見つつ適切に設定してください。

あとはこれらをもとに chef(-solo)を実行してください。

まとめ

mysql cookbook と database cookbook を使うとデータベースの構築がかんたんにできるようになりました。
ここまでは chef でお膳立てしておき、テーブルの定義はアプリのデプロイの際に migration するだけで、
アプリケーションを動かすことができるようになるはずです。

ここではユーザの定義をレシピベースでおこないましたが、data_bag を使って定義をするようにするなど、
必要に応じて cookbook の調整を加えていくと便利に使えそうです。
(どうせアプリ側の設定で接続ユーザの情報が必要になるはずなので、レシピ内の定数としてあれこれ書くのは望ましくないですよね)