mcpField
A
aws-cloud-services

aws-cloud-services

github.com/manutej云与 DevOps62450 次安装40 周前更新
代码仓库

关于 aws-cloud-services

aws-cloud-services 是面向开发者和架构师的 AWS 云基础设施学习技能,涵盖常用服务、安全、部署与架构实践。

主要功能

  1. 01S3 对象存储操作
  2. 02Lambda 事件驱动函数
  3. 03DynamoDB 与 RDS 数据库指南
  4. 04IAM 访问控制与凭证管理
  5. 05使用 CloudFormation 自动化基础设施
  6. 06架构与成本优化建议

适用场景

  1. 01设计基于 Lambda 的无服务器应用
  2. 02管理 S3 文件上传与下载
  3. 03设置最小权限 IAM 策略
  4. 04用 CloudFormation 自动部署基础设施

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/manutej/luxor-claude-marketplace --skill aws-cloud-services

安装后在 Claude Code 中输入/aws-cloud-services确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

.summary.txt
EXAMPLES.md
README.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 会按以下顺序查找凭证:

  1. 环境变量:AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY
  2. 共享凭证文件:~/.aws/credentials
  3. 共享配置文件:~/.aws/config
  4. IAM 角色(EC2/ECS/Lambda):实例元数据服务
  5. 进程凭证:来自自定义可执行文件
最佳实践
  • 切勿在源代码中硬编码凭证
  • 对 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

评论

支持 Markdown