未経験からAWS自動化!Serverless Frameworkで毎日のコスト通知Bot(LINE連携)を作ってみた
はじめに AWSの学習を始める際、真っ先に気になるのが「リソースの消し忘れによる高額請求」ではないでしょうか。 AWS SAAの取得に向けて学習を進める中で、この「コストへの恐怖」を技術で解決し、心理的安全性を保ちながら開発体験を積みたいと考えました。
そこで、実務未経験の早い段階から**IaC(Infrastructure as Code)**を導入し、「いつでも作って壊せる(=セーブポイントを作れる)環境」をベースに、毎朝AWSの利用料金をLINEに自動通知するシステムを構築しました。
使用技術・アーキテクチャ
AWS Lambda (Python 3.9): コスト取得と通知のメインロジック。
Amazon EventBridge (Cron): 毎朝9時にLambdaを起動するタイマー。
AWS Cost Explorer API: AWSの利用料金データを取得。
Serverless Framework (v4): IaCツール。コマンド一発でデプロイ・削除を実現。
LINE Messaging API: 日々のコストをスマホにプッシュ通知。
事前準備の落とし穴(Tips) 実装に入る前に以下の準備が必要です。私が少し躓いたポイントも共有します。
-
AWS Cost Explorerの有効化 AWSコンソールから「Cost Explorer」を検索し、有効化ボタンを押す必要があります。有効化からデータが見れるようになるまで24時間かかるため、一番最初にやっておくことをお勧めします。
-
LINE Messaging APIのトークン取得 LINE Developersコンソールでチャネルを作成します。必要な情報は以下の2つですが、タブが分かれているので注意してください。
チャネルアクセストークン(長期): 「Messaging API設定」タブの一番下にあります。
あなたのユーザーID: 隣の「チャネル基本設定」タブの下の方にあります(Uから始まるID)。
ハマりポイント:AWS認証エラーは「手動で合鍵を置く」だけで解決できる!
AWSと自分のPC(Mac)を連携させる際、本来は便利なコマンド(serverless config credentials)を1行打つだけで設定が終わります。 しかし私の環境では、「PCのフォルダを勝手に書き換えないで!」というMacのセキュリティに弾かれ、EACCES: permission denied という赤いエラーが出てしまいました。
初心者の私はここで「ツールの設定やnpmの権限を直さなきゃ…」と泥沼にハマりかけたのですが、実はこのコマンドが裏でやっていることは非常にシンプルでした。 それは、「PC内の決まった隠しフォルダ(~/.aws)に、合鍵(アクセスキー)が書かれたファイルを作っているだけ」だったのです。
「ツールがエラーで合鍵を置けないなら、自分で直接その場所に合鍵を置けばいいのでは?」と気づき、以下の手動設定で突破できました。
【解決手順】 ターミナルを開き、自分のPCの中に「認証情報を置くための隠しフォルダ」と「ファイル」を直接作成します。
1. 合鍵を入れる専用の隠しフォルダ(ポケット)を作成
mkdir -p ~/.aws
2. 空のファイルを作成
touch ~/.aws/credentials
3. テキストエディタで開く(Macの場合)
open -e ~/.aws/credentials
開いたファイルに、AWSで発行したアクセスキーを以下の形式でコピー&ペーストして保存します。
ini [default] aws_access_key_id = AKIAXXXXXXXXXXXXXXXX
aws_secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
これだけで無事に連携が完了しました。便利なコマンドがエラーになった時、「要するにそのコマンドは裏で何をしてくれるものなのか?」という仕組みを知ることで、あっさり解決できるという大きな学びになりました。
ディレクトリ構成 今回はシンプルに3つのファイルだけで構成します。
text aws-cost-notifier/
├── .env # LINEの認証情報(※Git等には公開しない)
├── serverless.yml # インフラの設計図
└── handler.py # Pythonの実行コード
1. 環境変数の設定 (.env) セキュリティの観点から、トークン類はコードに直書きせず .env に分離します。
ini LINE_CHANNEL_ACCESS_TOKEN=取得した非常に長いトークン LINE_USER_ID=Uから始まるあなたのユーザーID
2. インフラのコード化 (serverless.yml) Serverless Frameworkの設計図です。
useDotenv: true を指定することで、ローカルの .env を読み込んでLambdaの環境変数に渡してくれます。 また、最小特権の原則に従い、IAMロールには ce:GetCostAndUsage(コスト参照)の権限だけを付与しています。
yaml service: aws-cost-line-notifier useDotenv: true
provider: name: aws
runtime: python3.9
region: ap-northeast-1
logRetentionInDays: 7 # ログの保存期間を7日に制限(コスト削減)
environment: LINE_CHANNEL_ACCESS_TOKEN:
{env:LINE_CHANNEL_ACCESS_TOKEN} LINE_USER_ID:
{env:LINE_USER_ID} iam: role: statements: - Effect: Allow
Action: - ce:GetCostAndUsage Resource: "*"
functions: notifyCost: handler: handler.notify_cost events: # UTC時間で指定。日本時間の朝9時に実行 - schedule: cron(0 0 * * ? *)
### 3. メインロジックの実装 (handler.py) 外部ライブラリ(requestsなど)を使わずに標準ライブラリの urllib を使うことで、Lambda Layers等の複雑な管理を省き、単一ファイルで動くようにしています。
python import boto3 import json import os import urllib.request from datetime import datetime, timedelta
def notify_cost(event, context): try: # 1. AWS料金の取得 # Cost Explorer APIは us-east-1 エンドポイントを使用するのが一般的 client = boto3.client('ce', region_name='us-east-1')
## デプロイとテスト 作業ディレクトリで以下のコマンドを打つだけで、AWS上に全てのリソースが自動構築されます。
デプロイ(作成)
serverless deploy
手動でテスト実行
serverless invoke -f notifyCost --log
学習が終わってリソースを削除したい時も、コマンド一発です。これがIaCの最大のメリットです。
リソースの完全削除(お片付け)
serverless remove
おわりに
本記事のコード生成やエラー解決の壁打ちには生成AIを活用しつつ、最終的に自分の手でインフラを構築・理解することができました。 この仕組みを作ったことで、AWSで様々なサービスを触る際も「明日には必ずコストが通知されるし、不要になればコマンド一発で消せる」という安心感を得ることができました。
これからAWSを学ぶ方の参考になれば幸いです!