【AWS CDK】AWS CloudWatch Alarms로부터의 메시지를 Google Hangouts Chat에 자동 통지하는 구성을 속공으로 만든다

AWS CloudWatch Alarms의 메시지를 Google Hangouts Chat에 알리고 싶으신가요?
이번에는 그 구성을 CDK로 작성해 보았습니다.

환경



CDK CLI: 1.32.0
로컬 노드: 11.15.0

구성



이번에는, trigger-chat-cdk 라고 하는 Lambda 함수를 감시 대상으로 해, 「1분에 2회 이상, 함수가 불려 가면 에러를 든다」라고 하는 조건을 설정합니다.


이하는 순서가 됩니다만, 이 리포지토리 를 clone 하면, 순서의 3,4 는 생략할 수 있으므로, 보다 속공으로 만들 수 있을까 생각합니다.

1. Hangouts Chat의 Webhook URL 만들기



먼저 사전 준비를 위해 Hangouts Chat의 Webhook URL을 만들어야 합니다.
작성은 이하 링크처의 「준비」를 참조하면 가능합니다.
htps : // 이 m/이형 7/이고 ms/3c8f9f8f6예 1에 809558d

2. Webhook URL을 매개변수 저장소로 설정



AWS Management Console을 열고,
System Manager → 매개변수 저장소 → 매개변수 작성
가서,

이름: HANGOUTS_CHAT_WEBHOOK_URL
값: 검색된 Webhook URL
유형: SecureString

로 설정합니다.

3. CDK에서 스택 만들기



지금까지 준비가 되면 CDK의 스택을 정의해 갑니다.

lib/cdk-alarm-stack.ts

import * as cdk from '@aws-cdk/core'
import * as sns from '@aws-cdk/aws-sns'
import * as subs from '@aws-cdk/aws-sns-subscriptions'
import * as cw from '@aws-cdk/aws-cloudwatch'
import * as lambda from '@aws-cdk/aws-lambda'
import * as iam from '@aws-cdk/aws-iam'
import * as cw_actions from '@aws-cdk/aws-cloudwatch-actions'

export class CdkAlarmStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    const layer = new lambda.LayerVersion(this, 'node-fetch', {
      code: lambda.Code.asset('layer/forChat'),
      compatibleRuntimes: [
        lambda.Runtime.NODEJS_10_X,
        lambda.Runtime.NODEJS_12_X
      ],
      layerVersionName: 'node-fetch'
    })
    const triggerFunction = new lambda.Function(this, 'triggerFunction', {
      runtime: lambda.Runtime.NODEJS_12_X,
      handler: 'index.handler',
      code: lambda.Code.asset('lambda/trigger-chat-cdk'),
      functionName: 'trigger-chat-cdk'
    })
    const sendChatFunction = new lambda.Function(this, 'sendChatFunction', {
      runtime: lambda.Runtime.NODEJS_12_X,
      handler: 'index.handler',
      code: lambda.Code.asset('lambda/send-chat-cdk'),
      functionName: 'send-chat-cdk',
      layers: [
        layer
      ]
    })
    sendChatFunction.addToRolePolicy(new iam.PolicyStatement({
      actions: [
        'sts:AssumeRole',
        'ssm:GetParameter'
      ],
      resources: [
        '*'
      ]
    }))
    const topic = new sns.Topic(
      this,
      'sendChatTopic',
      {
        displayName: 'send chat',
        topicName: 'sendChatTopicCdk'
      }
    )
    topic.addSubscription(new subs.LambdaSubscription(sendChatFunction))
    const alarm = new cw.Alarm(this, 'sendChatAlarm', {
      evaluationPeriods: 1,
      metric: triggerFunction.metricInvocations(),
      threshold: 2,
      period: cdk.Duration.minutes(1),
      alarmName: 'sendChatCdk'
    })
    alarm.addAlarmAction(new cw_actions.SnsAction(topic));

  }
}


triggerFunction를 다른 리소스로 다시 작성하면 알람 모니터링 대상을 변경할 수 있으며 alarm를 다시 작성하면 알람 정의를 자유롭게 설정할 수 있습니다.

4. Chat에 메시지 보내기 Lambda 함수 작성



이번에는 람다 함수로
- 감시 대상이 됨 trigger-chat-cdk - 채팅에게 메시지 보내기 send-chat-cdk의 2개를 정의할 필요가 있습니다만, trigger-chat-cdk 의 내용은 정직한 것이어도 좋기 때문에, 설명을 생략 합니다.
send-chat-cdk의 내용은 다음과 같습니다.

send-chat-cdk.js
const fetch = require('node-fetch')
const AWS = require('aws-sdk')

exports.handler = async (event, context, callback) => {
  const ssm = new AWS.SSM()
  const res = await ssm.getParameter({ Name: 'HANGOUTS_CHAT_WEBHOOK_URL', WithDecryption: true }).promise()

  const fromSNS = event.Records[0].Sns.Message
  const data = JSON.stringify({
    text: `${fromSNS}`
  })

  fetch(res.Parameter.Value, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json; charset=UTF-8'
    },
    body: data
  })

  callback(null, event)
}

이 함수는 node-fetch라는 모듈을 가져오므로 이 모듈을 사용할 수 있도록 합니다.

5. Layer에서 사용할 모듈 설치



이번에 사용하는 모듈은 Layer에 세트합니다.
따라서 lambda/layer/forChat/nodejs라는 디렉토리를 만들고이 디렉토리에서
$ npm i node-fetch

실행하고 설치합니다.

6. 배포



여기까지 완료하면,
$ cdk deploy

에서 스택을 배포합니다.

7. 실행 테스트



AWS Management Console에서 Lambda trigger-chat-cdk 관리 화면을 열고 적절한 테스트 이벤트를 두 번 이상 실행합니다.


1분 정도 기다렸다가 방금 만든 Hangouts Chat 대화방에 CloudWatch의 오류 메시지가 전달되면 성공합니다!

메시지 문장의 내용은, Lambda의 내용을 적절히 어레인지해 주시면 좋겠습니다.

이상, 감사합니다.

좋은 웹페이지 즐겨찾기