aws-cloud-patterns について
aws-cloud-patternsは、AWSアプリケーションやインフラを構築する開発者向けのスキルです。Lambda、DynamoDB、CDK、S3イベント処理のパターンと確認項目を示します。
主な機能
- 01LambdaハンドラーとSDKクライアントのパターン
- 02DynamoDBのシングルテーブル設計
- 03CDKインフラの例
- 04S3イベント処理パターン
- 05IAMと運用上の安全対策
- 06インフラのチェックリスト
活用シーン
- 01Lambda APIハンドラーの構成
- 02DynamoDBのアクセスパターン設計
- 03CDKによるAWSインフラ定義
- 04S3イベントレコードの処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ rohitg00/ awesome-claude-code-toolkit --skill aws-cloud-patternsインストール後、Claude Code で/aws-cloud-patternsを入力して読み込まれたか確認します。
詳細
AWS クラウドパターン
Lambda 関数パターン
import { APIGatewayProxyHandlerV2 } from "aws-lambda";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, GetCommand } from "@aws-sdk/lib-dynamodb";
const client = DynamoDBDocumentClient.from(new DynamoDBClient({}));
export const handler: APIGatewayProxyHandlerV2 = async (event) => {
const id = event.pathParameters?.id;
if (!id) {
return { statusCode: 400, body: JSON.stringify({ error: "Missing id" }) };
}
const result = await client.send(
new GetCommand({ TableName: process.env.TABLE_NAME!, Key: { pk: id } })
);
if (!result.Item) {
return { statusCode: 404, body: JSON.stringify({ error: "Not found" }) };
}
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: JSON.stringify(result.Item),
};
};
呼び出し間で接続を再利用できるように、ハンドラーの外で SDK クライアントを初期化します。
DynamoDB のシングルテーブル設計
interface OrderItem {
pk: string; // USER#<userId>
sk: string; // ORDER#<orderId>
gsi1pk: string; // ORDER#<orderId>
gsi1sk: string; // ITEM#<itemId>
entityType: string; // "Order" | "OrderItem"
data: Record<string, any>;
ttl?: number;
}
const params = {
TableName: "AppTable",
KeyConditionExpression: "pk = :pk AND begins_with(sk, :prefix)",
ExpressionAttributeValues: {
":pk": `USER#${userId}`,
":prefix": "ORDER#",
},
};
まずアクセスパターンを設計し、その後キーをモデル化します。別のクエリパターンには GSI を使用します。
CDK インフラストラクチャ
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as lambda from "aws-cdk-lib/aws-lambda-nodejs";
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
import * as apigateway from "aws-cdk-lib/aws-apigatewayv2";
export class ApiStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const table = new dynamodb.Table(this, "AppTable", {
partitionKey: { name: "pk", type: dynamodb.AttributeType.STRING },
sortKey: { name: "sk", type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
pointInTimeRecovery: true,
removalPolicy: cdk.RemovalPolicy.RETAIN,
});
const fn = new lambda.NodejsFunction(this, "ApiHandler", {
entry: "src/handler.ts",
runtime: cdk.aws_lambda.Runtime.NODEJS_22_X,
architecture: cdk.aws_lambda.Architecture.ARM_64,
memorySize: 256,
timeout: cdk.Duration.seconds(10),
environment: { TABLE_NAME: table.tableName },
});
table.grantReadWriteData(fn);
}
}
S3 イベント処理
import { S3Event } from "aws-lambda";
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
const s3 = new S3Client({});
export async function handler(event: S3Event) {
for (const record of event.Records) {
const bucket = record.s3.bucket.name;
const key = decodeURIComponent(record.s3.object.key.replace(/\+/g, " "));
const obj = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
const body = await obj.Body?.transformToString();
await processFile(key, body);
}
}
アンチパターン
- IAM ロールを使用せず、AWS 認証情報をハードコーディングする
- Lambda のタイムアウトとメモリを適切に設定しない
- キー条件を指定したクエリではなく、DynamoDB で
SELECT *に相当するスキャンを使用する - ドメインごとにまとめず、CRUD 操作ごとに Lambda を作成する
- エラー率やスロットリングに対する CloudWatch アラームがない
- DynamoDB テーブルのポイントインタイムリカバリを有効にしない
チェックリスト
- SDK クライアントを Lambda ハンドラーの外で初期化している
- IAM ロールが最小権限の原則に従っている
- テーブルスキーマの設計前に DynamoDB のアクセスパターンを設計している
- コスト削減のため、Lambda で ARM64 アーキテクチャを使用している
- S3 バケットでバージョニングとライフサイクルポリシーを設定している
- Lambda のエラー、実行時間、スロットリングに対する CloudWatch アラームを設定している
- インフラストラクチャをコード(CDK または Terraform)として定義している
- シークレットを Systems Manager Parameter Store または Secrets Manager に保存している
コメント
Markdown 対応