confd とは
confd は Go 言語で実装されたシンプルな設定管理ツールです。
confd を実行すると、etcd や Consul といったデータストアの値を取得し、テンプレートに反映して設定ファイルを生成します。設定ファイルの生成後に任意のコマンドも実行できるため、例えば nginx の設定ファイルを生成して、nginx に反映するといった流れも実現できます。
confd をデーモンとして起動しておくと、設定を定期的に更新したり、リアルタイムに反映したりできて非常に便利です。ここからは confd を使う手順などをまとめていきます。
セットアップ
今回は Ubuntu 14.04 をインストールしたホストを用意し、そこに環境を構築していきます。
まず、confd をインストールします。
$ curl -L https://github.com/kelseyhightower/confd/releases/download/v0.11.0/confd-0.11.0-linux-amd64 -o confd
$ sudo mv confd /usr/local/bin
confd をサービスとして管理するためのファイルを作成しておきます。
$ sudo vim /etc/init/confd.conf
description "confd"
start on (net-device-up
and local-filesystems
and runlevel [2345])
stop on runlevel [016]
respawn
respawn limit 10 5
script
if [ -f "/etc/default/confd" ]; then
. /etc/default/confd
fi
chdir /var/confd
exec /usr/local/bin/confd >> /var/log/confd.log 2>&1
end script
次に、confd のバックエンドとなる etcd をインストールします。
$ curl -L https://github.com/coreos/etcd/releases/download/v2.2.5/etcd-v2.2.5-linux-amd64.tar.gz -o etcd-v2.2.5-linux-amd64.tar.gz
$ tar xzvf etcd-v2.2.5-linux-amd64.tar.gz
$ sudo cp etcd-v2.2.5-linux-amd64/etcd /usr/local/bin
$ sudo cp etcd-v2.2.5-linux-amd64/etcdctl /usr/local/bin
$ rm -rf etcd-v2.2.5-linux-amd64 etcd-v2.2.5-linux-amd64.tar.gz
etcd をサービスとして管理するためのファイルを作成しておきます。
$ sudo vim /etc/init/etcd.conf
description "etcd 2.0 distributed key-value store"
start on (net-device-up
and local-filesystems
and runlevel [2345])
stop on runlevel [016]
respawn
respawn limit 10 5
script
if [ -f "/etc/default/etcd" ]; then
. /etc/default/etcd
fi
chdir /var/etcd
exec /usr/local/bin/etcd >> /var/log/etcd.log 2>&1
end script
必要なディレクトリを作成後に、confd と etcd を起動します。
$ sudo mkdir /var/confd /var/etcd
$ sudo service confd start
$ sudo service etcd start
テンプレートからファイルを生成する
ここからは、クイックスタートガイドを参考にテンプレートからファイルを生成する流れを確認します。今回は etcd に格納したキーの値をテンプレートに反映し、設定ファイルを生成します。
まずは、設定ファイルやテンプレートを配置するディレクトリを作成します。
$ sudo mkdir -p /usr/local/etc/confd/{conf.d,templates}
次に、confd の設定ファイルを作成します。設定ファイルは TOML 形式で記述します。
$ sudo vim /usr/local/etc/confd/conf.d/test.toml
[template]
src = "test.conf.tmpl"
dest = "/tmp/test.conf"
keys = [
"/myapp/database/url",
"/myapp/database/user",
]
設定ファイルの内容をもとに、テンプレートを記述します。
$ sudo vim /usr/local/etc/confd/templates/test.conf.tmpl
[myconfig]
database_url = {{getv "/myapp/database/url"}}
database_user = {{getv "/myapp/database/user"}}
テンプレートを作成したら、テンプレート変数の値を etcd に設定します。
$ etcdctl set /myapp/database/url example.com
$ etcdctl set /myapp/database/user summerwind
設定ファイル、テンプレート、テンプレート変数の準備ができたら、confd を実行して、ファイルを生成します。
$ sudo /usr/local/bin/confd -onetime -backend etcd -node http://127.0.0.1:4001 -confdir /usr/local/etc/confd/
2016-03-09T05:36:07Z dev /usr/local/bin/confd[2929]: INFO Backend set to etcd
2016-03-09T05:36:07Z dev /usr/local/bin/confd[2929]: INFO Starting confd
2016-03-09T05:36:07Z dev /usr/local/bin/confd[2929]: INFO Backend nodes set to http://127.0.0.1:4001
2016-03-09T05:36:07Z dev /usr/local/bin/confd[2929]: INFO Target config /tmp/test.conf out of sync
2016-03-09T05:36:07Z dev /usr/local/bin/confd[2929]: INFO Target config /tmp/test.conf has been updated
生成されたファイル /tmp/test.conf
を確認すると、正しく変数が埋め込まれていることが分かります。
$ cat /tmp/test.conf
[myconfig]
database_url = example.com
database_user = summerwind
継続的にファイルを自動更新する
confd をデーモンとして起動すると、etcd の値を定期的に取得して、ファイルを自動更新することができます。更新頻度は -interval
オプションで指定できます。以下の例では30秒ごとに定期更新しています。
$ sudo /usr/local/bin/confd -backend etcd -node http://127.0.0.1:4001 -confdir /usr/local/etc/confd/ -interval 30
この時点でのファイルの内容は以下のようになっています。
$ cat /tmp/test.conf
[myconfig]
database_url = example.com
database_user = summerwind
confd を起動後に、etcd のキーの値を変更します。
$ etcdctl set /myapp/database/url test.example.com
confd による更新がおこなわれると、ファイルの内容が以下のように変化します。
$ cat /tmp/test.conf
[myconfig]
database_url = test.example.com
database_user = summerwind
Watch を使用してリアルタイムに更新する
etcd や Consul といったバックエンドには、Watch 機能が実装されているため、値の変更と同時に設定ファイルを更新することが可能です。Watch 機能を使用するには、-watch
オプションを指定して confd を起動します。
$ sudo /usr/local/bin/confd -backend etcd -node http://127.0.0.1:4001 -confdir /usr/local/etc/confd/ -watch
ファイル更新時に任意のコマンドを実行する
confd にはファイルの更新時に、更新されたファイルを検証するためのコマンドと更新されたファイルを反映するコマンドの2つを実行可能です。これらのコマンドは設定ファイルの check_cmd
と reload_cmd
に指定します。
設定ファイルを以下のように変更し、ファイル更新時に /tmp/test.conf.checked
と /tmp/test.conf.reloaded
が作成されるようにします。
$ sudo vim test.toml
[template]
src = "test.conf.tmpl"
dest = "/tmp/test.conf"
keys = [
"/myapp/database/url",
"/myapp/database/user",
]
check_cmd = "touch /tmp/test.conf.checked"
reload_cmd = "touch /tmp/test.conf.reloaded"
confd を起動後に etcd のキーを変更して、ファイルを更新します。
$ sudo /usr/local/bin/confd -backend etcd -node http://127.0.0.1:4001 -confdir /usr/local/etc/confd/ -watch
$ etcdctl set /myapp/database/url test.example.com
ファイルが更新されたのでコマンドが実行され、/tmp/test.conf.checked
と /tmp/test.conf.reloaded
が作成されていることが分かります。
$ ls -al /tmp
total 12
drwxrwxrwt 2 root root 4096 Mar 9 06:18 .
drwxr-xr-x 22 root root 4096 Mar 8 09:22 ..
-rw-r--r-- 1 root root 67 Mar 9 06:18 test.conf
-rw-r--r-- 1 root root 0 Mar 9 06:18 test.conf.checked
-rw-r--r-- 1 root root 0 Mar 9 06:18 test.conf.reloaded
なお、コマンドは check_cmd
、reload_cmd
の順に実行され、コマンドの実行に失敗した場合は、後続のコマンドが実行されず、ファイルもロールバックされるようです。使い方次第では、任意のコマンドを実行するようにもできるので、十分な注意が必要です。
セキュリティの考慮
confd は設定変更時に任意のコマンドを実行できる機能があるため、使い方によってはセキュリティ上問題になるかもしれません。Ubutntu では、標準でインストールされている AppArmor を使用すれば confd の権限を制御できます。AppArmor の設定方法については、ubuntuで AppArmor を使ってセキュアな環境を構築する が詳しいです。
AppArmor による制限を有効にするには、最初に設定ファイルを作成します。この設定ファイルには、confd がどのファイルにアクセスできるかなどの情報を記述します。
$ sudo vim /etc/apparmor.d/usr.local.bin.confd
# Last Modified: Fri Mar 11 01:53:58 2016
#include <tunables/global>
/usr/local/bin/confd {
#include <abstractions/nameservice>
#include <abstractions/base>
capability net_admin,
network inet stream,
network inet6 stream,
/usr/local/bin/confd mr,
/usr/local/etc/confd/conf.d/ r,
/usr/local/etc/confd/conf.d/test.toml r,
/usr/local/etc/confd/templates/ r,
/usr/local/etc/confd/templates/test.conf.tmpl r,
/etc/test.conf rw,
/etc/.test.conf* rw,
/usr/bin/basename ix,
/usr/bin/env ix,
/proc/sys/kernel/hostname r,
/proc/sys/net/core/somaxconn r,
}
設定ファイルができたら、設定を有効化します。
$ sudo aa-enforce confd
設定を無効化する場合は以下のコマンドを実行します。
$ sudo aa-disable confd
AppArmor によりファイルの読み込みやコマンドの実行が制限されているかどうかは、/var/log/syslog
で参照できます。以下のようなログが出力されていれば、制限が有効になっていることになります。
Mar 11 02:32:08 dev kernel: [234656.156133] type=1400 audit(1457663528.431:2358): apparmor="DENIED" operation="open" profile="/usr/local/bin/confd" name="/usr/sbin/service" pid=8515 comm="service" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Mar 11 02:32:41 dev kernel: [234688.878779] type=1400 audit(1457663561.151:2360): apparmor="DENIED" operation="open" profile="/usr/local/bin/confd" name="/usr/sbin/service" pid=8527 comm="service" requested_mask="r" denied_mask="r" fsuid=0 ouid=0