关于 aws-cloud-services
aws-cloud-services 是面向开发者和架构师的 AWS 云基础设施学习技能,涵盖常用服务、安全、部署与架构实践。
主要功能
- 01S3 对象存储操作
- 02Lambda 事件驱动函数
- 03DynamoDB 与 RDS 数据库指南
- 04IAM 访问控制与凭证管理
- 05使用 CloudFormation 自动化基础设施
- 06架构与成本优化建议
适用场景
- 01设计基于 Lambda 的无服务器应用
- 02管理 S3 文件上传与下载
- 03设置最小权限 IAM 策略
- 04用 CloudFormation 自动部署基础设施
安装
复制下面的命令,在终端中运行。
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 基础设施即代码,以及企业级云架构模式。
何时使用此技能
在以下情况下使用此技能:
- 在 AWS 基础设施上构建可扩展的云应用程序
- 使用 Lambda 和 API Gateway 实现无服务器架构
- 使用 S3 管理对象存储和文件上传
- 使用 DynamoDB 设计 NoSQL 数据库解决方案
- 部署 EC2 实例并管理计算资源
- 设置 RDS 数据库以存储关系型数据
- 实现 IAM 安全策略和访问控制
- 使用 CloudFormation 自动部署基础设施
- 设计多区域、高可用系统
- 优化云成本和性能
- 将本地部署的应用程序迁移到 AWS
- 实现事件驱动架构
- 构建数据管道和分析解决方案
- 安全地管理密钥和凭证
- 使用 AWS 服务设置 CI/CD 管道
核心概念
AWS 基础知识
AWS 是 Amazon 提供的综合云计算平台,涵盖计算、存储、数据库、网络、安全等领域的 200 多项服务。
关键概念
区域和可用区
- 区域:包含多个数据中心的地理区域(例如,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 v3 版 AWS SDK
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 核心组件
用户
- 具有长期凭证的个人身份
- 用于编程访问的访问密钥
- 用于控制台访问的密码
- 支持 MFA(多重身份验证)
组
- 用户集合
- 附加策略以集中管理权限
- 用户可以属于多个组
角色
- 由用户、服务或应用程序承担的临时凭证
- 跨账户访问
- 服务间通信
- 与外部身份提供商联合
策略
- 定义权限的 JSON 文档
- 基于身份的策略(附加到用户/组/角色)
- 基于资源的策略(附加到 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"
}
}
}
]
}
策略元素
- 效果:允许或拒绝
- 操作:服务和操作(例如,s3:GetObject)
- 资源:受影响资源的 ARN
- 条件:可选限制(IP、时间、MFA 等)
- 主体:策略适用的对象(适用于基于资源的策略)
最小权限原则
始终只授予所需的最低权限:
- 从不授予任何权限开始
- 根据需要逐步添加权限
- 对常见模式使用托管策略
- 针对特定用例创建自定义策略
- 定期审计并移除未使用的权限
凭证管理
凭证链
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(简单存储服务)
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
生成临时 URL,以便在无需 AWS 凭证的情况下安全地上传和下载文件。
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 是一项完全托管的 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 模式
单表设计
使用一张表和重载键来构建复杂的数据模型。
// 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 资源的基础设施即代码(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 最佳实践
- 为根账户和特权账户启用 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 保护 Web 应用
- 使用 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 实现自动恢复
- 实施运行状况检查和自动故障转移
- 使用 Route 53 实现基于 DNS 的故障转移
- 设计优雅降级机制
灾难恢复
- 实施自动备份
- 定期测试恢复流程
- 对关键数据使用多区域复制
- 记录恢复时间目标(RTO)和恢复点目标(RPO)
- 实施混沌工程实践
错误处理
- 使用指数退避机制实现重试逻辑
- 使用死信队列处理失败的消息
- 为错误设置 CloudWatch 警报
- 实施熔断器
- 全面记录错误日志
卓越运营
基础设施即代码
- 对所有基础设施代码进行版本控制
- 使用 CloudFormation 或 CDK 配置资源
- 为基础设施变更实施 CI/CD
- 使用 StackSets 进行多账户/多区域部署
- 部署前验证模板
监控与日志记录
- 使用 CloudWatch Logs 集中管理日志
- 设置自定义指标和仪表板
- 实施日志聚合与分析
- 使用 CloudTrail 审计 API
- 为关键指标设置警报
自动化
- 使用 CodePipeline 自动化部署
- 使用 Systems Manager 管理补丁
- 实施自动扩缩策略
- 使用 Lambda 执行运维任务
- 自动化备份和恢复流程
技能版本:1.0.0 最后更新:2025 年 10 月 技能类别:云基础设施、无服务器、数据库、DevOps 兼容:AWS SDK v3、CloudFormation、AWS CLI、Terraform