こんにちは。katoです。
今回は、先日一般公開されたS3 Selectを利用してAWSのサービス利用料を取得したいと思います。
概要
S3 Selectは、S3に配置したオブジェクトデータを取得することが可能なサービスとなっております。 これまでは、S3をデータソースとして利用する場合には、S3のオブジェクトを一度ダウンロードしたり、Amazon Athenaを利用したりと少し面倒な部分がありましたが、S3 Selectを利用することで簡単にデータの取得が可能となります。
S3 Selectでは、S3バケットに配置したCSVとJSONをデータソースとして利用することが可能となっております。 単純なSELECTのクエリ実行の場合には、Amazon Athenaを利用するよりもお手軽に利用することが可能です。
今回は、このS3 Selectを利用してaws-billing-csvへのクエリ実行を行っていきたいと思います。
手順
S3 SelectはS3上にデータセットが配置してあれば、特に設定することなくAWS CLI等からクエリ実行が可能です(S3へのアクセス権限は必要となります)。
今回はPythonのboto3を利用してクエリ実行を行いたいと思います。
s3selectのモジュールはデプロイパッケージの作成が必要となるので、Lambdaから実行する場合には、デプロイパッケージをローカル環境(EC2)やCloud9で用意し、zipアップロードでLambda関数を作成します。
それではさっそく構築を行っていきましょう。
まずはじめに今回必要となるモジュール等をインストールします。
# mkdir s3select # cd s3select # wget http://s3select.s3-website-us-east-1.amazonaws.com/public/python/aws-python-sdk-s3-select-preview-1.0.0.zip # unzip aws-python-sdk-s3-select-preview-1.0.0.zip -d . # cd aws-python-sdk-s3-select-preview-1.0.0 # pip install boto3 requests -t .
次に関数の作成を行います。
今回は AWSサービス毎の利用料を取得するために、クエリ実行後に各サービスのコストを合算しております。 また、取得したbillingの値を可視化できるよう、Elasticsearchに値をPOSTしております。
#!/usr/bin/python import datetime import random import string import requests import json import boto3 from s3select import ResponseHandler class PrintingResponseHandler(ResponseHandler): def handle_records(self, record_data): print(record_data.decode('utf-8')) def lambda_handler(event, context): handler = PrintingResponseHandler() now = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S%z") nowdate = datetime.datetime.now().strftime("%Y-%m") filename = "accountID-aws-billing-csv-" + nowdate + ".csv" s3 = boto3.client('s3', region_name='ap-northeast-1') response = s3.select_object_content( Bucket="bucket-name", Key=filename, ExpressionType='SQL', Expression='SELECT s.ProductCode, s.CostBeforeTax, s.TaxAmount, s.TotalCost, s.RecordType FROM S3Object AS s', InputSerialization={ 'CSV': { 'FileHeaderInfo': 'Use', 'RecordDelimiter': '\n', 'FieldDelimiter': ',', } }, OutputSerialization={ 'CSV': { 'RecordDelimiter': '\n', 'FieldDelimiter': ',', } } ) for event in response['Payload']: if 'Records' in event: records = event['Records']['Payload'] record = records.split("\n") services = [] costs = [] taxs = [] totals = [] for num in range(len(record)): data = record[num].split(",") if len(data[0]) == 0: pass else: if data[4] == "LinkedLineItem": if data[0] in services: index = services.index(data[0]) costs[index] = costs[index] + float(data[1]) taxs[index] = taxs[index] + float(data[2]) totals[index] = totals[index] + float(data[3]) else: services.append(data[0]) costs.append(float(data[1])) taxs.append(float(data[2])) totals.append(float(data[3])) for num2 in range(len(services)): random_str = ''.join([random.choice(string.ascii_letters + string.digits) for i in range(5)]) url = ("https://elasticsearch-endpoint/select/number/"+random_str) res = requests.post(url, data=json.dumps({"@timestamp": now, "ServiceName": services[num2], "CostBeforeTax": costs[num2], "TaxAmount": taxs[num2], "TotalCost": totals[num2]}))
関数を作成したら、zipで固めてLambda関数を作成します。
動作確認
Lambda関数の作成が完了したら、CloudWatch EventsからLambdaをスケジュール実行するよう設定し、動作の確認を行いましょう。
billingの更新は一日に数回なので、1日1回の実行間隔でも十分です。
Lambdaの実行が完了したら、Kibanaコンソールにアクセスし、インデックスの登録、グラフの作成を行います。
今回は全サービスの合計遷移、サービス毎の利用料遷移、利用料の割合をグラフ化しました。
まとめ
今回は、S3 Selectを利用したbillingの取得をご紹介致しました。
S3 Selectを利用することで、S3をデータセットとしたシステムの構築が今まで以上に簡単に実現できるようになりました。
今回のご紹介したbillingの取得であれば、サービスやアカウント毎のbillingの遷移を毎日取得することが可能となり、コスト管理を簡単に行うことが可能となります。
まだ一般提供されたばかりで機能の制限等も御座いますが、簡単に利用でき、便利なサービスとなっておりますので、今後の機能拡張を楽しみにしています。