AWS 요청 알림BOT는 AWS Lambda+AWS SDK+Go에서 ~SDK 조사편을 제작합니다~
AWS 요청 알림BOT는 AWS Lambda+AWS SDK+Go에서 ~SDK 조사편을 제작합니다~
대강
AWS 청구액이 설정 오류로 튕기는 사례가 많은데, 대책으로 현재 청구금액을 공지하는 BOT를 제작하는 것도 마찬가지다.
이번에는 코스트 익스플로러의 SDK에 대한 개인 조사를 진행했다.
Cost Explorer 소개
AWS의 비용을 시각화할 수 있습니다.
비용 정보
Cost Explorer의 사용자 인터페이스를 사용하면 비용과 사용 상황을 무료로 표시할 수 있습니다.
Cost Explorer API를 사용하여 프로그램을 통해 데이터에 액세스할 수도 있습니다.
API 요청마다 0.01달러의 비용이 발생합니다.
오늘(2022/04/07) 환율
1 USD = 123.69 YEN
0.01\times 123.69 = 1.2369
API 요청 때마다 1.2319엔의 비용이 발생합니다.
그래서 매일 한 번씩 요구하면
1.2369\times 30 = 37.107
한 달(30일 가정)에 약 37.107엔의 비용이 발생한다.
Cost Explorer용 SDK
Go에서 구현된 문서
USD만 해결할 수 있는 문제
USD 기반 rate의 API Open Exchange Rates를 이용하여 USD를 JPY로 변환합니다.
무료 방안은 1000개의 점방/월을 사용할 수 있다.
획득한 상황
사용 방법이 매우 간단하고 응용 프로그램쿼리 매개 변수에 id를 제공하고 Get 요청을 던지기만 하면 됩니다.
Go 언어로 구현된 예
app_id는 ssm 매개 변수 상점 등의 SecureString을 이용한다.
func GetOpenexchangeratesJpy(sess *session.Session) float64 {
// Base URL: https://docs.openexchangerates.org
base := "https://openexchangerates.org/api/latest.json?app_id=%s"
// Application id: https://docs.openexchangerates.org/docs/authentication
// Using ssm parametor store: https://ap-northeast-1.console.aws.amazon.com/systems-manager/parameters
svc := ssm.New(sess)
app_id, err := svc.GetParameter(&ssm.GetParameterInput{
Name: aws.String("<YOUR_OPENEXCHANGERATES_APP_ID_PARAMSNAME>"),
WithDecryption: aws.Bool(true),
})
if err != nil {
log.Println(err.Error())
}
// Create Request url
url := fmt.Sprintf(base, *app_id.Parameter.Value)
// Start Request
resp, err := http.Get(url)
if err != nil {
log.Println(err.Error())
}
defer resp.Body.Close()
source, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println(err.Error())
}
// Parse json
desc := Schema{}
json.Unmarshal(source, &desc)
return desc.Rates.JPY
}
Cost Explorer SDK 매개변수 요약
이번 이용
GetCostAndUsage
.Filter
다양한 유지 보수를 통해 AWS 비용을 필터링할 수 있습니다.
예를 들어, SERVICE 및 LINKED이 계정의 서비스 사용과 관련된 비용을 얻기 위해 ACCOUNT를 지정할 수 있습니다.
이 매개 변수는 반드시 필요한 것이 아니다.
Granularity
MONTHLY, DAILY, HOURLY를 통해AWS 원가의 입도를 설정할 수 있다.
유효한 값: DAILY | MONTHLY | HOURLY
이 매개 변수는 필수적이다.
GroupBy
AWS 비용은 최대 두 개의 다른 그룹 (유지보수, 탭 키, 비용 종류, 또는 다른 유형의 두 그룹) 을 사용하여 그룹을 구성할 수 있습니다.
DIMENSION 유형의 유효한 값은 다음과 같습니다.
AZ、
INSTANCE_TYPE、
LEGAL_ENTITY_NAME、
INVOICING_ENTITY、
LINKED_ACCOUNT、
OPERATION、
PLATFORM、
PURCHASE_TYPE、
SERVICE、
TENANCY、
RECORD_TYPE、
USAGE_TYPE
또한 탭의 종류에 따라 그룹을 나누고 유효한 탭 키를 포함하면 빈 문자열을 포함하는 모든 탭 값을 얻을 수 있습니다.
조금 더 자세히 적어주시면...
AZ, 각 아랍 국가에 대한 정보
INSTANCE_TYPE 정보, 인스턴스 유형(예: t2.micro 등)
LEGAL_ENTITY_NAME, INVOICING_ENTITY 정보(예: Amazon Web Services Japan G.K. 등)
LINKED_ACCOUNT 계정 정보
OPRATION에 대한 각 작업에 대한 정보(예: RunInstance 등)
PLATFORM 정보, 각 플랫폼에 대한 정보
PURCHASE_TYPE에 대한 주문형, 보존, saving 등 각 계획에 대한 정보
SERVICE, 각 서비스에 대한 정보
TENANCY 정보(예: Shared 등)
RECORD_TYPE 정보(예: DiscountedUsage, Tax 등)
USAGE_TYPE 정보(예: APS1-EUN1-AWS-Out-Bytes 등)
등키는 지정할 수 있고, 1회 호출은 2개를 지정할 수 있다.
이 매개 변수는 반드시 필요한 것이 아니다.
Metrics
AmortizedCost, BlendedCost, NetAmortizedCost, NetUnblendedCost, 정규화izedAmount, UnblendedCost, UsageQuantity
이곳의 보도는 참고로 삼을 수 있다.
이번 이용
UnblendedCost
.참고로 이 매개 변수는 필수적이다.
NextPageToken
영패가 다음 결과 집합을 가져옵니다.
지난번 호출의 응답 결과가 최대 페이지 크기를 초과하면 영패를 제공합니다.
이번 조사의 실시례에 관해서는 간단하게 하기 위해 붙이는 것을 고려하지 않는다.
결과 대상에 NextPageToken이 포함된 경우 후속 내용 처리를 읽어야 한다.
TimePeriod
AWS 비용 확보를 위한 시작일과 종료일을 설정할 수 있습니다.
시작 날짜는 포함되지만 종료 날짜는 포함되지 않습니다.
예를 들어 start가 2017-01-01이고end가 2017-05-01일 때 원가와 사용 상황의 데이터는 2017-01-01에서 2017-04-30을 얻었지만 2015-05-01은 포함되지 않았다.
물론 이 매개 변수도 필수적이다.
Go의 설치
알림 예약 섹션
package main
import (
"aws-billing-notify/pkg/aws/profile"
"aws-billing-notify/pkg/aws/sdk/ce/costandusage/calc"
"aws-billing-notify/pkg/aws/sdk/ce/costandusage/granularity"
"aws-billing-notify/pkg/aws/sdk/ce/costandusage/group"
"aws-billing-notify/pkg/aws/sdk/ce/costandusage/metric"
"aws-billing-notify/pkg/aws/sdk/ce/costandusage/term"
"fmt"
"log"
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/costexplorer"
"github.com/aws/aws-sdk-go/service/costexplorer/costexploreriface"
"github.com/aws/aws-sdk-go/service/ssm"
)
type costParams struct {
Granularity *string
Term *costexplorer.DateInterval
Metrics []*string
Groups []*costexplorer.GroupDefinition
}
func (c costParams) getCost(svc costexploreriface.CostExplorerAPI, start *string, end *string) (result *costexplorer.GetCostAndUsageOutput) {
c.Granularity = granularity.Monthly.String()
c.Metrics = []*string{
metric.UnblendedCost.String(),
}
c.Term = &costexplorer.DateInterval{
Start: start,
End: end,
}
service := costexplorer.GroupDefinition{
Key: group.Service.Key(),
Type: group.Dimention.Type(),
}
c.Groups = append(c.Groups, &service)
input := costexplorer.GetCostAndUsageInput{
Granularity: c.Granularity,
TimePeriod: c.Term,
Metrics: c.Metrics,
GroupBy: c.Groups,
}
result, err := svc.GetCostAndUsage(&input)
if err != nil {
log.Println(err.Error())
}
return result
}
func main() {
sess, err := session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
Profile: profile.Name,
}) // todo: change lambda
if err != nil {
log.Println(err.Error())
}
c := costParams{}
svce := costexplorer.New(sess)
jst, err := time.LoadLocation("Asia/Tokyo")
if err != nil {
log.Println(err.Error())
}
start, end := term.CreateThisMonthRange(jst)
cost := c.getCost(svce, start, end)
svc := ssm.New(sess)
rawjpy, err := svc.GetParameter(&ssm.GetParameterInput{
Name: aws.String("<YOUR_OPENEXCHANGERATES_JPY_RATE_PARAMSNAME>"),
WithDecryption: aws.Bool(false),
})
if err != nil {
log.Println(err.Error())
}
jpy, err := strconv.ParseFloat(*rawjpy.Parameter.Value, 64)
if err != nil {
log.Println(err.Error())
}
for _, group := range cost.ResultsByTime[0].Groups {
amount, err := strconv.ParseFloat(*group.Metrics[*metric.UnblendedCost.String()].Amount, 64)
if err != nil {
log.Println(err.Error())
}
// Set openexchangerates jpy
val := fmt.Sprintf("- %s: %f 円", *group.Keys[0], amount*jpy)
fmt.Println(val)
}
// Set openexchangerates jpy
fmt.Println(calc.Sum(cost, jpy))
}
속도 업데이트부package main
import (
"aws-billing-notify/pkg/aws/profile"
"aws-billing-notify/pkg/openexchangerates"
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
)
func main() {
sess, err := session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
Profile: profile.Name,
})
if err != nil {
log.Println(err.Error())
}
openexchangerates.PutOpenexchangeratesJpy(sess)
}
총결산
이번엔 SDK 검증까지
AWS의 서비스 설계를 이용할 때 어느 정도 정확하게 가늠하지 못하면 막대한 손실을 초래할 수 있어 신용을 잃을 가능성이 크다.
AWS의 요금 체계와 관련해서는 앞으로도 계속 공부할 예정이다.
다음에 람보를 세워 실제 통지를 하려고 합니다.
Reference
이 문제에 관하여(AWS 요청 알림BOT는 AWS Lambda+AWS SDK+Go에서 ~SDK 조사편을 제작합니다~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/_kazuya/articles/aeabc23cd5df2a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)