서버 인프라/Aws

서버 상태 Lambda와 Slack으로 실시간 확인하기

트리맨스 2022. 7. 27. 22:56
반응형

 

현재 운영중인 서버는 Elastic Beanstalk으로 관리를 하고 있다. 덕분에 오토 스케일링, 블루그린 배포 등등 서버와 관련된 설정들을 간편하게 관리하는 중이다. 명령어 몇 줄이면 자동으로 배포가 가능한 편리한 기능이다. 최근에 서버 운영 중 서버가 죽는 일이 있었다. 이 때 서버 운영 문제를 바로 알았더라면 대응이 조금 더 빨리 되었을 것 같은데, 바로 알아차리지 못해서 대처가 조금 늦었다. 그래서 서버에 문제가 생기거나 상태 변화가 있을 때 바로 슬랙으로 서버 상태를 보내주는 로직이 필요할 것 같아서, 바로 서비스를 구축해보기로 했다.

 

구상하기


구조는 간단하다. Elastic Beanstalk은 상태 변화와 관련된 이벤트를 EventBridge로 보내주게 된다. 이 이벤트를 잡아서 슬랙으로 이벤트 정보를 보내 주면 될 것 같았다. 이벤트 하나 보내주자고 ec2 서버를 여는 것은 문제가 있어 보여서, Lambda를 이용해서 메시지를 보내는 것이 좋을 것 같았다.

 

 

제작하기


먼저 Elastic Beanstalk의 이벤트를 확인해보자. EventBridge는 특정한 이벤트를 요청하게 되면(또는 주기적으로), 특정한 응답을 불러오게 된다. 아래에 이벤트 소스의 json과 응답 형태에 관한 json을 설명해 주고 있다. 간단하게 모든 이벤트 소스와 기본적인 응답 형태에 관한 예시를 아래에 적어 두었다.

 

이벤트 소스 (모든 이벤트 변화에 관한 요청)

{
   "source": [
    "aws.elasticbeanstalk"
  ],
  "detail-type": [
    "Health status change"
    ]
}

이벤트 응답 (Elastic Beanstalk의 모든 상태변화에 관한 응답값)

{ 
   "version":"0",
   "id":"1234a678-1b23-c123-12fd3f456e78",
   "detail-type":"Elastic Beanstalk resource status change",
   "source":"aws.elasticbeanstalk",
   "account":"111122223333",
   "time":"2020-11-03T00:31:54Z",
   "region":"us-east-1",
   "resources":[
      "arn:was:elasticbeanstalk:us-east-1:111122223333:environment/myApplication/myEnvironment"
   ],
   "detail":{
      "Status":"Environment creation started",
      "EventDate":1604363513951,
      "ApplicationName":"myApplication",
      "Message":"createEnvironment is starting.",
      "EnvironmentName":"myEnvironment",
      "Severity":"INFO"
   }
}

 

대충 어떤식으로 응답이 오는지는 알 것 같다. 이제 람다 함수를 작성해보자. slack으로 메시지를 보내는 방법을 확인해보니 이런저런 api가있던 것 같은데, 나는 webhook으로 post 요청을 보내는 방법을 사용할 것이다. 예전에 npm에서 slack-node 패키지를 사용했는데, lambda에서 작동을 종종 멈추는 것을 확인했다. 그래서 이번에는 rest 요청을 보내는 axios를 사용해서 요청을 보낼 것이다.

 

먼저 다음 사이트에서 슬랙 app을 생성한다.

https://api.slack.com/apps?new_app=1 

 

Slack API: Applications | Slack

Your Apps Don't see an app you're looking for? Sign in to another workspace.

api.slack.com

 

 

이후에는 Features - incomming Webhoos에서 toggle을 킨 다음, 하단의 Webhook을 특정 채널과 연결해준다. 그러면 다음과 같이 Webhook URL이 생긴다.

 

 

Webhook URL로 post 요청 (json 데이터 포함) 하면 메시지가 오게 된다. 간단히 curl 요청을 보내 보자. [Webhook URL]에는 위에서 제공한 주소를 넣으면 된다.

 

curl -X POST -H 'Content-type: application/json' --data '{"text":"안녕~!"}' [Webhook URL]

ㅎㅇㅎㅇ

 

응답이 잘 오는 것을 알 수 있다.

 

 

이제 Slack으로 요청을 보내는 lambda 함수를 만들고 배포해보자. 함수 제작 및 배포는 아래의 링크를 참고하면 된다.

https://tre2man.tistory.com/299

 

Typescript를 이용한 어플리케이션 Lambda에 배포하기

요즘 lambda가 재밌어 보여서 계속 알아보는 중이다. 람다 (서버리스) 애플리케이션에 대한 설명은 다음 사이트에 잘 나와있다. https://www.redhat.com/ko/topics/cloud-native-apps/what-is-serverless 서버리스..

tre2man.tistory.com

 

위랑 차이점이 있다면 axios를 통해서 요청을 보내고, 이벤트 소스가 GET/ 이 아니라 EventBridge이다. 소스 코드는 매우 간단하고, serverless.yml 파일을 조금 수정할 필요가 있다. 이벤트 소스는 위에서 작성한 EventBridge의 이벤트 소스를 확인하여 json 데이터를 yml로 변환하면 된다. 간단히 얘기하면 둘 다 key, value 값으로 이루어져 있고 array 정보는 원소 앞에 '-'를 붙여 표시한다.

 

serverless.yml

service: server-alert

frameworkVersion: "3"

plugins:
  - serverless-plugin-typescript
  - serverless-offline

provider:
  name: aws
  runtime: nodejs14.x
  region: ap-northeast-2

functions:
  sendMsg:
    handler: src/slack-msg.sendMsg
    timeout: 60
    events:
      - eventBridge:
          pattern:
            source:
              - aws.elasticbeanstalk
            detail-type:
              - Health status change

slack-msg.ts

import { Handler, Context } from "aws-lambda";
import axios from "axios";

export interface HttpResponse {
  statusCode: number;
  body: string;
}

const sendMsg: Handler = async (event: any, context: Context) => {
  try {
    // 슬랙 메시지 전송
    await axios.post(
      "Webhook URL 주소",
      {
        text: `환경 이름 : ${event?.detail?.EnvironmentName} \n이벤트 내용 : ${event?.detail?.Message}`,
      }
    );
    const response: HttpResponse = {
      statusCode: 200,
      body: JSON.stringify({
        message: "Health status changed!",
      }),
    };
    return response;
  } catch (e) {
    const response: HttpResponse = {
      statusCode: 404,
      body: JSON.stringify(e),
    };
    return response;
  }
};

export { sendMsg };

 

코드 작성 후 배포한 이후, Elastic Beanstalk에 일부러 배포 이벤트를 입력해 정상적으로 응답이 오는지 확인해 보았다.

 

 

상태 변화시 응답이 정상적으로 온다!

 

후기


최종적으로 잘 구현이 되어서 좋다. 일단 서버에 문제가 생기면 비교적 빨리 알 수 있다는 것이 제일 큰 장점이라고 생각한다. 중간에 slack-node를 이용한 함수는 슬랙 메시지가 잘 전송이 안되었지만, webhook을 사용하니 확실하게 메시지가 전송되었다. 간단한 api 로직을 작성할 때는 lambda를 사용하는 것이 매우 효율적인 것 같다. (API 게이트웨이가 월 100만건까지 무료면은 말 다한것 같다. 개인 프로젝트 할때는 매우 유용한듯 하다.)

 

참고자료


https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/AWSHowTo.eventbridge.html

 

Using Elastic Beanstalk with Amazon EventBridge - AWS Elastic Beanstalk

Using Elastic Beanstalk with Amazon EventBridge Using Amazon EventBridge, you can set up event-driven rules that monitor your Elastic Beanstalk resources and initiate target actions that use other AWS services. For example, you can set a rule for sending o

docs.aws.amazon.com

 

https://slack.com/intl/ko-kr/help/articles/115005265063-Slack%EC%9A%A9-%EC%88%98%EC%8B%A0-%EC%9B%B9%ED%9B%84%ED%81%AC

 

Slack용 수신 웹후크

수신 웹후크는 외부 소스에서 워크스페이스로 정보를 공유할 수 있는 간단한 방식입니다.   이용 방법 선택한 채널로 데이터를 보냅니다. 채널의 BAD+2CB...

slack.com

 

 

반응형