aws-cloud-services について
aws-cloud-servicesは、Amazon Web Servicesのインフラを構築・運用する開発者やアーキテクト向けの学習スキルです。主要サービスに加え、セキュリティ、デプロイ、設計の実践を扱います。
主な機能
- 01S3オブジェクトストレージ操作
- 02Lambdaイベント駆動関数
- 03DynamoDBとRDSのデータベースガイド
- 04IAMアクセス制御と認証情報管理
- 05CloudFormationによるインフラ自動化
- 06アーキテクチャとコスト最適化の指針
活用シーン
- 01Lambdaを使ったサーバーレスアプリの設計
- 02S3のファイルアップロードとダウンロード管理
- 03最小権限のIAMポリシー設定
- 04CloudFormationによるインフラの自動デプロイ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ manutej/ luxor-claude-marketplace --skill aws-cloud-servicesインストール後、Claude Code で/aws-cloud-servicesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.summary.txtEXAMPLES.mdREADME.md詳細
AWS クラウドサービス
Amazon Web Services(AWS)上でクラウドインフラストラクチャを構築、デプロイ、管理するための包括的なスキルです。S3 オブジェクトストレージ、Lambda サーバーレス関数、DynamoDB NoSQL データベース、EC2 コンピューティングインスタンス、RDS リレーショナルデータベース、IAM セキュリティ、CloudFormation による Infrastructure as Code、エンタープライズグレードのクラウドアーキテクチャパターンを習得します。
このスキルを使用する場面
次のような場合にこのスキルを使用します。
- AWS インフラストラクチャ上でスケーラブルなクラウドアプリケーションを構築する
- Lambda と API Gateway を使用してサーバーレスアーキテクチャを実装する
- S3 を使用してオブジェクトストレージとファイルアップロードを管理する
- DynamoDB を使用して NoSQL データベースソリューションを設計する
- EC2 インスタンスをデプロイし、コンピューティングリソースを管理する
- リレーショナルデータの保存に RDS データベースを設定する
- IAM セキュリティポリシーとアクセス制御を実装する
- CloudFormation を使用してインフラストラクチャのデプロイを自動化する
- マルチリージョンの高可用性システムを設計する
- クラウドのコストとパフォーマンスを最適化する
- オンプレミスのアプリケーションを AWS に移行する
- イベント駆動型アーキテクチャを実装する
- データパイプラインと分析ソリューションを構築する
- シークレットと認証情報を安全に管理する
- AWS サービスを使用して CI/CD パイプラインを設定する
主な概念
AWS の基礎
AWS は、コンピューティング、ストレージ、データベース、ネットワーク、セキュリティなどにわたる 200 以上のサービスを提供する、Amazon の包括的なクラウドコンピューティングプラットフォームです。
主な概念
リージョンとアベイラビリティーゾーン
- リージョン:複数のデータセンターを擁する地理的なエリア(例:us-east-1、eu-west-1)
- アベイラビリティーゾーン(AZ):リージョン内にある独立したデータセンター
- エッジロケーション:CloudFront のコンテンツ配信に使用する CDN エンドポイント
- ローカルゾーン:超低レイテンシーを実現するためにリージョンを拡張したもの
AWS アカウント構成
- ルートアカウント:すべてのアクセス権を持つプライマリアカウント(使用は最小限にしてください)
- IAM ユーザー:特定の権限を持つ個別ユーザーアカウント
- IAM ロール:サービスやアプリケーション向けの一時的な認証情報
- Organizations:企業向けのマルチアカウント管理
サービスカテゴリ
- コンピューティング:EC2、Lambda、ECS、EKS、Fargate
- ストレージ:S3、EBS、EFS、Glacier
- データベース:RDS、DynamoDB、Aurora、ElastiCache、Redshift
- ネットワーク:VPC、Route 53、CloudFront、API Gateway、ELB
- セキュリティ:IAM、Cognito、Secrets Manager、KMS、WAF
- インフラストラクチャ:CloudFormation、CDK、Systems Manager
- モニタリング:CloudWatch、X-Ray、CloudTrail
JavaScript 用 AWS SDK v3
AWS SDK v3 はモジュール型で、ツリーシェイキングに対応し、最新の JavaScript/TypeScript アプリケーション向けに最適化されています。
主な改善点
モジュール型アーキテクチャ
// v2 (monolithic)
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
// v3 (modular)
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
const client = new S3Client({ region: 'us-east-1' });
コマンドパターン
- 各操作はコマンドクラスです
- クライアントとコマンドが明確に分離されています
- TypeScript のサポートと型推論が向上しています
ミドルウェアスタック
- カスタマイズ可能なリクエスト/レスポンスのパイプライン
- リトライと指数バックオフを標準でサポート
- リクエストの署名と認証
アイデンティティとアクセス管理(IAM)
IAM は、すべての AWS サービスにおける認証と認可を制御します。
IAM の主要コンポーネント
ユーザー
- 長期的な認証情報を持つ個別の ID
- プログラムによるアクセス用のアクセスキー
- コンソールアクセス用のパスワード
- MFA(多要素認証)のサポート
グループ
- ユーザーの集合
- ポリシーを適用し、権限を一括管理
- ユーザーは複数のグループに所属できます
ロール
- ユーザー、サービス、アプリケーションが引き受ける一時的な認証情報
- クロスアカウントアクセス
- サービス間通信
- 外部 ID プロバイダーとのフェデレーション
ポリシー
- 権限を定義する JSON ドキュメント
- ID ベースのポリシー(ユーザー/グループ/ロールに適用)
- リソースベースのポリシー(S3 バケットなどのリソースに適用)
- Organizations 向けのサービスコントロールポリシー(SCP)
ポリシーの構造
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
}
}
}
]
}
ポリシーの要素
- Effect:許可または拒否
- Action:サービスと操作(例:s3:GetObject)
- Resource:影響を受けるリソースの ARN
- Condition:任意の制約(IP、時間、MFA など)
- Principal:ポリシーの適用対象(リソースベースのポリシーの場合)
最小権限の原則
必要最小限の権限のみを常に付与してください。
- 権限のない状態から始めます
- 必要に応じて権限を段階的に追加します
- 一般的なパターンには管理ポリシーを使用します
- 特定のユースケースにはカスタムポリシーを作成します
- 定期的に監査し、未使用の権限を削除します
認証情報の管理
認証情報チェーン
SDK は次の順序で認証情報を検索します。
- 環境変数:AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY
- 共有認証情報ファイル:~/.aws/credentials
- 共有設定ファイル:~/.aws/config
- IAM ロール(EC2/ECS/Lambda):インスタンスメタデータサービス
- プロセス認証情報:カスタム実行可能ファイルから取得
ベストプラクティス
- ソースコードに認証情報をハードコードしないでください
- EC2、Lambda、ECS ではIAM ロールを使用してください
- 可能な限り一時的な認証情報を使用してください
- アクセスキーを定期的にローテーションしてください(推奨期間は 90 日です)
- アプリケーションのシークレットにはAWS Secrets Manager を使用してください
- 特権アカウントではMFA を有効にしてください
- 一元的なアクセス管理にはAWS SSO を使用してください
リージョンとエンドポイントの設定
import { S3Client } from '@aws-sdk/client-s3';
// Specify region explicitly
const client = new S3Client({
region: 'us-west-2',
endpoint: 'https://s3.us-west-2.amazonaws.com' // Optional custom endpoint
});
// Use default region from environment/config
const defaultClient = new S3Client({}); // Uses AWS_REGION or default region
S3(Simple Storage Service)
S3 は、あらゆる場所から任意の量のデータを保存、取得できる AWS のオブジェクトストレージサービスです。
S3 の基本概念
バケット
- グローバルに一意な名前:すべての AWS アカウント間で一意である必要があります
- リージョナルリソース:特定のリージョンに作成されます
- オブジェクト数無制限:オブジェクト数に制限はありません
- バケットポリシー:リソースベースのアクセス制御
- バージョニング:オブジェクトの複数のバージョンを保持します
- 暗号化:サーバー側とクライアント側の暗号化
オブジェクト
- キーと値のストア:キーはオブジェクト名、値はデータです
- メタデータ:システム定義およびユーザー定義のメタデータ
- サイズ制限:オブジェクトあたり 5TB
- マルチパートアップロード:100MB を超えるオブジェクトに使用します(5GB を超える場合は必須)
- ストレージクラス:Standard、IA、Glacier など
S3 ストレージクラス
S3 Standard
- 頻繁にアクセスされるデータ
- 可用性 99.99%
- ミリ秒単位のレイテンシー
S3 Intelligent-Tiering
- コストを自動的に最適化します
- データをアクセス階層間で移動します
S3 Standard-IA(低頻度アクセス)
- アクセス頻度の低いデータを低コストで保存します
- データ取得料金が適用されます
S3 One Zone-IA
- 重要度の低いデータ向けの単一 AZ ストレージ
- Standard-IA より 20% 安価です
S3 Glacier
- 長期アーカイブ
- 取得に数分から数時間かかります
- 非常に低コストです
S3 Glacier Deep Archive
- 最も低コストのストレージ
- 取得に 12 時間かかります
- コンプライアンス用アーカイブに最適です
S3 の操作
オブジェクトのアップロード
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { readFileSync } from 'fs';
const client = new S3Client({ region: 'us-east-1' });
// Simple upload
const uploadFile = async (bucketName, key, filePath) => {
const fileContent = readFileSync(filePath);
const command = new PutObjectCommand({
Bucket: bucketName,
Key: key,
Body: fileContent,
ContentType: 'image/jpeg', // Optional
Metadata: { // Optional custom metadata
'uploaded-by': 'user-123',
'upload-date': new Date().toISOString()
},
ServerSideEncryption: 'AES256', // Enable encryption
ACL: 'private' // Access control
});
const response = await client.send(command);
return response;
};
オブジェクトのダウンロード
import { GetObjectCommand } from '@aws-sdk/client-s3';
import { writeFileSync } from 'fs';
const downloadFile = async (bucketName, key, destinationPath) => {
const command = new GetObjectCommand({
Bucket: bucketName,
Key: key
});
const response = await client.send(command);
// Convert stream to buffer
const chunks = [];
for await (const chunk of response.Body) {
chunks.push(chunk);
}
const buffer = Buffer.concat(chunks);
writeFileSync(destinationPath, buffer);
return response.Metadata;
};
オブジェクトの一覧表示
import { ListObjectsV2Command } from '@aws-sdk/client-s3';
const listObjects = async (bucketName, prefix = '') => {
const command = new ListObjectsV2Command({
Bucket: bucketName,
Prefix: prefix, // Filter by prefix
MaxKeys: 1000, // Max 1000 per request
Delimiter: '/' // Treat / as folder separator
});
const response = await client.send(command);
return response.Contents; // Array of objects
};
// Pagination for large buckets
const listAllObjects = async (bucketName) => {
let allObjects = [];
let continuationToken;
do {
const command = new ListObjectsV2Command({
Bucket: bucketName,
ContinuationToken: continuationToken
});
const response = await client.send(command);
allObjects = allObjects.concat(response.Contents || []);
continuationToken = response.NextContinuationToken;
} while (continuationToken);
return allObjects;
};
オブジェクトの削除
import { DeleteObjectCommand, DeleteObjectsCommand } from '@aws-sdk/client-s3';
// Delete single object
const deleteObject = async (bucketName, key) => {
const command = new DeleteObjectCommand({
Bucket: bucketName,
Key: key
});
await client.send(command);
};
// Delete multiple objects (up to 1000 at once)
const deleteMultipleObjects = async (bucketName, keys) => {
const command = new DeleteObjectsCommand({
Bucket: bucketName,
Delete: {
Objects: keys.map(key => ({ Key: key })),
Quiet: false // Return list of deleted objects
}
});
const response = await client.send(command);
return response.Deleted;
};
署名付き URL
AWS 認証情報を使わずにファイルを安全にアップロード/ダウンロードするための、一時的な URL を生成します。
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';
// Presigned URL for upload
const createUploadUrl = async (bucketName, key, expiresIn = 3600) => {
const command = new PutObjectCommand({
Bucket: bucketName,
Key: key,
ContentType: 'image/jpeg'
});
const url = await getSignedUrl(client, command, { expiresIn });
return url; // Client can PUT to this URL
};
// Presigned URL for download
const createDownloadUrl = async (bucketName, key, expiresIn = 3600) => {
const command = new GetObjectCommand({
Bucket: bucketName,
Key: key
});
const url = await getSignedUrl(client, command, { expiresIn });
return url; // Client can GET from this URL
};
マルチパートアップロード
大きなファイル(100MB 超)には、パフォーマンスと信頼性を高めるためにマルチパートアップロードを使用します。
import {
CreateMultipartUploadCommand,
UploadPartCommand,
CompleteMultipartUploadCommand,
AbortMultipartUploadCommand
} from '@aws-sdk/client-s3';
const multipartUpload = async (bucketName, key, fileBuffer, partSize = 5 * 1024 * 1024) => {
// 1. Initiate multipart upload
const createCommand = new CreateMultipartUploadCommand({
Bucket: bucketName,
Key: key
});
const { UploadId } = await client.send(createCommand);
try {
// 2. Upload parts
const parts = [];
const numParts = Math.ceil(fileBuffer.length / partSize);
for (let i = 0; i < numParts; i++) {
const start = i * partSize;
const end = Math.min(start + partSize, fileBuffer.length);
const partBody = fileBuffer.slice(start, end);
const uploadCommand = new UploadPartCommand({
Bucket: bucketName,
Key: key,
UploadId,
PartNumber: i + 1,
Body: partBody
});
const { ETag } = await client.send(uploadCommand);
parts.push({ PartNumber: i + 1, ETag });
}
// 3. Complete multipart upload
const completeCommand = new CompleteMultipartUploadCommand({
Bucket: bucketName,
Key: key,
UploadId,
MultipartUpload: { Parts: parts }
});
const result = await client.send(completeCommand);
return result;
} catch (error) {
// Abort on error to avoid storage charges for incomplete uploads
const abortCommand = new AbortMultipartUploadCommand({
Bucket: bucketName,
Key: key,
UploadId
});
await client.send(abortCommand);
throw error;
}
};
Lambda
AWS Lambda は、サーバーをプロビジョニングせずに、イベントに応じてコードを実行するサーバーレスコンピューティングサービスです。
Lambda の基本概念
実行モデル
- イベント駆動型:AWS サービスからのイベントまたは HTTP リクエストによって起動されます
- ステートレス:呼び出しはそれぞれ独立しています
- 同時実行:需要に応じて自動的にスケールします
- タイムアウト:最大実行時間は 15 分です
- メモリ:128MB から 10GB(CPU はメモリに応じてスケールします)
ハンドラー関数
// Lambda handler signature
export const handler = async (event, context) => {
// event: Input data (API request, S3 event, etc.)
// context: Runtime information (request ID, remaining time, etc.)
console.log('Event:', JSON.stringify(event, null, 2));
console.log('Request ID:', context.requestId);
console.log('Remaining time:', context.getRemainingTimeInMillis());
// Process event
const result = await processEvent(event);
// Return response
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(result)
};
};
呼び出しタイプ
同期(RequestResponse)
- API Gateway、SDK による呼び出し
- 呼び出し元はレスポンスを待機します
- エラーは呼び出し元に返されます
非同期(Event)
- S3、SNS、CloudWatch Events
- Lambda はイベントをキューに登録し、すぐに応答を返します
- 組み込みの再試行(2 回)
- 失敗時のデッドレターキュー
ポーリングベース(Stream)
- DynamoDB Streams、Kinesis
- Lambda はストリームをポーリングして関数を呼び出します
- シャード内で順序どおりに処理します
Lambda の設定
// Using AWS SDK to create/update Lambda function
import {
LambdaClient,
CreateFunctionCommand,
UpdateFunctionCodeCommand,
UpdateFunctionConfigurationCommand
} from '@aws-sdk/client-lambda';
const lambdaClient = new LambdaClient({ region: 'us-east-1' });
const createFunction = async () => {
const command = new CreateFunctionCommand({
FunctionName: 'myFunction',
Runtime: 'nodejs20.x',
Role: 'arn:aws:iam::123456789012:role/lambda-execution-role',
Handler: 'index.handler',
Code: {
ZipFile: zipBuffer // Or S3Bucket/S3Key for S3-stored code
},
Environment: {
Variables: {
'BUCKET_NAME': 'my-bucket',
'TABLE_NAME': 'my-table'
}
},
MemorySize: 512, // MB
Timeout: 30, // seconds
Tags: {
'Environment': 'production',
'Team': 'backend'
}
});
const response = await lambdaClient.send(command);
return response.FunctionArn;
};
Lambda のイベントソース
API Gateway との統合
// Lambda function for API Gateway
export const handler = async (event) => {
// Parse request
const { httpMethod, path, queryStringParameters, body } = event;
const requestBody = body ? JSON.parse(body) : null;
// Route based on HTTP method and path
if (httpMethod === 'GET' && path === '/users') {
const users = await getUsers();
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(users)
};
}
if (httpMethod === 'POST' && path === '/users') {
const newUser = await createUser(requestBody);
return {
statusCode: 201,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newUser)
};
}
// Not found
return {
statusCode: 404,
body: JSON.stringify({ message: 'Not found' })
};
};
S3 イベントとの統合
// Lambda function triggered by S3 events
export const handler = async (event) => {
// Process each S3 event record
for (const record of event.Records) {
const bucket = record.s3.bucket.name;
const key = decodeURIComponent(record.s3.object.key.replace(/\+/g, ' '));
const eventName = record.eventName;
console.log(`Event: ${eventName}, Bucket: ${bucket}, Key: ${key}`);
if (eventName.startsWith('ObjectCreated:')) {
await processNewFile(bucket, key);
} else if (eventName.startsWith('ObjectRemoved:')) {
await handleFileDeleted(bucket, key);
}
}
return { statusCode: 200 };
};
DynamoDB Streams との統合
// Lambda function for DynamoDB Streams
export const handler = async (event) => {
for (const record of event.Records) {
const { eventName, dynamodb } = record;
// INSERT, MODIFY, REMOVE
console.log(`Event: ${eventName}`);
if (eventName === 'INSERT') {
const newItem = AWS.DynamoDB.Converter.unmarshall(dynamodb.NewImage);
await handleNewItem(newItem);
}
if (eventName === 'MODIFY') {
const oldItem = AWS.DynamoDB.Converter.unmarshall(dynamodb.OldImage);
const newItem = AWS.DynamoDB.Converter.unmarshall(dynamodb.NewImage);
await handleItemUpdate(oldItem, newItem);
}
if (eventName === 'REMOVE') {
const oldItem = AWS.DynamoDB.Converter.unmarshall(dynamodb.OldImage);
await handleItemDeleted(oldItem);
}
}
};
Lambda のベストプラクティス
コールドスタートの最適化
- デプロイパッケージを小さく保ちます
- 外部依存関係を最小限に抑えます
- レイテンシーに敏感な関数にはプロビジョニング済み同時実行数を使用します
- SDK クライアントをハンドラーの外部で初期化します
エラー処理
export const handler = async (event) => {
try {
// Process event
const result = await processEvent(event);
return { statusCode: 200, body: JSON.stringify(result) };
} catch (error) {
console.error('Error processing event:', error);
// Log to CloudWatch
console.error('Error details:', {
message: error.message,
stack: error.stack,
event
});
// Return error response
return {
statusCode: 500,
body: JSON.stringify({
error: 'Internal server error',
requestId: context.requestId
})
};
}
};
環境変数
// Access environment variables
const BUCKET_NAME = process.env.BUCKET_NAME;
const TABLE_NAME = process.env.TABLE_NAME;
const API_KEY = process.env.API_KEY; // Use Secrets Manager for sensitive data
DynamoDB
DynamoDB は、あらゆる規模で 1 桁ミリ秒のパフォーマンスを実現する、フルマネージドの NoSQL データベースサービスです。
DynamoDB の基本概念
テーブルと項目
テーブル:項目のコレクション(SQL のテーブルに相当) 項目:個々のレコード(行に相当)、最大 400KB 属性:キーと値のペア(列に相当) プライマリキー:各項目を一意に識別します
プライマリキーのタイプ
パーティションキー(単純なプライマリキー)
User Table:
- userId (Partition Key) -> "user-123"
- name -> "John Doe"
- email -> "[email protected]"
パーティションキー + ソートキー(複合プライマリキー)
Order Table:
- userId (Partition Key) -> "user-123"
- orderId (Sort Key) -> "order-456"
- total -> 99.99
- status -> "shipped"
インデックス
グローバルセカンダリインデックス(GSI)
- 異なるパーティションキー、または異なるソートキーを使用します
- すべてのパーティションにまたがります
- 結果整合性があります
- いつでも作成・削除できます
ローカルセカンダリインデックス(LSI)
- 同じパーティションキーを使用し、ソートキーは異なります
- パーティションの範囲内に限定されます
- 強い整合性または結果整合性があります
- テーブルの作成時に作成する必要があります
DynamoDB の操作
項目の登録
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, PutCommand } from '@aws-sdk/lib-dynamodb';
const client = new DynamoDBClient({ region: 'us-east-1' });
const docClient = DynamoDBDocumentClient.from(client);
const putItem = async (tableName, item) => {
const command = new PutCommand({
TableName: tableName,
Item: item,
ConditionExpression: 'attribute_not_exists(userId)', // Prevent overwrite
ReturnValues: 'ALL_OLD' // Return previous item if existed
});
try {
const response = await docClient.send(command);
return response;
} catch (error) {
if (error.name === 'ConditionalCheckFailedException') {
console.log('Item already exists');
}
throw error;
}
};
// Example usage
await putItem('Users', {
userId: 'user-123',
name: 'John Doe',
email: '[email protected]',
createdAt: new Date().toISOString(),
preferences: {
theme: 'dark',
notifications: true
}
});
項目の取得
import { GetCommand } from '@aws-sdk/lib-dynamodb';
const getItem = async (tableName, key) => {
const command = new GetCommand({
TableName: tableName,
Key: key,
ConsistentRead: true, // Strong consistency (default: false)
ProjectionExpression: 'userId, #n, email', // Return specific attributes
ExpressionAttributeNames: {
'#n': 'name' // name is reserved word, use placeholder
}
});
const response = await docClient.send(command);
return response.Item;
};
// Example usage
const user = await getItem('Users', { userId: 'user-123' });
項目の更新
import { UpdateCommand } from '@aws-sdk/lib-dynamodb';
const updateItem = async (tableName, key, updates) => {
const command = new UpdateCommand({
TableName: tableName,
Key: key,
UpdateExpression: 'SET #n = :name, email = :email, updatedAt = :now',
ExpressionAttributeNames: {
'#n': 'name'
},
ExpressionAttributeValues: {
':name': updates.name,
':email': updates.email,
':now': new Date().toISOString()
},
ConditionExpression: 'attribute_exists(userId)', // Only update if exists
ReturnValues: 'ALL_NEW' // Return updated item
});
const response = await docClient.send(command);
return response.Attributes;
};
// Atomic counter increment
const incrementCounter = async (tableName, key, counterAttribute) => {
const command = new UpdateCommand({
TableName: tableName,
Key: key,
UpdateExpression: 'ADD #counter :inc',
ExpressionAttributeNames: {
'#counter': counterAttribute
},
ExpressionAttributeValues: {
':inc': 1
},
ReturnValues: 'UPDATED_NEW'
});
const response = await docClient.send(command);
return response.Attributes[counterAttribute];
};
クエリ
同じパーティションキーを持つ項目を効率的にクエリします。
import { QueryCommand } from '@aws-sdk/lib-dynamodb';
const queryItems = async (tableName, partitionKeyValue) => {
const command = new QueryCommand({
TableName: tableName,
KeyConditionExpression: 'userId = :userId AND orderId BETWEEN :start AND :end',
ExpressionAttributeValues: {
':userId': partitionKeyValue,
':start': 'order-100',
':end': 'order-200'
},
FilterExpression: 'orderStatus = :status', // Filter results (applied after query)
ExpressionAttributeValues: {
':status': 'completed'
},
Limit: 100, // Max items to return
ScanIndexForward: false // Sort descending (default: ascending)
});
const response = await docClient.send(command);
return response.Items;
};
// Pagination
const queryAllItems = async (tableName, partitionKeyValue) => {
let allItems = [];
let lastEvaluatedKey;
do {
const command = new QueryCommand({
TableName: tableName,
KeyConditionExpression: 'userId = :userId',
ExpressionAttributeValues: {
':userId': partitionKeyValue
},
ExclusiveStartKey: lastEvaluatedKey
});
const response = await docClient.send(command);
allItems = allItems.concat(response.Items);
lastEvaluatedKey = response.LastEvaluatedKey;
} while (lastEvaluatedKey);
return allItems;
};
スキャン
テーブル全体をスキャンします(非効率なため、本番環境では避けてください)。
import { ScanCommand } from '@aws-sdk/lib-dynamodb';
const scanTable = async (tableName, filterExpression) => {
const command = new ScanCommand({
TableName: tableName,
FilterExpression: 'age > :minAge',
ExpressionAttributeValues: {
':minAge': 18
},
Limit: 1000
});
const response = await docClient.send(command);
return response.Items;
};
// Parallel scan for performance
const parallelScan = async (tableName, totalSegments = 4) => {
const scanSegment = async (segment) => {
const command = new ScanCommand({
TableName: tableName,
Segment: segment,
TotalSegments: totalSegments
});
const response = await docClient.send(command);
return response.Items;
};
// Scan all segments in parallel
const promises = [];
for (let i = 0; i < totalSegments; i++) {
promises.push(scanSegment(i));
}
const results = await Promise.all(promises);
return results.flat();
};
項目の削除
import { DeleteCommand } from '@aws-sdk/lib-dynamodb';
const deleteItem = async (tableName, key) => {
const command = new DeleteCommand({
TableName: tableName,
Key: key,
ConditionExpression: 'attribute_exists(userId)', // Only delete if exists
ReturnValues: 'ALL_OLD' // Return deleted item
});
const response = await docClient.send(command);
return response.Attributes;
};
バッチ操作
import { BatchGetCommand, BatchWriteCommand } from '@aws-sdk/lib-dynamodb';
// Batch get (up to 100 items)
const batchGetItems = async (tableName, keys) => {
const command = new BatchGetCommand({
RequestItems: {
[tableName]: {
Keys: keys // Array of key objects
}
}
});
const response = await docClient.send(command);
return response.Responses[tableName];
};
// Batch write (up to 25 items)
const batchWriteItems = async (tableName, items) => {
const command = new BatchWriteCommand({
RequestItems: {
[tableName]: items.map(item => ({
PutRequest: { Item: item }
}))
}
});
await docClient.send(command);
};
// Batch delete
const batchDeleteItems = async (tableName, keys) => {
const command = new BatchWriteCommand({
RequestItems: {
[tableName]: keys.map(key => ({
DeleteRequest: { Key: key }
}))
}
});
await docClient.send(command);
};
DynamoDB のパターン
シングルテーブル設計
複雑なデータモデルには、キーを多目的に使用する 1 つのテーブルを使います。
// User entity
{
PK: "USER#user-123",
SK: "METADATA",
type: "user",
name: "John Doe",
email: "[email protected]"
}
// User's order
{
PK: "USER#user-123",
SK: "ORDER#order-456",
type: "order",
total: 99.99,
status: "shipped"
}
// Access patterns:
// 1. Get user: PK = "USER#user-123", SK = "METADATA"
// 2. Get all user's orders: PK = "USER#user-123", SK begins_with "ORDER#"
// 3. Get specific order: PK = "USER#user-123", SK = "ORDER#order-456"
EC2(Elastic Compute Cloud)
EC2 は、仮想マシン(インスタンス)を使用して、クラウドでサイズ変更可能なコンピューティング容量を提供します。
EC2 の基本概念
インスタンスタイプ
汎用(T3、M6i)
- CPU、メモリ、ネットワークのバランスが取れています
- Web サーバー、開発環境
コンピューティング最適化(C6i)
- 高性能プロセッサ
- バッチ処理、ゲームサーバー
メモリ最適化(R6i、X2idn)
- 大規模なインメモリワークロード
- データベース、キャッシュレイヤー
ストレージ最適化(I4i、D3)
- シーケンシャル読み取り/書き込み性能が高い
- データウェアハウス、分散ファイルシステム
高速コンピューティング(P4、G5)
- GPU インスタンス
- 機械学習、グラフィックスレンダリング
AMI(Amazon Machine Image)
インスタンス用の事前設定済みテンプレートで、次のものが含まれます。
- オペレーティングシステム(Amazon Linux、Ubuntu、Windows など)
- アプリケーションソフトウェア
- 設定
EC2 の操作
import {
EC2Client,
RunInstancesCommand,
DescribeInstancesCommand,
StartInstancesCommand,
StopInstancesCommand,
TerminateInstancesCommand
} from '@aws-sdk/client-ec2';
const ec2Client = new EC2Client({ region: 'us-east-1' });
// Launch instance
const launchInstance = async () => {
const command = new RunInstancesCommand({
ImageId: 'ami-0c55b159cbfafe1f0', // Amazon Linux 2 AMI
InstanceType: 't3.micro',
MinCount: 1,
MaxCount: 1,
KeyName: 'my-key-pair',
SecurityGroupIds: ['sg-0123456789abcdef0'],
SubnetId: 'subnet-0123456789abcdef0',
IamInstanceProfile: {
Name: 'ec2-instance-profile'
},
UserData: Buffer.from(`#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "Hello from EC2" > /var/www/html/index.html
`).toString('base64'),
TagSpecifications: [{
ResourceType: 'instance',
Tags: [
{ Key: 'Name', Value: 'WebServer' },
{ Key: 'Environment', Value: 'production' }
]
}]
});
const response = await ec2Client.send(command);
return response.Instances[0].InstanceId;
};
// Describe instances
const describeInstances = async (instanceIds) => {
const command = new DescribeInstancesCommand({
InstanceIds: instanceIds,
Filters: [
{ Name: 'instance-state-name', Values: ['running'] }
]
});
const response = await ec2Client.send(command);
return response.Reservations.flatMap(r => r.Instances);
};
// Stop instance
const stopInstance = async (instanceId) => {
const command = new StopInstancesCommand({
InstanceIds: [instanceId]
});
await ec2Client.send(command);
};
// Terminate instance
const terminateInstance = async (instanceId) => {
const command = new TerminateInstancesCommand({
InstanceIds: [instanceId]
});
await ec2Client.send(command);
};
RDS(Relational Database Service)
RDS は、マネージド型のリレーショナルデータベース(PostgreSQL、MySQL、MariaDB、Oracle、SQL Server、Aurora)を提供します。
RDS の操作
import {
RDSClient,
CreateDBInstanceCommand,
DescribeDBInstancesCommand,
ModifyDBInstanceCommand,
DeleteDBInstanceCommand
} from '@aws-sdk/client-rds';
const rdsClient = new RDSClient({ region: 'us-east-1' });
// Create database instance
const createDatabase = async () => {
const command = new CreateDBInstanceCommand({
DBInstanceIdentifier: 'mydb',
DBInstanceClass: 'db.t3.micro',
Engine: 'postgres',
EngineVersion: '15.3',
MasterUsername: 'admin',
MasterUserPassword: 'SecurePassword123!',
AllocatedStorage: 20, // GB
StorageType: 'gp3',
BackupRetentionPeriod: 7, // days
MultiAZ: true, // High availability
PubliclyAccessible: false,
VpcSecurityGroupIds: ['sg-0123456789abcdef0'],
DBSubnetGroupName: 'my-db-subnet-group',
StorageEncrypted: true,
Tags: [
{ Key: 'Environment', Value: 'production' },
{ Key: 'Application', Value: 'api' }
]
});
const response = await rdsClient.send(command);
return response.DBInstance;
};
// Describe database
const describeDatabase = async (dbInstanceId) => {
const command = new DescribeDBInstancesCommand({
DBInstanceIdentifier: dbInstanceId
});
const response = await rdsClient.send(command);
return response.DBInstances[0];
};
CloudFormation
AWS リソースを定義してプロビジョニングするための、Infrastructure as Code(IaC)サービスです。
CloudFormation テンプレート
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Full-stack web application infrastructure'
Parameters:
Environment:
Type: String
Default: production
AllowedValues:
- development
- staging
- production
Resources:
# S3 Bucket for static assets
AssetsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub '${AWS::StackName}-assets-${Environment}'
VersioningConfiguration:
Status: Enabled
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
# DynamoDB Table
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Sub '${AWS::StackName}-users-${Environment}'
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
- AttributeName: email
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
GlobalSecondaryIndexes:
- IndexName: EmailIndex
KeySchema:
- AttributeName: email
KeyType: HASH
Projection:
ProjectionType: ALL
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
# Lambda Execution Role
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: DynamoDBAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:Query
Resource: !GetAtt UsersTable.Arn
# Lambda Function
ApiFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub '${AWS::StackName}-api-${Environment}'
Runtime: nodejs20.x
Handler: index.handler
Role: !GetAtt LambdaExecutionRole.Arn
Code:
ZipFile: |
exports.handler = async (event) => {
return {
statusCode: 200,
body: JSON.stringify({ message: 'Hello from Lambda!' })
};
};
Environment:
Variables:
TABLE_NAME: !Ref UsersTable
BUCKET_NAME: !Ref AssetsBucket
ENVIRONMENT: !Ref Environment
Timeout: 30
MemorySize: 512
# API Gateway
RestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Sub '${AWS::StackName}-api-${Environment}'
Description: REST API for application
ApiResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref RestApi
ParentId: !GetAtt RestApi.RootResourceId
PathPart: users
ApiMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RestApi
ResourceId: !Ref ApiResource
HttpMethod: GET
AuthorizationType: NONE
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ApiFunction.Arn}/invocations'
ApiDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn: ApiMethod
Properties:
RestApiId: !Ref RestApi
StageName: !Ref Environment
LambdaApiPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref ApiFunction
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
SourceArn: !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*'
Outputs:
ApiUrl:
Description: API Gateway URL
Value: !Sub 'https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/${Environment}'
Export:
Name: !Sub '${AWS::StackName}-api-url'
BucketName:
Description: S3 Bucket Name
Value: !Ref AssetsBucket
Export:
Name: !Sub '${AWS::StackName}-bucket-name'
TableName:
Description: DynamoDB Table Name
Value: !Ref UsersTable
Export:
Name: !Sub '${AWS::StackName}-table-name'
CloudFormation の操作
import {
CloudFormationClient,
CreateStackCommand,
DescribeStacksCommand,
UpdateStackCommand,
DeleteStackCommand
} from '@aws-sdk/client-cloudformation';
import { readFileSync } from 'fs';
const cfClient = new CloudFormationClient({ region: 'us-east-1' });
// Create stack
const createStack = async (stackName, templatePath, parameters = {}) => {
const templateBody = readFileSync(templatePath, 'utf8');
const command = new CreateStackCommand({
StackName: stackName,
TemplateBody: templateBody,
Parameters: Object.entries(parameters).map(([key, value]) => ({
ParameterKey: key,
ParameterValue: value
})),
Capabilities: ['CAPABILITY_IAM'],
Tags: [
{ Key: 'ManagedBy', Value: 'CloudFormation' },
{ Key: 'Application', Value: 'MyApp' }
]
});
const response = await cfClient.send(command);
return response.StackId;
};
// Get stack status
const getStackStatus = async (stackName) => {
const command = new DescribeStacksCommand({
StackName: stackName
});
const response = await cfClient.send(command);
const stack = response.Stacks[0];
return {
status: stack.StackStatus,
outputs: stack.Outputs || []
};
};
ベストプラクティス
セキュリティ
IAM のベストプラクティス
- root アカウントと特権アカウントで MFA を有効にします
- アクセスキーではなく IAM ロールを使用します
- 最小権限の原則を適用します
- 認証情報を定期的にローテーションします
- IAM Access Analyzer を使用して、権限が過剰なポリシーを特定します
- 監査ログを記録するために CloudTrail を有効にします
データの暗号化
- 保存データを暗号化します(S3、EBS、RDS、DynamoDB)
- 転送中のデータには SSL/TLS を使用します
- シークレットは AWS Secrets Manager または Parameter Store に保存します
- 暗号化キーの管理には KMS を使用します
ネットワークセキュリティ
- ネットワークを分離するために VPC を使用します
- セキュリティグループと NACL を導入します
- VPC Flow Logs を有効にします
- ウェブアプリケーションを保護するために AWS WAF を使用します
- AWS Shield で DDoS 対策を導入します
コスト最適化
コンピューティング
- Auto Scaling を使用して、需要に合わせて容量を調整します
- 適切なインスタンスタイプとサイズを選択します
- 耐障害性が求められるワークロードには Spot Instances を使用します
- イベント駆動型のワークロードには Lambda を活用します
- 安定したワークロードには Savings Plans と Reserved Instances を使用します
ストレージ
- S3 ライフサイクルポリシーを導入します
- 適切なストレージクラスを使用します
- S3 Intelligent-Tiering を有効にします
- 使用していない EBS ボリュームとスナップショットを削除します
- 圧縮と重複排除を使用します
データベース
- データベースインスタンスのサイズを適正化します
- 読み取りトラフィックを分散するためにリードレプリカを使用します
- DynamoDB の自動スケーリングを有効にします
- 変動するワークロードには Aurora Serverless を使用します
- 古いデータを、より低コストのストレージにアーカイブします
パフォーマンス
アプリケーション設計
- キャッシュを導入します(ElastiCache、CloudFront)
- コンテンツ配信ネットワーク(CloudFront)を使用します
- データベースのクエリとインデックスを最適化します
- コネクションプーリングを導入します
- 非同期処理/並列処理を使用します
モニタリングと最適化
- CloudWatch でメトリクスとアラームを使用します
- 分散トレーシングに X-Ray を導入します
- パフォーマンス予算を設定します
- 定期的にパフォーマンステストを実施します
- AWS Compute Optimizer の推奨事項を活用します
信頼性
高可用性
- 複数のアベイラビリティーゾーンにデプロイします
- 自動復旧には Auto Scaling を使用します
- ヘルスチェックと自動フェイルオーバーを導入します
- DNS ベースのフェイルオーバーには Route 53 を使用します
- 段階的な縮退運転が可能な設計にします
災害復旧
- バックアップを自動化します
- 復旧手順を定期的にテストします
- 重要なデータにはマルチリージョンレプリケーションを使用します
- 目標復旧時間(RTO)と目標復旧時点(RPO)を文書化します
- カオスエンジニアリングのプラクティスを導入します
エラー処理
- 指数バックオフを用いた再試行ロジックを導入します
- 失敗したメッセージにはデッドレターキューを使用します
- エラーに関する CloudWatch アラームを設定します
- サーキットブレーカーを導入します
- エラーを包括的に記録します
オペレーショナルエクセレンス
Infrastructure as Code
- すべてのインフラストラクチャコードをバージョン管理します
- リソースのプロビジョニングには CloudFormation または CDK を使用します
- インフラストラクチャの変更に CI/CD を導入します
- 複数アカウント/リージョンへのデプロイにはスタックセットを使用します
- デプロイ前にテンプレートを検証します
モニタリングとログ記録
- CloudWatch Logs でログを一元管理します
- カスタムメトリクスとダッシュボードを設定します
- ログの集約と分析を導入します
- API の監査には CloudTrail を使用します
- 重要なメトリクスに関するアラームを設定します
自動化
- CodePipeline でデプロイを自動化します
- パッチ管理には Systems Manager を使用します
- 自動スケーリングポリシーを導入します
- 運用タスクには Lambda を使用します
- バックアップと復旧の手順を自動化します
スキルのバージョン: 1.0.0 最終更新日: October 2025 スキルカテゴリ: Cloud Infrastructure, Serverless, Database, DevOps 対応環境: AWS SDK v3, CloudFormation, AWS CLI, Terraform