AWS Elastic Beanstalkで環境構築自動化


Elastic Beanstalkでサービスのサーバ環境を自動でセットアップ、指定条件でオートスケーリングを設定します。
まだ情報が少ない印象がある中、実運用で使用するために設定しているのでたぶん他のどの日本語記事より細かい、はず。
というか凄い手探り感があった。

## Can & Can't

読み進めて絶望しないように先に書いておく。

### Yes we can!!

* サーバの応答が遅くなったり、CPU負荷が上がったりした時に自動でEC2インスタンスをロードバランサ下に紐づけて登録済みファイルを配置してくれる
* 自動でデプロイされたサーバには指定したユーザを作成して、RSAログインできるようにして、yumで指定したサービスをインストールして、各種設定ファイルも独自のものに置き換えて再起動させちゃう
* アップデート時にはダウンタイムが発生しないようAct-Sby構成を自動で作って切り替え

### No we can't...

以下は手動で設定する必要がありんす。手動ならできた。

* あらかじめEBで指定できる項目を超えた制御

例)
ロードバランサにHTTP、HTTPS以外の項目の追加（自動生成されたELBの設定を変更すれば可能 => Terminateすると設定消える）
自動起動したインスタンスに指定したElastic IPをAssociateする（[コマンドラインインターフェース](http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/set-up-ec2-cli-linux.html)を使わないと無理だよねー、ただ自動起動されたインスタンスをどう特定させるか作り込みが難しそう）
元々生成済みのインスタンスやリソースを使い回す => とにかく新しいのができちゃう。古いのは消える。来るもの拒まず、去る者追わず精神。




できる事、できない事がわからないまま始めたのでここまで調べ上げるのに結構な時間を使ってしまった。。
以下Yes we can!


## アプリケーションの構築

Elastic Beanstalkではアプリケーションという概念で設定を管理する。
AWS Management Consoleにログインして中央下部にあるElastic Beanstalkをクリック。

![AWS Management Console TOP](https://qiita-image-store.s3.amazonaws.com/0/15518/b5e26061-bc16-9500-f139-d8f4ecaf6c74.png "AWS Management Console TOP")




Elastic Beanstalkのトップ、詳細を設定したいので右上のCreate Applicationをクリック
もろもろ設定を進める。
調べるとコマンドラインツールを使ったセットアップ方法が沢山なので、ここではAWS Management Consoleから。
うっかり中央のLaunch Nowを押してしまいそうになるけど、ここを使うと全てデフォルト設定で起動されてしまうため困る。。

![Elastic Beanstalk](https://qiita-image-store.s3.amazonaws.com/0/15518/762c341d-7971-1c16-957e-e07a180bc27e.png "Elastic Beanstalk TOP")


### アプリケーション概要設定
![スクリーンショット 2014-04-20 18.10.18.png](https://qiita-image-store.s3.amazonaws.com/0/15518/68ae28eb-f64f-3560-1b4a-69dceddc9d9a.png "スクリーンショット 2014-04-20 18.10.18.png")

### 環境設定
この時点で既に空のアプリケーションができている。なので途中で中断しても平気。
続いてこのアプリケーションに環境という概念を追加していく。開発用、本番公開用とか。ブランチやね。

![スクリーンショット 2014-04-20 19.20.35.png](https://qiita-image-store.s3.amazonaws.com/0/15518/74fdc8c1-55d5-16f1-c34e-fd42cf34952a.png "スクリーンショット 2014-04-20 19.20.35.png")

![スクリーンショット 2014-04-20 18.12.01.png](https://qiita-image-store.s3.amazonaws.com/0/15518/db2512c5-08cb-8b9b-adc2-ca83a1b18702.png "スクリーンショット 2014-04-20 18.12.01.png")

## 追加リソース
RDSとかVPCを追加するとかしないとか。AWSのRDSは最小構成でも割とお高いので使わない（無料利用範囲なら試すくらいしても・・・）。
![スクリーンショット 2014-04-21 12.23.47.png](https://qiita-image-store.s3.amazonaws.com/0/15518/3b7551c4-3e92-babc-5281-f69a27be818a.png "スクリーンショット 2014-04-21 12.23.47.png")

### EC2のインスタンス設定
起動するEC2インスタンスの詳細を設定する。
実運用ならc3.large〜あたりのファミリーが価格的に一番コスパがいい！
この設定は環境に紐づくので開発環境はt1.micro、本番は別のタイプでみたいな事ができる。うん、素晴らしい。
この記事見ながら作業を進めている方もしいましたらここの設定はちょっとコツが必要なので画像の下読んでから進めた方が良いかと。
![スクリーンショット 2014-04-21 12.25.32.png](https://qiita-image-store.s3.amazonaws.com/0/15518/43041b2f-7ba1-abb1-c047-50afa2287202.png "スクリーンショット 2014-04-21 12.25.32.png")

起動したEC2にsshアクセスするためのキーペアは事前に作成しておく。
新しいアカウントだったのでどこで作るんだっけ！？ってなったので解説すると
EC2 Dashboard => 左メニューの NETWORK & SECURITY => Key Pairs
からCreate Key Pairボタンで作成してダウンロードしておきます。
![スクリーンショット 2014-04-21 12.36.50.png](https://qiita-image-store.s3.amazonaws.com/0/15518/11508bdc-e4eb-9fa7-bfb3-ae516650923d.png "スクリーンショット 2014-04-21 12.36.50.png")

Application health check URLはLBがヘルスチェックするURL。
ここ、既にサイト構築済みでHCが通る状態なら入力してもいいんだけど、初回構築時はひとまず入力せず（デフォルトだと：http://環境名.elasticbeanstalk.com）というエイリアスでヘルスチェックを通しちゃうのがおすすめです。
ヘルスチェックが通らないと詳細な設定が変更できないため、、これはハマった・・・

あと気になるのがEnable Rolling Updates。これ何かと調べてみると
>Elastic Beanstalk環境のローリングアップデートを有効にすると、環境内のリクエストハンドリング能力とアップデートにかかる期間のバランスを設定できる。例えば、開発環境ではすべてのインスタンスを一斉にアップデートするけれど、本番環境では一部のインスタンスずつ行うといったことだ。

だってさ。キュンキュンしますね。
アップデート中はLBまでうまく操作してくれちゃうのかなー凄いなー！動作レポートは後々。
後からオフれるのでとりあえずチェックして進める。

リザーブドインスタンスとして扱う場合は購入したアベイラビリティゾーンと合わせる必要があるので、一旦起動後に設定を変更しないとあかんかった。なんでお金の事を考えると($0.06くらいだけど)microで起動 => 後で変更してみる。

### 設定内容確認
問題なければLaunch！
![スクリーンショット 2014-04-21 12.59.18.png](https://qiita-image-store.s3.amazonaws.com/0/15518/a13f59b2-3d81-0ee0-3995-6a2ac2a67984.png "スクリーンショット 2014-04-21 12.59.18.png")

ダッシュボードで構築ステータスを確認します。3分くらいはかかるかな。
![スクリーンショット 2014-04-21 13.03.35.png](https://qiita-image-store.s3.amazonaws.com/0/15518/65ec6e7a-b862-66a6-d69c-6b5a963da91f.png "スクリーンショット 2014-04-21 13.03.35.png")


## もっと設定
ある程度自動設定で起動されてしまうんですがもっと細かく設定したいんだ！
というわけでConfigurationから。
![スクリーンショット 2014-04-21 15.41.56.png](https://qiita-image-store.s3.amazonaws.com/0/15518/f2fc082f-31b4-acf5-cb9c-4e96e0de7f13.png "スクリーンショット 2014-04-21 15.41.56.png")


### Scaling

![スクリーンショット 2014-04-21 14.14.42.png](https://qiita-image-store.s3.amazonaws.com/0/15518/55a3292b-b164-6282-3bb9-254aebded945.png "スクリーンショット 2014-04-21 14.14.42.png")

リザーブドインスタンス持っててアベイラビリティゾーンを固定したい場合は
Availability ZonesをAny 1にして
Custom Availability Zones から購入したゾーンを指定する。インスタンスタイプはInstancesの方で変更。
SaveするとEC2が再構築される。

Scaling cooldownと次項のScaling Triggerは合わせて検討する。

スケールアップは早めに（余裕を持って）、Scaling cooldown はゆっくりと行うのがAutoScalingの定石。
参考：[Netflix のスケール - オートメーション編 ](http://surgo.jp/2012/09/netflix.html)
とても貴重な経験記事です。一読しましょう。


デフォルトでトリガーに設定されているのはNetworkOut(どういうシチュエーションを基準にしているのだ？？)
LatencyとかCPUUtillization、RequestCountあたりがWEBサービスなら使い勝手良さそう。

5分間で平均遅延が10秒を超えるとインスタンス追加、1秒以下になったらCool Downするよう設定してみた（未検証）
![スクリーンショット 2014-04-21 16.33.02.png](https://qiita-image-store.s3.amazonaws.com/0/15518/bc6dc256-e174-7814-ab37-92ef5919daaf.png "スクリーンショット 2014-04-21 16.33.02.png")

各設定値の詳細に関しては以下が詳しい
[オプションの値](http://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/command-options.html)

環境をTerminateするとここまでの設定内容毎全て消失します。
Fixした環境設定はActionからSave Configrationしておくと安心です。


## もっともっと設定

まだ足りないんじゃー！PHPの設定もWEBサーバも変えたいし、何もかも足りないんじゃー！！
という事で更に細かく設定するにはebコマンド使ったデプロイする方法が早いと思い試してみた。
設定ファイルを作り込む必要があります面倒です。
たぶんEBはここが肝。

> アプリケーションをデプロイするときは、アプリケーションが依存するソフトウェアをカスタマイズおよび設定したい場合があります。このようなファイルとしては、アプリケーションで必要な依存関係（yum リポジトリからの追加パッケージなど）や、AWS Elastic Beanstalk でデフォルトの特定の設定を上書きするための httpd.conf の代わりの設定ファイルなどがあります。また、AWS Elastic Beanstalk 環境の一部である環境リソースをカスタマイズしたいこともあります（SQS キュー、ElastiCache クラスターなど）。例えば、Amazon SQS キューおよびキューの深さに対するアラームを追加したり、Amazon ElastiCache クラスターを追加したりする場合です。

ソースバンドルと共に設定ファイルを含めることにより、アプリケーションバージョンのデプロイと同時に環境を簡単にカスタマイズできます。インスタンスのソフトウェアをカスタマイズするときは、独自 AMI をカスタマイズするより設定ファイルを使用する方が、AMI のセットを保持する必要がないので優っています。 


ですっってー優ってるぅー！！！

参考：[公式ドキュメント](http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers.html)

まずは作業環境を整えます。

### ebコマンドをインストール
[[AWSマイスターシリーズ] AWS Elastic Beanstalk](http://aws.amazon.com/code/6752709412171743)


解凍したディレクトリ内のebコマンドに各OSに合わせてパスを通す。
うちのOS Xちゃんは以下な感じで

```bash

$ echo 'export PATH="$HOME/.AWS-ElasticBeanstalk-CLI-2.2/eb/macosx/python2.7:$PATH"' >> .bashrc
$ source .bashrc
$ eb --help

```

ebコマンドはgitをwrapした様な作りになってる（git必須）。
なので作業（ソース）ディレクトリは事前にgit initしておく必要がある。
作業ディレクトリ直下で以下進める。
アプリ名と環境名が合っていればUI側で作成した既に存在する環境として環境情報を勝手に拾ってきたー。

```bash

$ eb init
Enter your AWS Access Key ID: [IAMユーザのAccess Key]
Enter your AWS Secret Access Key: [IAMユーザのSecret Access Key]
1) US East (Virginia)
2) US West (Oregon)
3) US West (North California)
4) EU West (Ireland)
5) Asia Pacific (Singapore)
6) Asia Pacific (Tokyo)
7) Asia Pacific (Sydney)
8) South America (Sao Paulo)
Select (1 to 8): [使用するリージョン]
Enter an AWS Elastic Beanstalk application name (auto-generated value is "repo.hihin.git"): [上で作っておいたapplication name]
Enter an AWS Elastic Beanstalk environment name (auto-generated value is "hihinjp-env"): [環境名（開発とか本番）※.(ドット)を使用するとドメイン周りでトラブる可能性があるので注意]

Select an environment tier.
Available environment tiers are:
1) WebServer::Standard::1.0
2) Worker::SQS/HTTP::1.0
Select (1 to 2): 1
Select a solution stack.
Available solution stacks are:
1) 32bit Amazon Linux 2014.02 v1.0.1 running PHP 5.4
2) 64bit Amazon Linux 2014.02 v1.0.1 running PHP 5.4
3) 32bit Amazon Linux 2014.02 v1.0.1 running PHP 5.5
4) 64bit Amazon Linux 2014.02 v1.0.1 running PHP 5.5
5) 32bit Amazon Linux 2013.09 v1.0.1 running PHP 5.4
6) 64bit Amazon Linux 2013.09 v1.0.1 running PHP 5.4
7) 32bit Amazon Linux 2013.09 v1.0.1 running PHP 5.5
8) 64bit Amazon Linux 2013.09 v1.0.1 running PHP 5.5
9) 32bit Amazon Linux running PHP 5.3
10) 64bit Amazon Linux running PHP 5.3
11) 32bit Amazon Linux 2014.02 v1.0.1 running Node.js
12) 64bit Amazon Linux 2014.02 v1.0.1 running Node.js
13) 32bit Amazon Linux 2013.09 v1.0.1 running Node.js
14) 64bit Amazon Linux 2013.09 v1.0.1 running Node.js
15) 64bit Windows Server 2008 R2 running IIS 7.5
16) 64bit Windows Server 2012 running IIS 8
17) 32bit Amazon Linux 2014.02 v1.0.1 running Tomcat 7 Java 7
18) 64bit Amazon Linux 2014.02 v1.0.1 running Tomcat 7 Java 7
19) 32bit Amazon Linux 2014.02 v1.0.1 running Tomcat 7 Java 6
20) 64bit Amazon Linux 2014.02 v1.0.1 running Tomcat 7 Java 6
21) 32bit Amazon Linux 2013.09 v1.0.1 running Tomcat 7 Java 7
22) 64bit Amazon Linux 2013.09 v1.0.1 running Tomcat 7 Java 7
23) 32bit Amazon Linux 2013.09 v1.0.1 running Tomcat 7 Java 6
24) 64bit Amazon Linux 2013.09 v1.0.1 running Tomcat 7 Java 6
25) 32bit Amazon Linux running Tomcat 7
26) 64bit Amazon Linux running Tomcat 7
27) 32bit Amazon Linux running Tomcat 6
28) 64bit Amazon Linux running Tomcat 6
29) 32bit Amazon Linux running Python
30) 64bit Amazon Linux running Python
31) 64bit Amazon Linux 2014.03 v1.0.1 running Ruby 2.0 (Puma)
32) 64bit Amazon Linux 2014.03 v1.0.1 running Ruby 2.0 (Passenger Standalone)
33) 32bit Amazon Linux 2014.02 v1.0.1 running Ruby 1.8.7
34) 64bit Amazon Linux 2014.02 v1.0.1 running Ruby 1.8.7
35) 32bit Amazon Linux 2014.02 v1.0.1 running Ruby 1.9.3
36) 64bit Amazon Linux 2014.02 v1.0.1 running Ruby 1.9.3
37) 32bit Amazon Linux 2013.09 v1.0.1 running Ruby 1.8.7
38) 64bit Amazon Linux 2013.09 v1.0.1 running Ruby 1.8.7
39) 32bit Amazon Linux 2013.09 v1.0.1 running Ruby 1.9.3
40) 64bit Amazon Linux 2013.09 v1.0.1 running Ruby 1.9.3
41) 64bit Amazon Linux 2013.09 v1.0.1 running Python 2.7
42) 64bit Amazon Linux 2013.09 v1.0.1 running Python
43) 32bit Amazon Linux 2013.09 v1.0.1 running Python 2.7
44) 32bit Amazon Linux 2013.09 v1.0.1 running Python
Select (1 to 44): [使用するソリューション]
Select an environment type.
Available environment types are:
1) LoadBalanced
2) SingleInstance
Select (1 to 2): [ロードバランサ使うかどうか]
reate an RDS DB Instance? [y/n]: [RDS使うかどうか]
Attach an instance profile (current value is "[Create a default instance profile]"):
You IAM user does not have sufficient permission. User: arn:aws:iam::324691443829:user/developer is not authorized to perform: iam:ListInstanceProfiles on resource: arn:aws:iam::324691443829:instance-profile/
Do you want to proceed without attaching an instance profile? [y/n]:
1) [Create a default instance profile]
2) aws-elasticbeanstalk-ec2-role
3) [Other instance profile]
Select (1 to 3): 1
Updated AWS Credential file at "/Users/[ユーザ]/.elasticbeanstalk/aws_credential_file".

```

これで初期設定が完了。.git/configにエイリアスが追加されとるがな。
起動してみると

```bash

$ eb start
Start application [アプリケーション名]
Environment "[環境名]" already exists. Skipped creating.

```

スキップ、そしてworkspace/.ebextensions/
にoptionsettings.[環境名]ファイルが作成され、UIで設定しておいた情報が引き継がれている事がわかります。


### 詳細設定ファイルを作成

やってここまできたこれ。実際2日かかってるんだからね！
構成は以下のようにすべしとの事。上から順に実行される。

* workspace/.ebextensions/各設定ファイル.config
* workspace/.elasticbeanstalk/アプリケーション・環境設定ファイル
* workspace/opt/elasticbeanstalk/hooks/appdeploy/pre/*
* workspace/opt/elasticbeanstalk/hooks/appdeploy/enact/*
* workspace/opt/elasticbeanstalk/hooks/appdeploy/post/* 
* workspace/optionsettings.[環境名]
* workspace/その他配置するファイル達

デプロイするにはgitブランチとebブランチをマップしておきます。
関連コマンド一覧しときます。

* ブランチ一覧： git branch
* ブランチ作成： git branch [gitブランチ名]
* ブランチ切り替え：git checkout [gitブランチ名]
* 現在ブランチとEB環境をマップ： eb branch
* 現在ブランチがマップしているEB環境にデプロイ： git aws.push
* 別EB環境を指定してデプロイ： git aws.push --environment [eb環境名]
* コミット指定デプロイ： git aws.push --commit [コミット番号]
* 環境の更新： eb update
* 環境の停止： eb stop


デプロイする時はサーバ上で/var/log*をtailしておくか終了時にログを確認した方が良いでしょう。
特に/var/log/eb-tools.logにデプロイ操作がロギングされます。
EBのWEBコンソールの各環境のEventsにも文法エラー等が出力されます。うまく動かないときはチェックしてみましょう。
ちなみに僕は.ebextensionsに置くべきファイルを.elasticbeanstalkに置いたり、
YAMLにタブを打ったりスペーシングミスして引っかかり無駄な半日を過ごしましたとさ。
この辺りのスクリプト起動時のログは/var/log/cfn-init.logにロギングされるよう。
設定ファイル内でファイルを作成した場合、自動で削除される事はないのでリネーム時はきちんと削除しないと、
なんか前に定義した処理が残ってる的なシチュにぶつかる。デプロイには時間がかかるのでこの時間がモッタイナイ。

無理矢理設定ファイル内で全てやろうとするとどこかで不足な事態がおきそうな気がするので
workspace直下のファイル達が/var/app/current/に配置されるのを利用して
シェルでここからコピー、配置していくとすっきりさせられる印象。


設定ファイル長くなったんでソースはgithubに置いておきます。
以下やった事簡単に。

### ユーザまわり

ec2-userとかセキュリティ的に削除、ログインユーザ生成、RSA設定とか。


### Apaceh => Nginxに変更

デフォルトのapacheを停止して、Nginx、php-fpm、memcacheをデプロイします。


### EB上のphp.iniを変更

オプションだと項目が少なすぎるのでデプロイ時にphp.iniを書き換えようという発想は世の常。
起動されているサーバを覗いてみたところ、我が城では
php.ini => php-5.5.ini のSymbolic link
php.dはphp-5.5.dのSymbolic link
になってる。ならばやる事は一つ、php.dの下にアプリ用のiniを突っ込んであげればOK。

なぞなぞ。
こんか感じでカスタマイズしていけば色々いじれそう！


## 困った事とか

EBで環境をstartするとリソースが自動で生成されまくる。EC2とかELBとかSecurityGroupとか、各々細かく設定したい時はそれぞれの設定をいじくる必要がった。
で、ちょっとリセットしたくて環境を再起動したりすると残念な事になるという。
特にTerminateしちゃうとELBが変わってDNSレコードを書き換えなければという作業が特に残念。


以上、運用して何かあれば随時追記予定。



参考：
[PHP で AWS Elastic Beanstalk アプリケーションをデプロイする](http://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/create_deploy_PHP_eb.html)
[http://www.slideshare.net/AmazonWebServicesJapan/aws-aws-elastic-beanstalk](http://www.slideshare.net/AmazonWebServicesJapan/aws-aws-elastic-beanstalk)


参考
http://lab.sonicmoov.com/development/elastic-beanstalk/
http://dev.classmethod.jp/cloud/aws/aws-elastic-beanstalk-rails/
http://dx.24-7.co.jp/beanstalk/
http://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/troubleshooting.html