Railsが動いている検証用サーバ(EC2)を、AWSLambdaで指定の時間だけ起動して、コストを削減する

# はじめに
サービスを運用していると必ず課題になってくる「インフラコスト」。出来ればなるべくお金を掛けたくないところですよね。
今回はRailsが動いてる検証用サーバをAWSLambdaを使って必要な時だけ起動するようにしました。


# 今回お世話になった参考サイト
AWSLambdaの設定
http://dev.classmethod.jp/cloud/scheduled_to_start_instance_from_lambda/

unicorn自動起動
http://blog.mmmcorp.co.jp/blog/2015/10/23/unicorn-auto-start/

delayed_job自動起動
http://blog.champierre.com/1037

大変参考になりました。有難うございます。

# 注意事項
今回インスタンスIDを指定して、サーバの自動起動・停止をおこないますが、インスタンスIDを指定する際は**検証用サーバ**であることを確認してください。


# 環境
環境| バージョン |    
:----- |:----- |  
ubuntu| 14.04
Ruby |2.1.2
Rails|4.0.2
capistrano |3.2.1
delayed_job|4.0.6

今回は上記構成のサーバを対象に検証しています。
また、Rubyのインストールにはrbenvを使用しています。



# AWSLambdaの設定

AWSにログインしたら下記図のようにLambdaを選択してください。

![AWS_マネジメントコンソール.png](https://qiita-image-store.s3.amazonaws.com/0/49347/ee637b2c-14c7-2812-63b3-425d618ba3e8.png "AWS_マネジメントコンソール.png")

## サーバ自動起動スクリプトの作成

### Create aLambda functionの選択

![Lambda_Management_Console 3.png](https://qiita-image-store.s3.amazonaws.com/0/49347/598a40f5-7fed-3839-c44f-232cb0a9be3a.png "Lambda_Management_Console 3.png")

### スクリプトテンプレートに「hello-world-python」を選択
![Lambda_Management_Console.png](https://qiita-image-store.s3.amazonaws.com/0/49347/520237d5-22f1-389b-5bbf-459894ada1d8.png "Lambda_Management_Console.png")

### Lambda function codeにスクリプトを記述
![Lambda_Management_Console.png](https://qiita-image-store.s3.amazonaws.com/0/49347/4eabf217-9615-f2e4-68de-cb26c4be8038.png "Lambda_Management_Console.png")



```python:起動スクリプト
import boto3
 
def lambda_handler(event, context):
    client = boto3.client('ec2')
    response = client.start_instances(
        InstanceIds=[
            'インスタンスID',
        ]
    )
    print response
```


### Roleの作成
ページ中央辺りに「Role」の項目があるので、下記図のように選択

　![Lambda_Management_Console 2.png](https://qiita-image-store.s3.amazonaws.com/0/49347/bc04db1a-62df-667e-cae3-b5f7f4f15232.png "Lambda_Management_Console 2.png")

選択が終わると別タブが開くので下記図を参考に入力

![IAM_Management_Console.png](https://qiita-image-store.s3.amazonaws.com/0/49347/4581bde1-452e-4056-3346-c061088ba1c1.png "IAM_Management_Console.png")


```:ロールスクリプト
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "ec2:StartInstances",
		"ec2:StopInstances"
      ],
      "Resource": [
        "arn:aws:logs:*:*:*",
        "arn:aws:ec2:*:*:*"
      ]
    }
  ]
}
```



作成が終わったら元のタブに戻り、もう一度「Role」を選択し、先ほど作成したロールを選択。
以上が終わったらNextを押下して確認画面へ


![Lambda_Management_Console.png](https://qiita-image-store.s3.amazonaws.com/0/49347/c9603e38-0331-d17e-911e-4bd6cbf3e89d.png "Lambda_Management_Console.png")


### 起動時間の設定
Fucntionが出来たら、起動時間の設定をします。
上部のタブから「Event sources」 => 「Add event source」を選択すると下記図のようになります。


![スクリーンショット 2016-04-21 12.38.55.jpg](https://qiita-image-store.s3.amazonaws.com/0/49347/5cfd0acb-ffcc-92c8-d4c7-a1e89680b064.jpeg "スクリーンショット 2016-04-21 12.38.55.jpg")

ここで「CloudWatch Events - Schedule」を選択します。

すると、下記図のようになります。今回は**月曜日から金曜日の9時に起動**するように設定します。
*cronの設定はUTCなので注意してください。

![Lambda_Management_Console 5.png](https://qiita-image-store.s3.amazonaws.com/0/49347/9489b0f4-a1c3-b535-b89a-6da02a80bcd6.png "Lambda_Management_Console 5.png")

これで完了です。


## サーバ自動停止スクリプトの作成
基本的には起動と同じ手順なのですが一部スクリプトを書き換えます。

```python:停止スクリプト
import boto3

def lambda_handler(event, context):
    client = boto3.client('ec2')
    response = client.stop_instances(
        InstanceIds=[
            'インスタンスID',
        ]
    )
    print response
```

![Lambda_Management_Console 6.png](https://qiita-image-store.s3.amazonaws.com/0/49347/b6daaf71-ca3e-d891-b5b8-0c93fa51bb1b.png "Lambda_Management_Console 6.png")

これでLamda側は完了です。

# 検証用サーバ
サーバ起動時にunicornとdelayed_jobを自動起動するようにします。

## 自動起動ツールのインストール
ubuntuの場合、chkconfigが使えないのでsysv-rc-confをインストールします。

```bash:インストール
sudo apt-get install sysv-rc-conf
```


## unicornの自動起動

### unicorn起動スクリプトの作成

``etc/init.d/``配下にunicornファイルを作成

```bash:etc/init.d/
sudo touch unicorn
```

unicornファイルの権限を755に変更

```bash:権限変更
sudo chmod 755 unicorn
```

unicornファイルに下記を記述

```bash:etc/init.d/unicorn
#!/bin/sh

#description:unicorn shell

NAME="Unicorn"
ENV=staging
USER=ubuntu

# 環境にあわせてください
ROOT_DIR="/var/www/vhosts/app/current"

GEMFILE="${ROOT_DIR}/Gemfile"
PID="${ROOT_DIR}/tmp/pids/unicorn.pid"
CONF="${ROOT_DIR}/config/unicorn/${ENV}.rb"
OPTIONS=""

start()
{
  if [ -e $PID ]; then
    echo "$NAME already started"
    exit 1
  fi
  echo "start $NAME"
  cd $ROOT_DIR
  su - ${USER} -c "cd ${ROOT_RIR} && BUNDLE_GEMFILE=${GEMFILE} bundle exec unicorn -c ${CONF} -E ${ENV} -D ${OPTIONS}"
}

stop()
{
  if [ ! -e $PID ]; then
    echo "$NAME not started"
    exit 1
  fi
  echo "stop $NAME"
  kill -QUIT `cat ${PID}`
}

force_stop()
{
  if [ ! -e $PID ]; then
    echo "$NAME not started"
    exit 1
  fi
  echo "stop $NAME"
  kill -INT `cat ${PID}`
}

reload()
{
  if [ ! -e $PID ]; then
    echo "$NAME not started"
    start
    exit 0
  fi
  echo "reload $NAME"
  kill -HUP `cat ${PID}`
}

restart()
{
  stop
  sleep 3
  start
}

case "$1" in
  start)
  start
  ;;
  stop)
  stop
  ;;
  force-stop)
  force_stop
  ;;
  reload)
  reload
  ;;
  restart)
  restart
  ;;
  *)
  echo "Syntax Error: release [start|stop|force-stop|reload|restart]"
  ;;
esac

```


上記で作成したスクリプトを、サーバ起動時に自動起動するように設定してください

```bash:unicorn自動起動
sudo sysv-rc-conf unicorn on
```

## delayed_jobの自動起動
### railsプロジェクト内にスクリプトを作成

```bash
sudo touch /var/www/vhosts/app/shared/config/delayed_job.monitrc
```

* プロジェクトのパスは環境に合わせてください

```sh:delayed_job.monitrc
check process delayed_job
  with pidfile /var/www/vhosts/app/shared/pids/delayed_job.pid
  start program = "/bin/su - ubuntu -c 'cd /var/www/vhosts/app/current; PATH=/usr/local/rbenv/shims:/usr/local/rbenv/bin:$PATH RBENV_ROOT=~/.rbenv RBENV_VERSION=2.1.2 RAILS_ENV=staging ~/.rbenv/bin/rbenv exec bundle exec bin/delayed_job -n 2 --queues=mailer,tracking --prefix=reports --pool=mailer:2 --pool=tracking:1 --pool=*:2 start'"
  stop program = "/bin/su - ubuntu -c 'cd /var/www/vhosts/app/current; PATH=/usr/local/rbenv/shims:/usr/local/rbenv/bin:$PATH RBENV_ROOT=~/.rbenv RBENV_VERSION=2.1.2 RAILS_ENV=staging ~/.rbenv/bin/rbenv exec bundle exec bin/delayed_job -n 2 --queues=mailer,tracking --prefix=reports --pool=mailer:2 --pool=tracking:1 --pool=*:2 stop'"

```

## monitのインストール

```bash:インストール
 sudo apt-get install monit
```


## 自動起動設定
```bash:自動起動
sudo sysv-rc-conf monit on
```

## monitファイルの編集

``/etc/monit/``配下のmonitrcを下記のように書き換えます。

```bash:/etc/monit/monitrc
set daemon 120
set logfile /var/log/monit.log

set idfile /var/lib/monit/id
set statefile /var/lib/monit/state
set eventqueue
    basedir /var/lib/monit/events
    slots 100
set httpd port 2812 and
  allow localhost

###############################################################################
## Includes
###############################################################################
   include /etc/monit/conf.d/*
	# 環境に合わせてください
   include /var/www/vhosts/app/shared/config/delayed_job.monitrc
```

権限をrootユーザの700にしてください。


```bash:権限変更
sudo chmod 700 monitrc
```

以上です。これで検証用サーバが月曜日 ~ 金曜日の9時 ~ 23時まで起動するようになります。