AutoScalingGroupのインスタンス起動・停止をSlackに通知する

AutoScalingGroupの作成からSNSとLabmdaと連携してイベントをSlackに通知するところまで。


# LaunchConfigurationの作成

AutoScalingGroupingを作るためにはLaunchTemplate, LaunchConfigurationNameまたはInstanceIdが必要なので今回はLaunchConfigurationを作成します。

```bash
$ aws autoscaling create-launch-configuration \
  --launch-configuration-name sample-auto-scale-launch-configration \
  --instance-type t2.micro \
  --image-id ami-bf4193c7
  --key-name xxxxx
```

# AutoScalingGroupの作成

先ほど作成したLaunchConfigurationを指定してAutoScalingGroupを作成します。

```bash
$ aws autoscaling create-auto-scaling-group \
  --auto-scaling-group-name sample-auto-scale \
  --min-size 1 --max-size 5 \
  --launch-configuration-name sample-auto-scale-launch-configration \
  --availability-zones us-west-2a us-west-2b
```

# インスタンスの起動・停止を通知する

AutoScalingGroupからインスタンスのイベントを受け取る方法は [LifeCycleHook](http://docs.aws.amazon.com/ja_jp/autoscaling/latest/userguide/lifecycle-hooks.html#sns-notifications)でもできそうですが、今回は[SNSを使った方法](http://docs.aws.amazon.com/ja_jp/autoscaling/latest/userguide/ASGettingNotifications.html)でやってみます。

## SNSのトピックを作成する

AutoScalingGroupのイベントを通知するためのTopicを作成します。

```
$ aws sns create-topic --name sample-auto-scale-notification
```

## AutoScalingGroupのイベントをSNSと紐付ける

NotificationConfigurationを追加します。
今回は以下の４つのイベントをSNSで通知するようにしました。

- EC2_INSTANCE_LAUNCH
- EC2_INSTANCE_LAUNCH_ERROR
- EC2_INSTANCE_TERMINATE
- EC2_INSTANCE_TERMINATE_ERROR

```
$ aws autoscaling put-notification-configuration \
  --auto-scaling-group-name sample-auto-scale \
  --topic-arn arn:aws:sns:us-west-2:999999999999:sample-auto-scale-notification 
  --notification-types "autoscaling:EC2_INSTANCE_LAUNCH" "autoscaling:EC2_INSTANCE_LAUNCH_ERROR" "autoscaling:EC2_INSTANCE_TERMINATE" "autoscaling:EC2_INSTANCE_TERMINATE_ERROR"
```

## SNSからSlackに通知するLambdaを作成する

pythonでSlackへ通知するLambdaを作成していきます。

<img width="1126" alt="sns-to-slack-notificatioin-lambda.png" src="https://qiita-image-store.s3.amazonaws.com/0/32184/823e49fc-650b-e9e4-0ada-6c4e840b82a7.png">

```python
import urllib.request
import json

def lambda_handler(event, context):
    url = 'https://hooks.slack.com/services/AAAAAAAAA/BBBBBBBBB/CCCCCCCCCCCCCCCCCCCCCCCC'
    method = "POST"
    headers = {"Content-Type" : "application/json"}
    obj = {"text":json.dumps(event)}
    json_data = json.dumps(obj).encode("utf-8")
    request = urllib.request.Request(url, data=json_data, method=method, headers=headers)
    with urllib.request.urlopen(request) as response:
        response_body = response.read().decode("utf-8")

    return response_body
```

## LambdaにSNSをsubscribeさせる

```
$ aws sns subscribe \
  --topic-arn arn:aws:sns:us-west-2:999999999999:sample-auto-scale-notification \
  --protocol lambda \
  --notification-endpoint arn:aws:lambda:us-west-2:999999999999:function:sns-to-slack-notification
```

SNSがLambdaを起動できるようにpermissionを与えます。

```
$ aws lambda add-permission \
  --function-name sns-to-slack-notification \
  --statement-id autoscaling-sns-to-lambda \
  --action "lambda:InvokeFunction" \
  --principal sns.amazonaws.com \
  --source-arn arn:aws:sns:us-west-2:999999999999:sample-auto-scale-notification
```

# インスタンスを追加して通知を受け取る

`AutoScalingGroup -> SNS -> Lambda`の設定ができたので実際にインスタンスを追加して通知を確認します。
`desired-capacity`を増やし、インスタンスを１つ起動します。

```
$ aws autoscaling set-desired-capacity \
  --auto-scaling-group-name sample-auto-scale \
  --desired-capacity 2
```

インスタンスが起動されSlackに通知がきました。

<img width="404" alt="スクリーンショット 2017-12-10 14.50.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/32184/1b77e08c-32fc-2922-95fa-9c9ab97e9291.png">