슬랙 채널에 EC2 인스턴스가 떨어졌음을 알리도록 해 보았습니다.

배경



때때로 개발 환경의 EC2 인스턴스가 마음대로 떨어질 수 있으며, 깨달은 사람의 문의로 매번 수동으로 EC2 인스턴스를 다시 시작했습니다.
개발자들이 개발에 집중할 수 있도록 자동으로 통지해주는 구조를 구축했습니다.

구현 목록


  • Slack 채널이 EC2 인스턴스가 중지되었음을 알릴 수 있도록합니다.
  • stopped가되면 자동으로 재부팅 할 수 있습니다
  • 위의 기능을 9:00 ~ 21:00 사이로 제한 할 수 있습니다

  • 9:00~21:00 사이에 제한을 두고 있는 이유입니다만, 개발 환경에서는 비용 개선을 위해 21시가 되면, 자동으로 개발 환경의 모든 EC2 인스턴스가 shutdown 되어 다음날 아침 9시가 되면 자동으로 시작할 수 있도록 하고 있습니다.
    따라서 위의 기능이 21시 이후에도 유효하게 되어 버리면, 몇개의 EC2 인스턴스의 스테이터스 통지가 Slack 채널을 메울 뿐만 아니라, 심야 이른 아침에도 개발 환경이 계속 기동될 우려가 있습니다.

    사용 도구


  • CloudWatch Event
  • Lambda
  • Incoming Webhook

  • 절차



    ①Slack에서 Incoming Webhook 앱 설치
    어떤 서비스 정보를 Slack 채널에 알리기 위해서는 Incoming Webhook이라는 Slack 앱을 활용하여 실현 가능합니다. 공식 사이트
    설치 후 서비스 정보를 공유할 Slack 채널을 선택하고 WebhookURL을 삼가해 둡니다.

    ② Lambda 함수 작성
    새로 Lambda 함수를 만들고 다음 함수를 작성합니다.


    lambda_function.py
    from __future__ import print_function
    from time import strptime, strftime
    
    import os, json, boto3, urllib.request
    
    #GMT表記
    before = strptime('00:00:00', '%H:%M:%S')
    after = strptime('11:59:00', '%H:%M:%S')
    now = strptime(strftime('%H:%M:%S'), '%H:%M:%S')
    
    print(now)
    
    #自動起動/シャットダウンバッチに引っかからないようにJST9:00-JST21:00の間で処理を動かすようにしている
    if (now >= before and now <= after):
    
       #変数eventの中身がCloudWatch Eventから受け取ったEC2インスタンスのstop
       def lambda_handler(event,context):
    
          instances = [ event ]
          region = 'ap-northeast-1'
          ec2 = boto3.client('ec2', region_name=region)
    
          #色付きメッセージ発行
          attachments = {
            'attachments': [{
              # titleのリンクをクリックするとtitle_linkで設定したページへ飛びます。
              'title': 'EC2が停止しました。',
              'title_link': 'https://api.slack.com/docs/message-attachments',
              'color': "warning",
            }]
          }
    
          req = json.dumps(attachments).encode('ascii')
    
          message_color = urllib.request.Request(os.environ['slackUrl'], req )
    
          try:
             response = urllib.request.urlopen(message_color)
             response.read()
    
          except Exception as e:
             print(e)
    
          #インスタンスの起動停止メッセージ
          message_stop = {
             'text': "<!here> EC2 Instance " + (event) + " stopped"
          }
    
          data = json.dumps(message_stop).encode('ascii')
    
          req = urllib.request.Request(os.environ['slackUrl'], data )
          try:
              response = urllib.request.urlopen(req)
              response.read()
    
              print("Message posted: %s" % message_stop )
          except Exception as e:
              print(e)
    
          #停止したインスタンスの再起動
          ec2.start_instances(InstanceIds=instances)
          message_restart = {
             'text': "started your instances: " + str(instances)
          }
    
          data2 = json.dumps(message_restart).encode('ascii')
    
          req = urllib.request.Request(os.environ['slackUrl'], data2 )
          try:
              response = urllib.request.urlopen(req)
              response.read()
    
              print("Message posted: %s" % message_restart )
          except Exception as e:
              print(e)
    
       #自動起動/シャットダウンが走る9時前、21時以降は処理をさせない
    else:
       print("out time of function")
    
    

    함수 내에서 정의되지 않은 변수 slackUrl은 Lambda 측에서 가져온 WebhookURL을 설정했습니다.

    ③CloudWatch Event에서 Lambda 함수가 발동하는 규칙을 작성한다.
    EC2 인스턴스가 중지된 후 방금 만든 Lambda 함수를 시작할 수 있도록 규칙을 만듭니다.

    이때, Lambda 함수에 건네주는 입력 내용을 짜내는 것으로 Slack 채널에 표시되는 내용을 보기 쉬운 것으로 가공할 수 있습니다.
    ※전표시의 경우(일부 모자이크 처리)

    이상으로 Slack 채널에 통지하는 순서가 완료되었습니다. 마지막으로 EC2 인스턴스를 중지하여 Slack 채널에 알림을 받고 다시 시작할 수 있는지 확인합니다.

    제대로 구현하고 싶었던 것을 할 수 있게 되었습니다.

    소감



    AWS와 Slack의 연동 방법으로는 CloudWatch Alarm에서 Lambda를 건너뛰고 Slack 채널로 알람 내용을 연계하는 방법이 일반적이며, 검색하면 많은 기사가 나오고 Lambda 함수에도 그것에 대한 템플릿이 있습니다.
    또한 최근 AWS와 Slack이 제휴를 발표하고 각 서비스의 연결이 향후 점점 강해질 것으로 보입니다. 참고 링크
    최근에는 AWS Chatbot에서 쉽게 AWS 서비스의 내용을 Slack에 제휴하기 쉬워졌습니다만, 아직 제공할 수 있는 서비스가 적기 때문에 CloudWatch Event에서도 대응할 수 있게 되면 검증해 보고 싶습니다.

    좋은 웹페이지 즐겨찾기