Building an Automated Cloud Cost Optimization and CI/CD Pipeline on AWS¶
チェック¶
- [ ] 本文を確認した
- [ ] 概要を確認した
- [ ] タグを確認した
- [ ]
inbox/直下へ移行した
概要¶
AWS 上で、アイドルリソース検出、停止アクション、レポート保存、AI サマリ、CI/CD を組み合わせたクラウドコスト最適化パイプラインを作る記事。 Terraform で S3、DynamoDB、IAM、SNS、CloudWatch を用意し、Lambda で scanner、action、ai_insights を実装する。 GitHub Actions、Docker、ECR、Terraform workspace を使い、staging/production 環境へデプロイする流れまで扱う。
本文¶
記事の構成はフェーズ分けされている。 最初に Terraform で基盤を作り、その後 Lambda を実装し、Docker/ECR でパッケージ化し、GitHub Actions で CI/CD へつなげる。
全体アーキテクチャ¶
目的は、クラウド上の無駄なリソースを自動検出し、必要に応じて停止し、結果を保存し、通知や AI サマリを作ること。
主要コンポーネントは次の通り。
- Terraform: AWS リソース定義。
- Lambda scanner: アイドルリソースや未使用リソースを検出。
- Lambda action: 停止やタグ付けなどのアクションを実行。
- Lambda ai_insights: レポートを読み、要約や通知を行う。
- S3: レポート、ログ、AI サマリの保存先。
- DynamoDB: 検出履歴やアクション履歴の保存先。
- SNS: 通知。
- CloudWatch: ダッシュボードやスケジュール実行。
- GitHub Actions: テスト、Docker build、ECR push、Terraform deploy。
Terraform の基盤¶
Terraform では、環境ごとに staging/production を分ける。 記事では Terraform workspace を使う。
cd terraform
terraform init
terraform workspace new staging
terraform workspace new production
terraform apply -var="environment=staging"
remote state は S3 に置き、DynamoDB で state lock を取る構成。 複数人や CI/CD で Terraform を実行するなら、remote state と lock は必須に近い。
Terraform で作るものは、レポート用 S3 bucket、DynamoDB table、Lambda 用 IAM role/policy、SNS topic、CloudWatch dashboard placeholder など。 環境名をリソース名に含め、staging と production が混ざらないようにする。
例として、staging なら次のようなリソースが作られる。
cloud-cost-optimizer-staging-reports- コスト検出履歴用 DynamoDB table
- Lambda 実行 role
- 通知用 SNS topic
scanner Lambda¶
scanner は、AWS リソースを調べ、コスト削減候補を findings として出す。 記事の例では EC2 と S3 が対象。
EC2 では、実行中インスタンスを列挙し、CPU 使用率が低いものを idle candidate として扱う。 S3 では、空の bucket などを検出対象にする。
検出結果は DynamoDB と S3 に保存する。 Lambda の環境変数には、DynamoDB table、report bucket、environment を渡す。
戻り値には findings count を含める。
action Lambda¶
action Lambda は、検出されたリソースに対して停止などの処理を行う。 記事の例では、EC2 instance を stop し、アクション履歴を DynamoDB と S3 に保存する。
実運用では、いきなり停止するのではなく、タグ、承認、対象除外、スケジュール、所有者通知などを入れる必要がある。 ただし記事のサンプルでは、仕組みを理解するために action Lambda が直接停止処理を行う構成になっている。
ai_insights Lambda¶
ai_insights Lambda は、最新レポートを S3 から読み、要約を作成し、S3 の ai_summaries などへ保存し、SNS へ通知する。
記事タイトルには Bedrock も含まれており、AI によるコスト最適化サマリや推奨事項を作る位置づけ。
AI 要約は、人間が大量の findings を読む負担を減らす。 ただし、停止判断そのものを AI に任せる場合はリスクが高いため、承認フローや対象除外ルールと組み合わせる必要がある。
Lambda のテスト¶
記事では moto を使った Python Lambda のユニットテストが紹介されている。
AWS 実環境へアクセスせず、DynamoDB や S3 を mock して Lambda handler をテストする。
from moto import mock_aws
import boto3
import json
import os
from importlib import reload
import lambdas.scanner.main as scanner_main
@mock_aws
def test_lambda():
os.environ["RESOURCE_TABLE"] = "test-table"
os.environ["REPORT_BUCKET"] = "test-reports"
os.environ["ENVIRONMENT"] = "staging"
reload(scanner_main)
from lambdas.scanner.main import lambda_handler
dynamodb = boto3.client("dynamodb", region_name="us-east-1")
s3 = boto3.client("s3", region_name="us-east-1")
s3.create_bucket(Bucket="test-reports")
dynamodb.create_table(
TableName="test-table",
KeySchema=[{"AttributeName": "resource_id", "KeyType": "HASH"}],
AttributeDefinitions=[{"AttributeName": "resource_id", "AttributeType": "S"}],
BillingMode="PAY_PER_REQUEST",
)
result = lambda_handler({}, {})
assert result["statusCode"] == 200
assert "findings" in json.loads(result["body"])
テストは次のように実行する。
Docker と ECR¶
Lambda は container image として package する。 Python 3.12 の Lambda base image を使う Dockerfile は次のような形。
FROM public.ecr.aws/lambda/python:3.12
COPY main.py ${LAMBDA_TASK_ROOT}
COPY requirements.txt ./
RUN pip install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"
CMD ["main.lambda_handler"]
build、login、ECR repository 作成、tag、push の流れは次の通り。
docker build -t scanner-lambda ./lambdas/scanner
aws ecr get-login-password --region us-east-1 \
| docker login --username AWS --password-stdin <account-id>.dkr.ecr.us-east-1.amazonaws.com
aws ecr create-repository --repository-name scanner-lambda
docker tag scanner-lambda:latest \
<account-id>.dkr.ecr.us-east-1.amazonaws.com/scanner-lambda:latest
docker push <account-id>.dkr.ecr.us-east-1.amazonaws.com/scanner-lambda:latest
Terraform では、Lambda function の package_type を Image にし、ECR image URI を指定する。
timeout は 300 秒、環境変数として table、bucket、environment を渡す。
記事では、PowerShell の pipe まわりや、Docker BuildKit の manifest が Lambda と合わない問題にも触れている。 BuildKit 由来の問題が出る場合は、環境変数で無効化する。
GitHub Actions の CI/CD¶
CI では、Pull Request で lint、unit test、Docker build を行い、必要に応じて ECR push まで行う。 CD では、main branch への merge 後に Terraform apply を実行し、最新 image を Lambda に反映する。
GitHub Actions では、AWS credentials を設定し、ECR login を行い、Docker image を build/push し、Terraform を実行する。 大まかな流れは次のようになる。
name: ci
on:
pull_request:
jobs:
test-and-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-east-1
- uses: aws-actions/amazon-ecr-login@v2
- run: python -m pytest -v
- run: docker build -t scanner-lambda ./lambdas/scanner
本番適用では、workspace、環境変数、承認、OIDC、最小権限 IAM を整える必要がある。
読み替え¶
この記事は、クラウドコスト最適化の「仕組み作り」を学ぶサンプルとして使える。 ただし、実運用で自動停止を行うには、所有者確認、タグ運用、承認フロー、除外リスト、営業時間、依存関係、監査ログを必ず設計する。
AI 要約は便利だが、コスト削減アクションの最終判断をいきなり AI に任せるのは危険。 まずは検出とレポートから始め、通知、承認、自動化の順に広げるのが安全。
要点¶
- Terraform で S3、DynamoDB、IAM、SNS、CloudWatch、Lambda を管理する。
- scanner Lambda はアイドル EC2 や空 S3 bucket などを findings として検出する。
- action Lambda は停止などの処理を行い、履歴を保存する。
- ai_insights Lambda はレポートを要約し、SNS などで通知する。
- Lambda は Docker image として ECR に push できる。
- moto を使うと AWS リソースを mock して Lambda をテストできる。
- GitHub Actions で test、build、push、Terraform apply をつなげる。
- 実運用では、承認、除外、監査、最小権限を必ず設計する。