接收到 SNS Health Check 失敗後使用 Lambda reboot EC2

1. 先使用 Route 53 Health Checks 建立通知

2. 接著設定 Get notified when health check fails,如果沒有建立過 SNS topic 先要先建立(這邊舉例 topic 名稱為 MyServerFail),建立完成的 topic 可以在 AWS Simple Notification Service 裡管理

可以在 AWS SNS 裡面管理 topics

3. 因為我在 Lambda 上的程式碼需要從 SNS 裡設定的 Tags 抓取 EC2 Instance name 來重新啟動,所以需要在 AWS SNS 裡設定 Tags

Edit topic 的最下方可以新增 tag

4. 建立 Lambda Function

開啟 Lambda console,選擇 create function 輸入 function 名稱(例:auto-reboot-when-health-check-fail),runtime 選擇 Python 2.7,Execution role 的部份因為要使用 Lambda 在 health check 通知不正常時重新啟動 ec2 instance 所以需要有 AmazonEC2FullAccess ,如果你想要觀察 Lambda function print 出的訊息另外需要 CloudWatchLogsFullAccess

使用 Add trigger 加入觸發條件

5. 在 Function code 的位置貼上下列程式碼

變數 region 為服務區域的代號,這裡可以查詢。

import boto3

region = 'ap-northeast-1'
ec2 = boto3.resource('ec2')

def lambda_handler(event, context):
    # 將 SNS 裡設定的 tags 取出,用來辨別需要重啟哪個 instance
    tag = event['Records'][0]['Sns']['Tags'][0]
    #print("Tag Key: " + tag['Key'] + " / Value: " + tag['Value'])
    
    filters = [{
        'Name': 'tag:Name',
        'Values': [tag['Value']]
    }]
    
    instances = ec2.instances.filter(Filters=filters)
    RunningInstances = [instance.id for instance in instances]

    if len(RunningInstances) > 0:
        # 找到對應 tag 的 instance
        #print("instance.id : " + RunningInstances[0])
        ec2Client = boto3.client('ec2', region_name=region)
        ec2Client.reboot_instances(InstanceIds=[RunningInstances[0]])
        print('reboot your instances: ' + RunningInstances[0])
    else:
        print("none found")

6.接下來可以使用 test event 來測試

{
  "Records": [
    {
      "EventSource": "aws:sns",
      "EventVersion": "1.0",
      "EventSubscriptionArn": "你的 SNS ARN",
      "Sns": {
        "Type": "Notification",
        "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
        "TopicArn": "arn:aws:sns:ap-northeast-1:123456789012:ExampleTopic",
        "Subject": "My Server Health Low",
        "Message": "My Server Health Low",
        "Tags": [
          {
            "Key": "Name",
            "Value": "你在 SNS topic 裡設定的 EC2 Instance Name"
          }
        ]
      }
    }
  ]
}

設定好之後關閉設定視窗就可以按下 Test 來測試看看了,按照設定的話接收到測試的 SNS 之後該對應的 EC2 Instance 就會重啟了。

以上就是我設定使用 Health check 來偵測,然後通知 Lambda 重啟 EC2 Instance 的方式,歡迎討論。