CDP Advent Calendar 2012に登録しました。ここ1年ちょいで使い慣れてきたパターンがあり、作った当時はクラウドデザインパターンはなかったのですが、Clone ServerとScale Outパターンの組合せに当てはまると思うので紹介します。ちなみにアプリはRails。
常にデプロイして更新し続けるシステムを手動、あるいは自動スケールアウトする時に便利な手法だったりします。
図にするとこんな感じですかね。
Auto Scaling設定
Launch Config
まず、ベースとなるAMIの起動インスタンスサイズやセキュリティーグループを定義したLaunch Configを設定。
as-create-launch-config cdp-lc --image-id ami-22a51d23 --instance-type m1.small \
--group cdp_web, cdp_admin
Scaling Group
次に、Scaling Groupで適用するAvailability Zone、インスタンス数の最小・最大閾値設定、紐尽くELB、死活監視方法・開始待ち時間、タグ等を定義。(ec2addtagではスペース入りのキーを設定できるのにas-create-auto-scaling-groupではできないので注意。早く直して。。)
as-create-auto-scaling-group cdp-sg --launch-configuration cdp-lc \
--availability-zones ap-northeast-1a --min-size 1 --max-size 9 --load-balancers cdp \
--health-check-type ELB --grace-period 300 --tag "k=Name, v=web.cdp" --tag "k=Use_Case, v=Test"
Scaling Out Policy
Scaling Outのポリシー設定。以下の例ではインスタンス1台を追加し、次のスケールアクションまでは5分間待機。ポリシーのARN (Amazon Resource Name)が出力されるので控えます。
as-put-scaling-policy CDPOut --auto-scaling-group cdp-sg --adjustment 1 --type ChangeInCapacity \
--cooldown 300
> arn:aws:autoscaling:ap-northeast-1:494850320039:scalingPolicy:d0d4dcf1-fb44-428a-a19c-38946633acf5:autoScalingGroupName/cdp-sg:policyName/CDPOut
Cloudwatchトリガー(Scaling Out)
Cloudwatchで閾値を超えたらスケールアウトするように設定。以下の例では対象Scaling Group配下のインスタンス達のCPUが1分間で平均75%以上で推移した場合、先ほど設定したScaling OutポリシーがARN経由で実行されます。また、閾値を超過あるいは下回った場合にSNS経由でアラートメールを飛ばします。
mon-put-metric-alarm CDPHighCPUAlarm --comparison-operator GreaterThanThreshold \
--evaluation-periods 1 --metric-name CPUUtilization --namespace "AWS/EC2" --period 60 \
--statistic Average --threshold 75 --dimensions "AutoScalingGroupName=cdp-sg" \
--ok-actions arn:aws:sns:ap-northeast-1:494850320039:cdp-alert --alarm-actions \
arn:aws:sns:ap-northeast-1:494850320039:cdp-alert, arn:aws:autoscaling:ap-northeast-1:494850320039:scalingPolicy:d0d4dcf1-fb44-428a-a19c-38946633acf5:autoScalingGroupName/cdp-sg:policyName/CDPOut
Scaling Down Policy
同じくScaling Downのポリシー設定。インスタンスが起動すると最低1時間は課金されるので頻繁に伸縮するともったいないのでスケールダウンアクションはゆっくりやるのがポイントです。
as-put-scaling-policy CDPDown --auto-scaling-group cdp-sg --adjustment=-1 \
--type ChangeInCapacity --cooldown 1500
> arn:aws:autoscaling:ap-northeast-1:494850320039:scalingPolicy:de53fbd5-130c-46a8-bf47-25e29f7d358e:autoScalingGroupName/cdp-sg:policyName/CDPDown
Cloudwatchトリガー(Scaling Down)
スケールダウンのトリガーは平均CPUが35%を25分間下回った場合に実行されます。この閾値周辺のアラートメールはいらないので設定してません。
mon-put-metric-alarm CDPLowCPUAlarm --comparison-operator LessThanThreshold \
--evaluation-periods 1 --metric-name CPUUtilization --namespace "AWS/EC2" --period 1500 \
--statistic Average --threshold 35 --dimensions "AutoScalingGroupName=cdp-sg" --alarm-actions \
arn:aws:autoscaling:ap-northeast-1:494850320039:scalingPolicy:de53fbd5-130c-46a8-bf47-25e29f7d358e:autoScalingGroupName/cdp-sg:policyName/CDPDown
通知
最後にスケールアクション時に通知が飛ぶように設定。例えば、あるインスタンスが不調により反応がなく、ポリシーによってリプレースされる場合に飛んだりします。
as-put-notification-configuration cdp-sg -t arn:aws:sns:ap-northeast-1:494850320039:cdp-alert \
-n autoscaling:EC2_INSTANCE_LAUNCH, autoscaling:EC2_INSTANCE_TERMINATE, \
autoscaling:EC2_INSTANCE_LAUNCH_ERROR, autoscaling:EC2_INSTANCE_TERMINATE_ERROR
APP側の設定
ソースコード同期
同期には起動時にupstart経由でrsyncを叩いて管理サーバから最新ソースを取ってきてサービスを再起動します。転送時の圧縮モードはarcfourが一番スループットが出たのでそれに。
Capistrano
デプロイはマスターサーバ(管理兼)上でCapistranoを実行し、ELB配下の生きているインスタンスに対して更新をかけます。deploy.rbに追加する記述は以下の通り。昔はec2 api toolsを直接呼んでパースしたりしてコードが長かったのですが、今はAWS SDK for Rubyがあり、IAM roleでinstance profileを設定すればわずか数行でできてしまいます!
1 2 3 4 5 |
|
注意点
- 同期するファイル数が多すぎる(数十万個)と、チェックサム比較で時間がかかってしまい同期が終了する前にAuto Scalingの死活監視によってインスタンスがterminateされ、またlaunchされterminateされるという恐怖のスケールループ地獄に陥る。。。(これ、制限できないのかな)
- あらかじめトラフィック増の時間帯が分かっていたらScheduled Actionで多めに設定しておいて自動スケールダウンさせた方が吉。
- マスタサーバがSPOFとなりうるので冗長化する、もしくはrsyncよりs3経由にした方が良い。
- 急激なトラフィック増ではELB自体のスケールが追いつかない場合も。