設定する対象がデータベースやアプリケーションサーバの場合、「一つのインスタンスに複数のアプリケーションをデプロイ」したり、「一つのアプリケーションに複数のデータソースを追加」といった一対多の設定はよくあります。
ansibleで設定を行う場合に、
- 設定ファイルを肥大化を防止
- 必要最小限の値を設定
- 設定と構造の関係を把握することが容易
となるようなパターンを検討してみました。
より良い方法があるかもしれませんが、ひとまずこれで動いています。
設定:構造を定義
設定は、“./host_vars/[対象サーバ名]を起点にします。こうすることでansibleがインベントリから対象サーバを特定した際に自動的に設定が読み込まれます。
$ cat host_vars/appserv1 serverName: app-server1 tomcat: - appName: inst1 db: - dba - appName: inst2 db: - db1 - db2 $
この例では、tomcat
という変数にinst1
とinst2
という2つのアプリケーションがあり、inst1
は、dba
というデータベース接続を、inst2
は、db1
とdb2
の2つのデータベース接続を設定します。
設定:各オブジェクトのパラメータ定義
各オブジェクトのパラメータ定義は、./vars
にオブジェクト毎に設定します。
アプリケーションのパラメータは、./vars/inst1.yml
と./vars/inst2.yml
に設定します。
各アプリケーションに関連するデータベースの設定は、./vars/[アプリ名][db名].yml
に設定します。
今回の例ですと、./vars/inst1dba.yml
や./vars/inst2db1.yml
や./vars/inst2db2.yml
に設定することになります。
$ ls vars/inst[12]*.yml | cat vars/inst1.yml vars/inst1dba.yml vars/inst2.yml vars/inst2db1.yml vars/inst2db2.yml $
アプリケーションの設定は、下記のようにappName
を定義します。
$ for i in `ls ./vars/inst[12].yml`; do echo $i; cat $i; done ./vars/inst1.yml appName: inst1 ./vars/inst2.yml appName: inst2 $
データベースの設定は、下記とします。
$ for i in `ls ./vars/inst[12]db*.yml`; do echo $i; cat $i; done ./vars/inst1dba.yml schemaName: inst1dba ./vars/inst2db1.yml schemaName: inst2db1 ./vars/inst2db2.yml schemaName: inst2db2 $
roleの定義
パラメータを読み込んで設定するroleを作成するために下記のようなファイル一式を作ります。host_vars
とvars
は、上記で設定したファイルです。
$ tree . ├── host_vars │ ├── appserv1 │ └── appserv2 ├── hosts ├── roles │ └── app │ └── tasks │ ├── db.yml │ ├── main.yml │ └── tomcat.yml ├── site.yml └── vars ├── inst1.yml ├── inst1dba.yml ├── inst2.yml ├── inst2db1.yml └── inst2db2.yml $
roles/app/tasks/main.yml
でアプリケーションの設定と、それに紐づくデータベースの設定をするためのタスクを定義します。
$ cat roles/app/tasks/main.yml --- - include: tomcat.yml with_items: "{{tomcat}}" - include: db.yml with_subelements: - tomcat - db $
一つ目のタスクは、アプリケーション設定をするtomcat.yml
というファイルをインクルードします。
./host_avrs/[サーバ名]
で定義したtomcat
という変数に定義したアプリケーションの回数繰り返します。
二つ目のタスクは、アプリケーションに紐付いたデータベースの設定をするdb.yml
というファイルをインクルードします。
本当は、インスタンスの設定に入れ子したかったのですが、with_items
で使われるitem
という変数が入れ子の中では設定できず諦めました。(誰かうまい方法教えて)
いろいろ調べた結果、with_subelements
でtomcat
変数の配列の一つを取り出し、appName
+db
の組み合わせをdb.yml
に渡しています。
それぞれの処理
サンプルなので設定されたパラメータを読み込み表示するだけの処理です。
アプリケーションの設定は、以下の通りです。
$ cat roles/app/tasks/tomcat.yml --- - include_vars: "{{item.appName}}.yml" - debug: msg="Tomcat application Name={{appName}}" $
DBの設定は、以下の通りです。
$ cat roles/app/tasks/db.yml --- - include_vars: "{{item.0.appName}}{{item.1}}.yml" - debug: msg="{{item.0.appName}} application dbName={{schemaName}}" $
どちらも、最初にinclude_vars
で./vars
ディレクトリ下の所定の定義ファイルのパラメータを読み込み、表示します。
実行
インベントリにとりあえず1台サーバを追加します。
appserv2
も追加して、./host_vars/appserv1
を./host_vars/appserv2
とにコピーすると、全くおなじ設定のサーバを作ることができます。
もちろん、./vars/inst1*.yml
一式をコピーして個別の設定にすることも可能です。
[appservers] appserv1 #appserv2 $
実行すると、こんな感じです。
アプリケーションの名前やDB接続先など、設定が必要な固有の値をtemplate
で埋め込んだりtask
の中で参照するといった使い方になります。
$ ansible-playbook -i hosts site.yml PLAY *************************************************************************** TASK [setup] ******************************************************************* ok: [appserv1] TASK [app : include] *********************************************************** included: /home/vagrant/git/sample/roles/app/tasks/tomcat.yml for appserv1 included: /home/vagrant/git/sample/roles/app/tasks/tomcat.yml for appserv1 TASK [app : include_vars] ****************************************************** ok: [appserv1] TASK [app : debug] ************************************************************* ok: [appserv1] => { "msg": "Tomcat application Name=inst1" } TASK [app : include_vars] ****************************************************** ok: [appserv1] TASK [app : debug] ************************************************************* ok: [appserv1] => { "msg": "Tomcat application Name=inst2" } TASK [app : include] *********************************************************** included: /home/vagrant/git/sample/roles/app/tasks/db.yml for appserv1 included: /home/vagrant/git/sample/roles/app/tasks/db.yml for appserv1 included: /home/vagrant/git/sample/roles/app/tasks/db.yml for appserv1 TASK [app : include_vars] ****************************************************** ok: [appserv1] TASK [app : debug] ************************************************************* ok: [appserv1] => { "msg": "inst1 application dbName=inst1dba" } TASK [app : include_vars] ****************************************************** ok: [appserv1] TASK [app : debug] ************************************************************* ok: [appserv1] => { "msg": "inst2 application dbName=inst2db1" } TASK [app : include_vars] ****************************************************** ok: [appserv1] TASK [app : debug] ************************************************************* ok: [appserv1] => { "msg": "inst2 application dbName=inst2db2" } PLAY RECAP ********************************************************************* appserv1 : ok=16 changed=0 unreachable=0 failed=0 $