はじめに
クラスメソッドさんの記事を参考にAmazon ECSでオートスケールを実装する。
この記事の通りに設定していけば問題はないが,1点サービスを相対的に+1/-1しかできない部分を改善した。
SNSで送られてくるメッセージの確認
実際に送られくるSNSを確認するためにログに出力(console.log(event.Records[0].Sns);
)すると以下の情報が送られてきていることがわかる。
{ Type: 'Notification', MessageId: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', TopicArn: 'arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:test', Subject: 'Auto Scaling: launch', Message: '{"StatusCode":"InProgress","Service":"AWS Auto Scaling","AutoScalingGroupName":"EC2ContainerService-default-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX-EcsInstanceAsg-XXXXXXXXXXXX","Description":"Launching a new EC2 instance: i-XXXXXXXX","ActivityId":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX","Event":"autoscaling:EC2_INSTANCE_LAUNCH","Details":{"Availability Zone":"ap-northeast-1a","Subnet ID":"subnet-XXXXXXXX"},"AutoScalingGroupARN":"arn:aws:autoscaling:ap-northeast-1:XXXXXXXXXXXX:autoScalingGroup: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX:autoScalingGroupName/EC2ContainerService-default-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX-EcsInstanceAsg-XXXXXXXXXXXX","Progress":50,"Time":"2015-10-10T03:31:23.470Z","AccountId":"XXXXXXXXXXXX","RequestId":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX","StatusMessage":"","EndTime":"2015-10-10T03:31:23.470Z","EC2InstanceId":"i-5cb264f9","StartTime":"2015-10-10T03:30:20.410Z","Cause":"At 2015-10-10T03:29:53Z a user request executed policy scale-out changing the desired capacity from 2 to 4. At 2015-10-10T03:30:18Z an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 2 to 4."}', Timestamp: '2015-10-10T03:31:23.503Z', SignatureVersion: '1', Signature: 'XXXXXXXXXXXX', SigningCertUrl: 'https://sns.ap-northeast-1.amazonaws.com/XXXXXXXXXXXX.pem', UnsubscribeUrl: 'https://sns.ap-northeast-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:test:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', MessageAttributes: {} }
記事ではSNSのSubjectに含まれる launch/termination を検出してそれぞれ +1/-1 を行なってた。
ここで本文であるMassageに注目するとJSONになっていてわかり辛いが以下のように書かれている。
"Cause":"At 2015-10-10T03:29:53Z a user request executed policy scale-out changing the desired capacity from 2 to 4. At 2015-10-10T03:30:18Z an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 2 to 4."
このメッセージからAuto Scaling後のcapacityを知ることができそうだ。前半はdesired capacityで後半が実際のcapacityになっているように読める。
Capacityの取得
SNSの本文にcapacityが記載されていることがわかったので正規表現を使ってcapacityを取得する。
var matches = JSON.parse(event.Records[0].Sns.Message).Cause.match(/the capacity from (\d+) to (\d+)./);
var currentCapacity = parseInt(matches[1]);
var desiredCapacity = parseInt(matches[2]);
capacityが取得できたのでこれをECSのServiceのdesiredCountにすればよい。
コードの全体はクラスメソッドさんの記事にあるので割愛。
まとめ
SNSの本文からAuto ScalingのCapacityが取得できることがわかったので,これをECSのServiceのdesiredCountすることでAuto ScalingとServiceを連動できるようにした。
この方法はクラスタ内の80%でServiceを起動するなどの応用もできると思う。