LoginSignup
1
3

More than 5 years have passed since last update.

AutoScaling環境においてGitを使わないでEC2を冗長化する方法

Last updated at Posted at 2017-09-15

制約

Git禁止(協力会社がFTPしか使えないため)

結論

  1. Master Serverを建てる
  2. Master Serverのファイルの更新をlsyncdで監視し、常にS3と同期する
  3. 任意のタイミングでSlave Server(ELB配下の全EC2インスタンス)をS3と同期する

イメージ図

だいたいこんな感じ

AutoScaling環境においてGitを使わないでEC2を冗長化する方法

Master Server編

1. S3バケットを作成する

公式サイトに詳しい方法が書いてあります。
S3 バケットを作成する方法 - Amazon Simple Storage Service

2. AWS CLIを設定する

公式サイトに詳しい方法が書いてあります。
AWS CLI の設定 - AWS Command Line Interface

3. lsyncdをインストールする

EPELリポジトリを利用してインストールします。

$ sudo yum install --enablerepo=epel lsyncd

4. lsyncdの設定を変更する

普通の書き方だとファイル名の末尾に/(スラッシュ)が混入してエラーが出たりうまくsyncしてくれなかったので、
下記のような感じでパースしてあげる必要があります。
komeda-shinjiさんの記事がとても参考になりました。ありがとうございます。

$ sudo vim /etc/lsyncd.conf
/etc/lsyncd.conf

source_dir = "/var/www/source"
s3bucket = "files.hoge.com"
prefix = "source"

snscmd = "echo !!! error "

settings {
    logfile    = "/var/log/lsyncd.log",
    statusFile = "/var/log/lsyncd.status",
    nodaemon = false,
    statusInterval = 1,
    delay = 5,
}

cp = function(event)
  local src_path = event.sourcePathname
  local dst_path = event.targetPathname

  if (string.sub(event.source, -1, -1) == "/") then
      src_path = string.sub(event.source, 1, -2) .. event.pathname
  end
  if (string.sub(event.target, -1, -1) == "/") then
      dst_path = string.sub(event.target, 1, -2) .. event.pathname
  end
  local s3cmd = "aws s3 cp '" .. src_path .. "' '" .. dst_path .. "'"
  local msg_body = "command failed: " .. s3cmd
  local msg = " --message '" ..  string.gsub(msg_body, "'", "\"") .. "'"


  local runcmd = "rc=0 && [ -f '" .. src_path .. "' ] && for try in 1 2 3; do " .. s3cmd .. "; rc=$?; [ $rc -eq 0 ] && break; done || " .. snscmd .. msg .. " || :"
  spawnShell(event, runcmd)
end

rm = function(event)
  local src_path = event.sourcePathname
  local dst_path = event.targetPathname

  if (string.sub(event.source, -1, -1) == "/") then
      src_path = string.sub(event.source, 1, -2) .. event.pathname
  end
  if (string.sub(event.target, -1, -1) == "/") then
      dst_path = string.sub(event.target, 1, -2) .. event.pathname
  end

  local s3cmd = "aws s3 rm '" .. dst_path .. "'"
  local msg_body = "command failed: " .. s3cmd
  local msg = " --message '" ..  string.gsub(msg_body, "'", "\"") .. "'"
  local runcmd = "rc=0 && [ ! -f '" .. src_path .. "' ] && for try in 1 2 3; do " .. s3cmd .. "; rc=$?; [ $rc -eq 0 ] && break; done || " .. snscmd .. msg .. " || :"
  spawnShell(event, runcmd)
end

mv = function(event)
  local src_path = event.o.targetPathname
  local dst_path = event.d.targetPathname

  if (string.sub(event.o.target, -1, -1) == "/") then
      src_path = string.sub(event.o.target, 1, -2) .. event.o.pathname
  end
  if (string.sub(event.d.target, -1, -1) == "/") then
      dst_path = string.sub(event.d.target, 1, -2) .. event.d.pathname
  end
  local s3cmd = "aws s3 mv '" .. src_path .. "' '" .. dst_path .. "'"
  local msg_body = "command failed: " .. s3cmd
  local msg = " --message '" ..  string.gsub(msg_body, "'", "\"") .. "'"

  local runcmd = "rc=0 && [ -f '" .. src_path .. "' ] && for try in 1 2 3; do " .. s3cmd .. "; rc=$?; [ $rc -eq 0 ] && break; done || " .. snscmd .. msg .." || :"
  spawnShell(event, runcmd)
end

s3sync = {
    maxProcesses = 1,
    onCreate = cp,
    onModify = cp,
    onDelete = rm,
--  onMove = mv,
}

sync {
    s3sync,
    source = source_dir,
    target = "s3://" .. s3bucket .. "/" .. prefix,
}

5. lsyncdを起動する

$ sudo /etc/rc.d/init.d/lsyncd start
$ sudo chkconfig lsyncd on
$ /etc/rc.d/init.d/lsyncd status
lsyncd (pid  12345) is running...

6. Sourceを変更する

$ vim /var/www/source/hoge.txt
/var/www/source/hoge.txt
hogehoge

7. Sourceの変更がS3に反映しているか確認する

$ tailf /var/log/lsyncd.log

Slave Server編

1. AWS CLIを設定する

公式サイトに詳しい方法が書いてあります。
AWS CLI の設定 - AWS Command Line Interface

2. S3のSourceをローカルに同期するシェルスクリプトを作成する

$ vim /usr/local/bin/s3sync.sh
/usr/local/bin/s3sync.sh
#!/bin/sh
SOURCE_DIR="/var/www"
S3_BUCKET="files.hoge.com"
PREFIX="source"

TARGET_MASTER="s3://${S3_BUCKET}/${PREFIX}/"
TARGET_LOCAL="${SOURCE_DIR}/${PREFIX}/"

aws s3 sync ${TARGET_MASTER} ${TARGET_LOCAL} --delete

3. 同期スクリプトをEC2インスタンス起動時に実行するように設定する

$ vim /etc/rc.local
/etc/rc.local
s3sync.sh
exit 0

※ちなみに、rc.localに書かれたスクリプトはroot権限で実行されます。

4. 任意のタイミングで同期スクリプトを実行する

 cronするなり、execするなり

ボツ案

Master Server+rsyncパターン

s3Syncパターン

s3fsパターン

NFSパターン

AMIを最新にしてから起動するパターン

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3