EC-CUBE3のコンテンツ同期
やりたいこと
EC-CUBE3をEC2に構築しているが、管理機能とユーザー機能でインスタンスを分けているので、管理機能からページ更新などの更新処理が行われたら、ユーザー機能のEC2に更新したコンテンツを反映したい。
構成
EC2の構成は以下の通り。すべてのEC2インスタンスには、同じEC-CUBE3をインストールしている。したがってEC-CUBE3の構成は全く同じ。
- 管理機能:EC2x1台
- ユーザー機能:EC2xN台(Auto ScalingでN台まで増える。初期は2台)
問題はユーザー機能がAuto Scaringしているところ。EC2が台数固定であれば、lsyncd+rsyncdで単純に同期を取れば済むのだが、Auto Scaringの場合は台数が増えたことを検知しなければいけないし、IPが動的に変わってしまうのでそのあたりも考慮しないといけない。
解決策
lsyncdがLuaの記法でスクリプト書けるので、あとはAWS CLIを駆使して対象となるEC2の情報を取得、動的にコンテンツ配布先を指定して同期するように処理を組めば良い。
aws.amazon.com
EC2のIPを取得するShell
事前に、EC2のIP一覧を取得するShellを作っておくと良い。これをlsyncd.confから呼び出す。
使用するコマンドは「aws ec2 describe-instances」。ただしこれだけだとIPアドレスのみ抽出はできない。以下は参考程度のコマンド例だが、filterオプションなどを使ってAuto ScaringしているEC2インスタンスを絞り込む必要がある。
#!/usr/bin/env bash REGION=us-west-1 aws ec2 describe-instances --region ${REGION} --filter "Name=instance-state-name,Values=running" --query "Reservations[*].Instances[*].NetworkInterfaces[*].PrivateIpAddresses[*].[PrivateIpAddress]" --output text | sort
スクリプトを実行すると、以下のようにIPが一覧表示されるのが望ましい。
10.0.10.100
10.0.10.101
10.0.10.102
/etc/lsyncd.conf に設定を書く
Lua記法を駆使して同期設定を書く。以下の記事を参考にした。
qiita.com
qiita.com
ひとつひとつ説明していくと長くなるので、作ったlsyncd.confを少し手直しして公開する。
---- -- User configuration file for lsyncd. -- -- Simple example for default rsync, but executing moves through on the target. -- -- For more examples, see /usr/share/doc/lsyncd*/examples/ -- --sync{default.rsyncssh, source="/var/www/html", host="localhost", targetdir="/tmp/htmlcopy/"} settings { logfile = "/var/log/lsyncd/lsyncd.log", statusFile = "/tmp/lsyncd.stat", statusInterval = 1, } function get_instance_list() local command='/path/to/script' local commandResult = exec(command) local result = string.gsub(commandResult, "\n", " ") return split(result, " ") end function split(str, delim) assert(str, "文字列が設定されていません") assert(delim,"区切り文字がしていされていません") local pattern = "[^"..delim.."]*"..delim local result = {} for item in string.gmatch(str, pattern) do local tmp = item:gsub(delim,"") table.insert(result, tmp) end return result end function exec(command) local handle = io.popen(command,"r") local content = handle:read("*all") handle:close() return content end -- Set lsyncd target files. lsyncd_target_dirs = { rsync_test1="/path/to/rsync_test1", rsync_test2="/path/to/rsync_test2", rsync_test3="/path/to/rsync_test3" } lsyncd_target_hosts = get_instance_list() for lsyncd_target_host_key, lsyncd_target_host in pairs(lsyncd_target_hosts) do for lsyncd_target_dir_key, lsyncd_target_dir in pairs(lsyncd_target_dirs) do sync{ default.rsync, source=lsyncd_target_dir, target=lsyncd_target_host .. "::" .. lsyncd_target_dir_key, delay = 0, rsync = { _extra = {"-av","--delete"} } } end end
配布先インスタンスのrsyncdの設定は割愛。lsyncdとrsyncdを利用した同期設定については特別なことをする必要はないので、他の記事を参考にするとよい。また同期を行うパスについては、ご自身のサイト構成にあわせて設定を書く必要がある。ちなみにユーザー機能側のEC2インスタンス上に作成されるtwigのキャッシュは、同期するときに必ず削除するようにしたほうがよい*1。
よくわかっていない問題
lsyncdが変更を検知してtiwgキャッシュを削除してくれないことがある。なぜこういう事象が発生するか調べきれなかったので、cronで定期的にlsyncdを再起動して回避している。
*1:--deleteオプション使うと良い