Go와 Lambda에서 AWS 사용료를 매일 LINE 알림

16113 단어 5람다LineNotify

AWS 사용 수수료



OWS AWS 콘솔 놀기 ~
오, 그래 ~ AWS 지금 얼마쯤 깡통 넨 야로
내 청구 대시 보드 포치 ~ 트


응! ? ?

ECS를 방치하여 $100 초과의 청구가 오거나,
죽여야 할 RDS 인스턴스가 모르는 사이에 부활하고 있어 수수하게 $40 정도 청구가 오거나,
이 통과 의례를 좋은 가감 어떻게든 하려고 간단한 요금 통지 시스템을 만들었습니다.

했던 일



Go 언어로 LINE notify 알림 API를 킥하는 함수 구현
AWS Lambda에 배포 Cron에서 정기적으로 실행하여 매일 AWS 사용료를 스스로 LINE 해주는 간단한 시스템을 만들었습니다.

구현 준비



LINE notify에서 토큰 발행



LINE notify로 이동합니다.


로그인하는 계정은 물론 알림을 받고 싶은 자신의 LINE 계정입니다.
앱 측에서 이메일 주소 비밀번호를 설정하여 PC에서 로그인합니다. 그리고 내 페이지로 이동

PC로부터의 액세스라면 이러한 컴포넌트가 나타나 토큰을 받을 수 있습니다.

serverless framework



AWS Lambda를 제대로 구현하고 싶어도 물론 serverless framework를 사용합니다!
Go 용 병아리를 사쿠토 명령으로 준비
$ sls create -u https://github.com/serverless/serverless-golang/ -p goserverless

serverless.yaml은 최소한, 아래와 같은 설명에 있으면 움직일 수 있습니다.
cron은 일본 시간의 아침 8시에 통지가 오도록 설정하고 있습니다.
IAM은 CloudWatchReacOnlyAccess의 것을 완전히 붙여넣습니다.

serverless.yaml

service: goserverless

provider:
  name: aws
  runtime: go1.x
  region: ap-northeast-1
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - 'autoscaling:Describe*'
        - 'cloudwatch:Describe*'
        - 'cloudwatch:Get*'
        - 'cloudwatch:List*'
        - 'logs:Get*'
        - 'logs:List*'
        - 'logs:Describe*'
        - 'logs:TestMetricFilter'
        - 'logs:FilterLogEvents'
        - 'sns:Get*'
        - 'sns:List*'
      Resource:
        - '*'

package:
 exclude:
   - ./**
 include:
   - ./bin/**

functions:
  billing_notify:
    handler: bin/main
    events:
      - schedule: cron(0 23 * * ? *)
    environment:
      LINEpostURL: https://notify-api.line.me/api/notify
      LINEnotyfyToken: <Token>

구현



Go 언어를 사용합니다. 파이썬에서는 비교적 구현 예가 있는 것 같습니다만, Go에서의 구현은 내 관측 범위에서는 발견되지 않았기 때문에 레시피를 올려 둡니다.

Go 언어로 CloudWatch에서 요금 정보를 얻는 과정



CloudWatch 요금 정보는 다음과 같이 구조체를 채우면 얻을 수 있습니다. 요금 정보로 인해 지역은 us-east-1입니다.

main.go
func Handler() (Response, error) {
    svc := cloudwatch.New(session.New(), &aws.Config{Region: aws.String("us-east-1")})

    params := &cloudwatch.GetMetricStatisticsInput{
        Dimensions: []*cloudwatch.Dimension{
            {
                Name:  aws.String("Currency"),
                Value: aws.String("USD"),
            },
        },
        StartTime:  aws.Time(time.Now().Add(time.Hour * -24)),
        EndTime:    aws.Time(time.Now()),
        Period:     aws.Int64(86400),
        Namespace:  aws.String("AWS/Billing"),
        MetricName: aws.String("EstimatedCharges"),
        Statistics: []*string{
            aws.String(cloudwatch.StatisticMaximum),
        },
    }
    resp, err := svc.GetMetricStatistics(params)
    if err != nil {
        fmt.Println(err)
    }

    // ...省略

}

func main() {
    lambda.Start(Handler)
}

Go 언어로 LINE notify API에 POST



LINE Notify API Document에 따르면 다음과 같은 요청 헤더가 필요합니다.
요청 파라미터에 자신의 LINE에 알리고 싶은 내용을 올립니다. message는 필수이며 이미지를 POST하여 알림으로 건너 뜁니다

main.go

func Handler() (Response, error) {

    // ...省略

    val := url.Values{}
    val.Add("message", param)
    request, err := http.NewRequest("POST", os.Getenv("LINEpostURL"), strings.NewReader(val.Encode()))
    if err != nil {
        fmt.Println(err)
    }
    request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    request.Header.Add("Authorization", "Bearer "+os.Getenv("LINEnotyfyToken"))
    lineResp, err := http.DefaultClient.Do(request)
    if err != nil {
        fmt.Println(err)
    }

    return Response{
        Message: fmt.Sprintf("%v", lineResp),
    }, nil
}


무사히 매일 AWS 사용료를 파악할 수 있었다



정말 초조해 ~
이제 이것으로 간과로 사용 요금 어려운 일이라니 ~

종량 과금의 AWS 서비스를 시험하기 전에는 사용 요금을 통지하는 구조를 꼭 만들어 두는 것이 중요하네요. 지갑을 지키기 위해서도 ....

좋은 웹페이지 즐겨찾기