现在云服务已经十分普及,这里分享亚马逊的一些实战经验
1. 新增IAM用户
为了方便管理,可以创建iam账号(类似于子账户)的来分不同用户管理AWS
步骤 1:使用根账户登录 AWS 管理控制台
- 打开 AWS 管理控制台:aws.amazon.com/
- 点击 “Sign In to the Console”(登录控制台)
- 使用你注册时的 邮箱地址 和 密码 登录(这就是根账户登录)
注意:如果之前选择了 “使用 IAM 用户登录” 方式,可能会进入 IAM 登录页面。如果是首次登录,一般是通过根账户邮箱登录。
步骤 2:进入 IAM 控制台
-
登录后,在 AWS 控制台搜索栏中输入 “IAM”,或者访问:
-
点击进入 IAM(Identity and Access Management)服务
步骤 3:创建 IAM 用户
-
在 IAM 控制台左侧菜单,点击 “用户(Users)”
-
点击顶部 “添加用户(Add users)” 按钮
-
设置用户信息:
-
用户名(User name):例如
dev-user或zhangsan -
访问类型(Select AWS access type):
- 勾选 “编程访问(Programmatic access)” → 用户将拥有 API、CLI、SDK 使用的 Access Key 和 Secret Key
- 勾选 “AWS 管理控制台访问(AWS Management Console access)” → 用户可以通过用户名密码登录控制台
- (根据你的需求勾选,通常两者都勾选)
-
-
点击 “下一步:权限(Next: Permissions)”
步骤 4:为用户分配权限
这里有几种常见方式:
方式 1:直接附加现有策略(推荐新手)
-
选择 “直接附加现有策略(Attach existing policies directly)”
-
在筛选框中输入你想要的权限策略,比如:
AdministratorAccess→ 拥有所有权限(慎用!仅用于管理员)AmazonS3ReadOnlyAccess→ 只读 S3AmazonEC2ReadOnlyAccess→ 只读 EC2- 或者你自定义的其他策略
-
勾选你希望赋予的策略,例如
AdministratorAccess(仅作测试,生产环境请细化权限!) -
点击 “下一步:标签(Next: Tags)”(可选)
方式 2:添加用户到用户组(推荐最佳实践)
- 你可以先创建一个用户组(如
Developers),然后给该组绑定策略,再将用户加入该组。 - 如果你还没创建组,可以稍后再做,或者在这一步先直接附加策略。
通过用户组统一设置权限好维护
(可选)步骤 4b:添加标签(Tags)
- 可以为用户添加标签(如部门、用途等),非必填,可跳过
步骤 5:审核并创建用户
- 检查你填写的用户名、访问类型、权限策略是否正确
- 点击 “创建用户(Create user)”
步骤 6:获取访问凭证
如果选择了 “编程访问”,你将看到:
- Access key ID
- Secret access key
⚠️ 重要:Secret access key 只会显示这一次!请务必保存(比如下载 CSV 文件或复制保存下来)。丢失后将无法再查看,只能重新创建。
如果选择了 “控制台访问”,你将得到:
-
一个 初始密码 或提示用户 首次登录时设置密码
-
用户可以通过以下地址登录 AWS 控制台:
https://你的账户ID.signin.aws.amazon.com/console或者使用你设置的账户别名(如果有配置):
https://你的账户别名.signin.aws.amazon.com/console
你可以点击 “登录链接” 直接发送给用户,或让用户使用:
https://console.aws.amazon.com/
然后输入你创建的 IAM 用户名和密码登录。
2. 新增EC2服务器
创建 EC2 实例
- 在 EC2 控制台首页,点击 “启动实例”(Launch Instance) 按钮
配置实例基本信息
① 为实例命名(可选但推荐)
- 在 “名称和标签”(Name and tags) 部分,给你的实例起个名字(比如
MyFirstEC2),便于管理
② 选择一个 Amazon Machine Image (AMI)
-
AMI 是预配置的操作系统镜像(如 Amazon Linux、Ubuntu、Windows 等)
-
推荐新手使用:
- Amazon Linux 2(免费层级友好)
- 或者 Ubuntu Server 22.04 LTS
-
在列表中找到并选择你想要的操作系统镜像,例如:
- Amazon Linux 2 AMI (HVM), SSD Volume Type(免费 tier 可用)
③ 选择实例类型(Instance Type)
-
实例类型决定了 CPU、内存、存储等配置
-
对于学习或测试用途,推荐选择:
- t2.micro(属于 AWS 免费套餐范围,每月有一定免费额度)
-
选中后,点击 “下一步:配置实例详细信息”
配置实例(可保持默认)
- 大多数设置可以保持 默认值
- 如果你有特殊需求(比如放到某个 VPC、指定子网、IAM 角色等),可以在这里配置
- 新手通常直接点击 “下一步:添加存储”
添加存储(默认一般足够)
- 默认情况下,会提供 8GB 的通用 SSD (gp2) 根卷
- 如果你需要更大的磁盘空间,可以在这里添加或修改
- 学习用途通常无需更改,点击 “下一步:添加标签”(可选)
添加标签(可选)
- 标签是键值对,用于帮助你更好地管理资源
- 例如:Key =
Name, Value =MyTestEC2 - 可跳过,直接点击 “下一步:配置安全组”
配置安全组(重要!)
-
安全组相当于虚拟防火墙,控制哪些端口可以被访问
-
你可以:
- 创建新的安全组,或者
- 选择一个已有的安全组
推荐配置(以 SSH 访问为例,适用于 Linux):
-
规则 1:允许 SSH(端口 22)
- 类型:SSH
- 协议:TCP
- 端口范围:22
- 来源:
My IP(推荐,只允许你当前的公网 IP 访问,更安全) 或者Anywhere(0.0.0.0/0,不推荐用于生产环境)
-
(可选)规则 2:允许 HTTP(端口 80)或 HTTPS(端口 443),如果你要运行网站
⚠️ 注意:将来源设为
0.0.0.0/0或Anywhere意味着任何人都能访问该端口,请谨慎使用!
点击 “下一步:选择密钥对”
选择密钥对(非常关键!)
密钥对用于通过 SSH 登录你的 Linux 实例(Windows 用户可能使用 RDP 和其它方式)。
你有三个选项:
-
选择现有密钥对(如果你之前已经创建过)
-
创建新的密钥对(推荐,第一次使用)
- 选择 “创建新密钥对”
- 输入密钥对名称(如:
my-key-pair) - 下载私钥文件(.pem 文件) —— 务必保存好,只会出现一次!
- 选中“我确认已下载密钥对文件”
-
选择已有密钥对但不下载(无法登录,不推荐)
📌 注意:
- 私钥文件(.pem)相当于密码,不能公开,不要上传到网络或共享
- 只能下载一次,丢失后将无法通过 SSH 登录该实例(除非有其它登录方式)
点击 “启动实例”
实例启动中
- 你会看到 “您的实例正在启动” 的提示
- 点击 “查看实例”,可以查看你刚刚创建的 EC2 实例状态
连接
链接支持4种方式,推荐使用ssh客户端,直接复制 示例:
ssh -i "myrsa.pem" ec2-user@xxxx.compute-1.amazonaws.com
注意 "myrsa.pem"要设置权限
chmod 400 "myrsa.pem"
3. 新增S3桶
步骤 1:登录 AWS 控制台并进入 S3
- 打开 AWS 管理控制台。
- 在服务搜索栏中输入 S3,然后点击 S3 服务进入。
步骤 2:创建 S3 存储桶
-
点击页面左上角的 “创建存储桶” 按钮。
-
输入 存储桶名称:
- 必须是 全局唯一 的(整个 AWS 中唯一,不是你账户内唯一)。
- 例如:
my-public-bucket-12345
-
选择你想要的 AWS 区域(建议选择离你近的或业务需要的区域)。
-
取消勾选(不推荐勾选):
-
“阻止所有公共访问”(Block all public access)—— 你需要取消勾选此选项才能设置公开权限!
- 默认情况下,AWS 会勾选并阻止所有公共访问,你需要 手动取消勾选全部四个选项,然后确认你了解风险。
- 系统会弹出警告,点击 “确认” 表示你了解将允许公开访问的风险。
-
-
设置 存储桶策略
your-bucket-name 替换为你的桶名字
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
]
}
-
其它设置可保持默认,比如:
- 不启用版本控制
- 不启用加密(或按需配置)
- 不启用日志记录等
-
点击 “创建存储桶” 完成创建。
测试
在S3里面选择自己的桶,然后点击上传测试
在浏览器直接访问
https://your-bucket-name.s3.amazonaws.com/your-file.jpg
4. 新增CloudFront
在 AWS 上配置 CDN(内容分发网络)通常使用的是 Amazon CloudFront
创建 CloudFront 分发(Distribution)
登录 AWS 管理控制台,打开 CloudFront 控制台
点击 “创建分配”(Create Distribution)
选择分发类型
- 一般选择 “Web”(适用于网站、HTTP/HTTPS 内容)。
- 如果你要加速实时流媒体,可以选择 RTMP(不过现在较少用)。
配置 “源”(Origin)
-
Origin Domain Name:选择你的来源,比如:
- 如果是 S3:从下拉列表中选择你的 S3 存储桶(注意:不是存储桶的网站终端节点,而是 S3 本身的源,形如
your-bucket-name.s3.amazonaws.com)。 - 如果是自定义源(如 EC2、ELB):输入它的域名或 IP,比如
example.com或123.45.67.89。
- 如果是 S3:从下拉列表中选择你的 S3 存储桶(注意:不是存储桶的网站终端节点,而是 S3 本身的源,形如
-
Origin Path:一般留空,除非你的内容存放在存储桶或服务器的某个子目录下。
-
Origin Access Control (OAC) 或 Origin Access Identity (OAI)(推荐):
- 对于 S3,建议使用 OAC(新方式) 或 OAI(旧方式) 来限制只有 CloudFront 能访问 S3。
- 如果你开启 OAI/OAC,那么你 不能直接通过 S3 的公开 URL 访问文件,只能通过 CloudFront 访问。
配置默认缓存行为(Default Cache Behavior)
-
Viewer Protocol Policy:
- 如果你的源是 HTTPS,建议选 Redirect HTTP to HTTPS 或 HTTPS Only。
-
Allowed HTTP Methods:通常选 GET, HEAD, OPTIONS(如果是 API 或需要 POST,也可以选更多)。
-
缓存策略和 origin 请求策略(AWS 推荐使用托管策略,比如 “CachingOptimized”)。
-
Forward Headers / Cookies / Query Strings:根据需求配置,一般静态资源不需要转发查询字符串,可提升缓存命中率。
设置备用域名(可选)
- 在 “Alternate Domain Names (CNAMEs)” 中,你可以填上你自己的域名,比如
www.example.com。 - 如果你填了 CNAME,你后续需要为该域名配置一个有效的 SSL 证书,并在 CloudFront 中使用。
SSL 证书配置
- 如果你用了自定义域名(如
www.example.com),你可以在 “Custom SSL Certificate” 中选择一个由 ACM(AWS Certificate Manager) 颁发的证书(必须是在 us-east-1 区域,如果你使用 CloudFront 的默认域名则不需要)。 - 如果你暂时不用自定义域名,可以直接使用 CloudFront 默认的域名(如
dxxxxx.cloudfront.net),它自带 HTTPS 支持。
设置价格类别 / 边缘站点
- 你可以选择 CloudFront 将内容分发到哪些地区,一般保持默认(全球)即可。
其他设置(日志、标签等)
- 可选择开启 访问日志,记录谁访问了你的 CDN。
- 添加标签便于管理。
点击 “创建分发”
测试
直接地址栏访问
https://xxxx.cloudfront.net/index.html
边缘渲染函数
- CloudFront Functions
- Lambda@Edge
CloudFront Functions
docs.aws.amazon.com/zh_cn/Amazo…
cloudfront支持简单的请求修改 通过js可以在接受请求,和返回请求的做逻辑处理,如果需要更高级别的处理推荐使用 lambda
例子代码:docs.aws.amazon.com/zh_cn/Amazo…
Lambda@Edge
支持更高级的能力,接口查询,数据库连接等 docs.aws.amazon.com/zh_cn/Amazo…
5. 新增lambda
AWS Lambda 是 Amazon Web Services (AWS) 提供的一种 无服务器(Serverless)计算服务。即用户无需关心服务器等,直接编写服务。
创建一个新的 Lambda 函数
- 点击页面上的 “创建函数”(Create function) 按钮
4️⃣ 配置函数基本信息
在创建页面中,填写以下内容:
选择创建方式:
- 选择 “从头开始编写”(Author from scratch)
填写函数信息:
-
函数名称(Function name): 例如
MyFirstNodeJSLambda -
运行时(Runtime): 选择 Node.js 的版本,比如:
- 推荐:Node.js 18.x(或根据你的需求选择 16.x、20.x 等,注意 AWS 支持的版本可能更新)
-
架构:默认即可(x86_64 或 arm64/Graviton,后者更省成本)
-
执行角色(Execution role):
- 选择:“创建新角色与基本 Lambda 权限”(Create a new role with basic Lambda permissions)
- 这样 AWS 会自动为你的函数创建一个 IAM 角色,具备写入日志等基础权限
⚠️ 如果你后续要让 Lambda 访问其他 AWS 服务(如 S3、DynamoDB),需要给这个角色添加对应权限。
然后点击 “创建函数”(Create function)
修改函数
网页版
通过网页版,可以在线直接编辑,并且点击deploy进行实时发布
缺点:如图所示,经常会出现加载失败问题。建议使用上传方式
上传版
实际开发可能改动比较多,可以使用上传的方式
注意该方式 要注意构建时候的指令要与服务器的一致。如你是mac电脑打包,服务器是liunx就会报错。
调试
网页调试
直接url访问
可以通过直接访问url地址 来测试效果,日志可以通过下面的cloudwatch分析
6. 查看日志cloudwatch
通过cloudwatch的日志组可以查询所有方法请求的结果
7. 实战
1. Lambda@Edge + cloudFonnt 修改请求头
官方例子 指导如何通过触发器,在响应cloudFonnt的时候调用Lambda 实现请求头修改 docs.aws.amazon.com/zh_cn/Amazo…
2. Lambda + S3 触发器创建缩略图
官方例子,每次请求S3的时候,都会在另外一个存储桶生成对应的缩略图 docs.aws.amazon.com/zh_cn/lambd…
注意该程序,如果配置错误,很有可能出现同一个桶响应的图片又生成图片再响应图片的死循环。测试需要多注意
3. 模仿7牛实现url参数动态切割图片
const AWS = require('aws-sdk');
const sharp = require('sharp');
const s3 = new AWS.S3();
const TAG_NAME = 'CreateByLambda';
const TAG_VALUE = '1';
const LAMBDA_BODY_LIMIT = 1024 * 1024; // 1MB
exports.handler = async (event, context, callback) => {
const request = event.Records[0].cf.request;
const response = event.Records[0].cf.response;
const params = new URLSearchParams(request.querystring);
const width = params.get('width') ? parseInt(params.get('width'), 10) : null;
const height = params.get('height') ? parseInt(params.get('height'), 10) : null;
console.log('请求参数:', { width, height });
console.log('请求URI:', request.uri);
console.log('请求方法:', request.method);
console.log("Response Headers:");
for (const headerName in response.headers) {
const headerValues = response.headers[headerName];
console.log(`${headerName}: ${headerValues.map(h => h.value).join(', ')}`);
}
console.log("Request Headers:");
for (const headerName in request.headers) {
const headerValues = request.headers[headerName];
console.log(`${headerName}: ${headerValues.map(h => h.value).join(', ')}`);
}
if (!width && !height) {
console.log('无参数则直接回源')
return callback(null, response); // 无参数则直接回源
}
const hostHeader = request.headers.host[0].value;
const s3Bucket = hostHeader.split('.')[0];
const originalKey = decodeURIComponent(request.uri.substring(1));
try {
const sizePart = [width || '', height || ''].filter(Boolean).join('x');
const parts = originalKey.split('.');
const extension = parts.pop().toLowerCase();
const baseName = parts.join('.');
const newKey = `${baseName}_${sizePart}.${extension}`;
// 检查缓存
try {
await s3.headObject({ Bucket: s3Bucket, Key: newKey }).promise();
console.log(`命中缓存: ${newKey}`);
} catch (err) {
if (err.code !== 'NotFound' && err.code !== 'NoSuchKey') throw err;
const originalImage = await s3.getObject({ Bucket: s3Bucket, Key: originalKey }).promise();
let resizedImage = sharp(originalImage.Body);
if (width || height) {
resizedImage = resizedImage.resize(width || null, height || null, {
fit: 'inside',
withoutEnlargement: true,
});
}
if (['jpg', 'jpeg'].includes(extension)) resizedImage = resizedImage.jpeg({ quality: 80 });
else if (extension === 'webp') resizedImage = resizedImage.webp({ quality: 80 });
else if (extension === 'png') resizedImage = resizedImage.png();
const processedBuffer = await resizedImage.toBuffer();
// 保存到 S3
await s3.putObject({
Bucket: s3Bucket,
Key: newKey,
Body: processedBuffer,
ContentType: `image/${extension}`,
CacheControl: 'public, max-age=31536000',
Tagging: `${TAG_NAME}=${TAG_VALUE}`,
}).promise();
console.log(`新图生成并保存: ${newKey}`);
}
// 获取 S3 对象大小
const objMeta = await s3.headObject({ Bucket: s3Bucket, Key: newKey }).promise();
const size = objMeta.ContentLength;
console.log(`Get img: https://${hostHeader}/${newKey}`)
if (size >= LAMBDA_BODY_LIMIT) {
// 大于 1MB → 302 Redirect,使用 S3 域名,由于使用源响应,host默认就是桶域名
return {
status: '302',
statusDescription: 'Found',
headers: {
location: [{ key: 'Location', value: `https://${hostHeader}/${newKey}` }],
'cache-control': [{ key: 'Cache-Control', value: 'public, max-age=86400' }],
},
};
} else {
// 小于 1MB → 200 Base64,使用 CDN 域名
const imageObj = await s3.getObject({ Bucket: s3Bucket, Key: newKey }).promise();
return {
status: '200',
statusDescription: 'OK',
body: imageObj.Body.toString('base64'),
bodyEncoding: 'base64',
headers: {
'content-type': [{ key: 'Content-Type', value: `image/${extension}` }],
'cache-control': [{ key: 'Cache-Control', value: 'public, max-age=86400' }],
},
};
}
} catch (err) {
console.error('Error processing image:', err);
return {
status: '500',
statusDescription: 'Internal Server Error',
body: 'Failed to process image',
};
}
};
测试
https://your-cdn-domain.com/images/photo.jpg?width=300&height=200
这是一个运行在 AWS CloudFront + Lambda@Edge 环境下的 图片动态缩放与优化服务,主要功能包括:
-
根据 URL 参数动态调整图片尺寸(如 ?width=300&height=200)。
-
使用 Sharp 库进行高性能图片处理(缩放、格式转换、压缩)。
-
将处理后的图片缓存到 S3,并设置长期缓存头。
-
智能返回结果:
- 图片小(<1MB):直接以 Base64 内联返回(200)。
- 图片大(≥1MB):返回 302 重定向到 S3 上的图片。
-
避免重复处理:通过检查 S3 缓存实现。
-
带有监控与日志:打印请求、响应、错误等详细信息,便于调试。
8. 踩坑
有时候有些服务会提示“未知错误”无法正常使用
解决办法,清空cookie和缓存并且退出账号重新登录,或者直接换一个浏览器重新登录。