0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS S3 + APIGateway + Lambda でンプルなアプリケーションを作成

Posted at

AWS Cost Dashboardを作成してみた

概要

過去30 日分のAWSのコストを簡単に可視化できる簡単なアプリケーションを作成しました。このアプリケーションは、AWS Cost Explorer APIを利用して、AWSアカウントの過去30日分のコストを取得し、フロントエンドで表示する仕組みになっています。
この記事では、使用した技術や実装のポイントについて解説していきます!


使用技術

AWS サービス

  • AWS Lambda: コストデータを取得するバックエンドを実装
  • API Gateway: Lambda関数を公開するためのエンドポイント
  • S3: フロントエンドの静的ファイルをホスティング
  • CloudFront: フロントエンドのキャッシュと高速配信を実現
  • WAF: APIGatewayにアタッチし、特定のIPアドレスからのみアクセスを許可

構成管理

  • Terraform: AWSリソースのプロビジョニングと管理

CI/CD

  • GitHub Actions: dev or main push時に、フロント(S3)への自動デプロイとCloudFrontのキャッシュ削除

全体のアーキテクチャ

image.png

このアプリケーションでは以下のことができます。

  1. AWS Cost Explorer APIを使用して、AWSアカウントの過去30日分のコストを取得
  2. フロントエンドで取得したコストデータを表示
  3. WAFを使用して、特定のIPアドレスからのみAPIにアクセスできるように制限

フロント部分は全く作り込んでいないので、こんな感じの見た目です。。笑

image.png


CORSについて

今回の実装では、CORS (Cross-Origin Resource Sharing) に対応するために以下のポイントを押さえました。

  1. API Gatewayの設定
    API Gatewayのメソッドレスポンスで、以下のヘッダーを設定しました。

    • Access-Control-Allow-Origin
    • Access-Control-Allow-Methods
    • Access-Control-Allow-Headers
  2. Lambda関数のレスポンスヘッダー
    Lambda関数のレスポンスにも同様のCORSヘッダーを追加しました。これにより、フロントエンドからのリクエストが正常に処理されます。

以下は、Lambda関数でCORS対応を行った部分のコードです。

"headers": {
    "Access-Control-Allow-Origin": allowed_origin,  # 環境変数から取得
    "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
    "Access-Control-Allow-Headers": "Content-Type, Authorization"
}

Lambdaコードについての解説

Lambda関数では、AWS Cost Explorer APIを使用してコストデータを取得しています。以下は、主な処理の流れです。

1.Cost Explorerクライアントの作成

  • boto3ライブラリを使用して、Cost Explorerクライアントを作成します。

2.コストデータの取得

  • get_cost_and_usageメソッドを使用して、指定した期間のコストデータを取得します。

3.レスポンスの整形

  • 取得したデータを解析し、合計コストと通貨単位をレスポンスとして返します。

以下は、Lambda関数のコードの一部です。

response = ce_client.get_cost_and_usage(
    TimePeriod={
        'Start': start_date,
        'End': end_date
    },
    Granularity='MONTHLY',
    Metrics=['UnblendedCost']
)

cost_data = response['ResultsByTime']
total_cost = sum(float(item['Total']['UnblendedCost']['Amount']) for item in cost_data)

return {
    'statusCode': 200,
    'body': json.dumps({
        'message': 'AWS account cost retrieved successfully.',
        'total_cost': total_cost,
        'currency': cost_data[0]['Total']['UnblendedCost']['Unit']
    }),
    "headers": {
        "Access-Control-Allow-Origin": allowed_origin,
        "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
        "Access-Control-Allow-Headers": "Content-Type, Authorization"
    },
}

実際に使用するための手順

試してみたい方は、以下の手順でセットアップしてください。

1.リポジトリをクローン
以下のコマンドでリポジトリをクローンします。

git clone https://github.com/takaakihoya/aws_cost_dashbord.git

2.Terraform.tfvars の作成
terraform/terraform.tfvars.sampleをコピーしてterraform/terraform.tfvarsを作成し、以下の値を設定してください。

profile: AWS CLIで使用するプロファイル名
hosted_zone: Route 53のホストゾーン名
product: サブドメイン名
lambda_source_dir: Lambda関数のソースコードディレクトリ
my_ip: 許可するIPアドレス

3.terraform apply
下記のコマンドを実行してください。

#terraform/ で実行
terraform init
terraform apply

4.CI/CD 周りの設定
app/frontend/* 配下で変更があり、dev or main ブランチにpushすると自動でS3にデプロイされるようにworkflow を作成しています。
workflow の実行にはgithubにて下記の secret の設定が必要になります。

secrets.AWS_ROLE_ARN = マネコンで作成。github OIDC用のrole
ecrets.AWS_S3_BUCKET = terraform で作成した、S3URL
secrets.DISTRIBUTION_ID = terraform で作成したCloudFrontのID

CI/CD 周りの設定は、別で記事を作成しているのでよければ参考にしてください。
https://qiita.com/hoyat4967/items/d77c321650f0798aab15

5.config.js の設定
app/frontend/config.js のapiurlを、terraform で作成したAPIGateway のURLに変更してください。

6.フロントエンドのデプロイ
GitHub Actionsを使用して、フロントエンドをS3にデプロイします。devまたはmainブランチにプッシュすることで、自動的にデプロイが実行されます。

以上でセットアップは完了です。ブラウザでCloudFrontのURLにアクセスし、AWSコストが表示されることを確認してみてください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?