客户那边最初的表达往往很简单:“帮我们在亚马逊云上开几台EC2,把网站跑起来。”等你真正坐下来,业务架构、实例选型、网络规划、权限配置、备份成本,每一项都要当场拿主意。AWS EC2在我的日常工作中几乎天天打交道,从纯技术交付到帮客户优化账单,它都是绕不开的主战场。这篇文章不是我对着文档念概念,而是把我实际经手的一个典型B2B网站项目完整复盘:从客户一句“够用就行”开始,到EC2选型、CLI部署、根卷扩容、CPU积分排障,再到和ECS/ECR权限问题衔接,把整条链路里真正容易翻车的细节、命令和判断逻辑摊开讲。不管你是刚接触AWS的渠道商新人,还是已经在做代维交付的伙伴,应该都能从这里找到能直接抄作业的部分。
1. “先跑起来”的客户需求背后,到底要拆出哪些硬指标
1.1 需求分析从“几句话”变成“一张表”
大多数客户老板不会用云计算的术语描述需求。我接手的这个项目是一家做B2B独立站的客户,日活不大,几百到一千多,真正流量高峰集中在工作日上午和下午两个时段,促销期偶尔会冲高到平时的七八倍。对方的原话是“配置不用太高,能用就行”。
这种话绝对不能直接当成技术方案依据。“能用就行”在没有业务画像的前提下,意味着后面可能要花好几倍的时间在救火上。我会在项目启动时先和客户确认几个硬指标:并发访问量大概多少、业务是无状态网页还是带数据库写操作、有没有定时任务或批处理、数据量增长速度、是否需要保证高可用、预算有没有明确红线。这几个问题问完,架构轮廓才开始清晰。
当时的估算逻辑很简单:独立站核心应用以PHP/Java类型的Web服务为主,单请求平均占用约0.5个vCPU、内存占用约300MB,高峰期同时在线并发300人左右,算上冗余系数,核心计算节点在2 vCPU / 4 GiB内存的量级已经能覆盖日常需求。数据库层面考虑到客户不想再单独维护服务器,直接放托管数据库方案,避免把时间和精力耗在自建数据库的备份和主从上。
1.2 先画网络图再开实例,顺序错了后面很被动
很多刚接触AWS的人,习惯一上来就点“创建实例”,网络、子网、安全组全用默认值。自己测试没问题,但一旦到了交付客户环境,默认VPC往往会造成两个麻烦:一是和客户的专线或办公网段冲突,二是安全组规则混乱,后面排查出问题时很难解释清楚架构。
我在这类项目里一定会先确定VPC和子网规划。一般业务实例放在私有子网,只有需要对外提供服务的入口才放到公网子网,或者干脆用一个负载均衡器对外统一接收流量,后端EC2全部放到私网里。也就是说,EC2的“公网属性”不是必须的,一个连公网IP都没有的内部服务反而更安全,运维可以通过跳板或SSM访问。考虑到当时客户没有复杂网络需求,我采用了一个简单但清晰的模型:用一个VPC,划分两个子网,一个放Web服务,一个放内部中间件;通过安全组做实例间访问控制,而不是把数据库和中间件的端口暴露到公网。
这一步看似和“实战案例”关系不大,其实是EC2架构的地基。渠道商做交付,最怕的就是给客户留下一套谁也说不清楚的网络,所以我在每次部署之初都会强迫自己先在文档里画清楚VPC、子网、安全组、路由表大概长什么样,再动手创建任何资源。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 实例选型不是挑“最大套餐”,付费模式和匹配度才是关键
2.1 按需付费、预留/Savings Plans、Spot三选一
实例规格重要,付费模式同样重要,很多渠道商习惯先把机器开起来然后月底看账单,这种思路会让客户很快对“上云省钱”失去信心。同样的机型,选错付费模式可能在一年内多付30%以上。
按需计费适合不可预测、临时性的负载,测试环境、短期项目很合适,缺点是单价最高。Savings Plans或预留实例适合那些明确要长期运行、24小时在线的业务,一般能省20%-30%。Spot实例价格优势更明显,但核心前提是实例随时可能被回收,只适合无状态、可中断的任务,比如批量处理、持续集成构建节点。
当时客户的核心业务是面向客户的网站,绝不能随便中断,所以主力实例我直接放弃了Spot选项,推荐用按需实例起步,等稳定运行一个月后,通过账单里的使用率数据判断是否需要买Savings Plans。至于构建和打包任务,因为可以中断,我特意开了一台Spot实例来承担,成本差距立刻就体现出来了。
2.2 不同业务负载对应的EC2实例族群
AWS实例类型非常多,如果只看vCPU和内存,很容易被绕晕。我的判断方法很简单:先看负载类型,再选对应族群。
- 通用型M系:CPU和内存比例均衡,适合大多数Web应用、中小数据库、企业应用。项目初期没有明确瓶颈时,这是个不容易出错的起点。
- 突发性能T系:适合CPU平时使用率不高、偶尔需要冲一冲的场景。T系有CPU积分机制,后面我会专门讲,它省钱的代价是有性能边界。
- 计算优化C系:适合视频转码、批处理、科学计算等CPU密集任务,单vCPU性价比更好。
- 内存优化R系、X系:适合数据库、缓存、内存计算场景。如果应用吞内存特别厉害,就不要硬用M系堆规格。
- 存储优化I系:适合本地磁盘高IO场景,但本地盘不持久,使用时要注意数据安全。
这个项目的选型推导大约是:Web服务平时负载不高但会有促销突发,所以先在t3.medium级别跑起来,用突发积分应对短期峰值;但客户后台有一个每天跑报表的定时任务,CPU消耗稳定且持续,这种场景不适合放T系,我给了它一台C系的实例做专用任务节点,避免报表任务把Web实例的CPU积分全部吃掉。
2.3 区域选择、AMI选择和配置规划的经验
不少新手会把区域看得很随意,实际上不同区域的实例价格、可用区数量是有差异的。对国内客户而言,如果目标用户就在当地,选择就近区域能明显降低延迟;如果只是测试,就挑一个实例类型最全的区域。AMI方面,我通常优先选择Amazon Linux 2023或Ubuntu LTS版本,理由是更新周期稳定、AWS集成度高。实际创建时要看当前区域里有哪些AMI可用,不要在示例命令里看到ID就直接复制到生产环境,那是踩坑的开始。
系统盘容量也是经常被忽略的点。AWS默认根卷容量往往不大,客户数据写到一定程度就会满。我在这类项目中习惯把根卷规划为30GB到50GB,使用gp3类型。gp3的基准性能已经足够大多数业务使用,关键是它的IOPS和吞吐量可以独立调整,不必为了性能去盲目扩大容量。相比gp2,gp3费用更低,这是AWS里少数“性能差不多但更便宜”的选择。
3. 部署阶段真正省时间的办法:用AWS CLI批量建资源
3.1 控制台点几十次,不如十几行命令
现在不少AWS新用户把所有操作都放在控制台里完成。如果只是创建一台临时服务器,控制台确实方便。但到渠道商交付场景,可能要一次性创建好几台实例,还要配套安全组、标签、EIP、卷,每个资源都在图形界面里找半天,效率很低,也容易漏配置。我在这类项目中更习惯用AWS CLI。
假设已经提前创建好了VPC和子网,并拿到对应的子网ID,命令链大致是:
bash复制# 创建安全组
aws ec2 create-security-group \
--group-name web-sg \
--description "web server security group" \
--vpc-id vpc-0a1b2c3d4e5f67890
# 添加入方向规则:只放行22端口给办公网段,80给所有人
aws ec2 authorize-security-group-ingress \
--group-id sg-0abc123def4567890 \
--protocol tcp --port 22 \
--cidr 203.0.113.0/24
aws ec2 authorize-security-group-ingress \
--group-id sg-0abc123def4567890 \
--protocol tcp --port 80 \
--cidr 0.0.0.0/0
# 创建实例并指定数据盘配置
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.medium \
--key-name my-key-pair \
--security-group-ids sg-0abc123def4567890 \
--subnet-id subnet-0abc123def4567890 \
--block-device-mappings '[{"DeviceName":"/dev/xvda","VolumeSize":30,"VolumeType":"gp3"}]' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=web-01}]'
命令里的AMI ID只是示意。实际操作时,先用aws ec2 describe-images或直接去控制台确认当前区域可用的Amazon Linux 2023镜像ID,再填进来。
CLI的优势不只是快,还在于整个过程可记录下来,放到交付文档里,下次遇到同类型需求把参数改一改就能复用。我在给客户维护环境时,所有资源的创建几乎都有对应的CLI脚本,后期审计和重建环境都很方便。
3.2 安全组配置中最容易忽略的“方向感”
安全组是EC2第一道防线,同时也是初学者最容易犯错的地方。AWS安全组有状态,意思是允许了入站请求,出站响应会自动放行,不需要为响应流量单独再配规则;但很多人因此忽略了出站规则本身,把一个需要访问外网更新软件包的实例,出站方向配成了全拒绝,结果业务跑起来各种超时。
我一般这样把握:面向公网的Web层,入站只开80/443,SSH端口只对办公网段开放,不要对全世界开放22;出站按需放行。不同安全组之间允许互相引用,比如后端应用安全组可以只允许来自Web安全组的流量访问特定端口,这样比用IP白名单更清晰,实例IP变了也不会断。
另外一个容易忽略的点:一个实例可以挂多个安全组,规则是“或”的关系。如果有一次我们排查一个端口不通的问题,看了半天以为是系统防火墙,最后发现是实例绑定的两个安全组里,另一个组也有规则在起作用。维护复杂架构时,尽量一个实例绑定一两个安全组,规则写得少而明确,远比堆一堆规则要好。
3.3 EIP的分配和它的隐藏成本
给EC2分配公网IP,很多人第一时间想到“弹性IP”,也就是EIP。但EIP有两点要注意:一是默认每个区域配额很有限,用满之后想再分配就得提工单;二是EIP如果分配了却没有绑定到运行中的实例,会按小时收取闲置费用。很多渠道商帮客户创建了EIP,客户后来不使用那个实例了,EIP却一直空着,月底账单里就出现了一笔不大不小但完全没必要花的钱。
遇到不一定要固定公网IP的场景,我通常建议用负载均衡器对外提供入口,后端实例只管内网地址,这样既不需要EIP,又能顺便拿到健康检查和流量分发能力。真正需要EIP的地方,是那些没有负载均衡、又必须通过固定IP被外部访问的少量场景。我们在这个项目里只给运维跳板机配了一个EIP,并且写清楚绑定了哪台实例,后面检查账单就很省心。
4. 运行期“半夜变慢”的真相:CPU积分耗尽
4.1 客户反馈的典型现象
项目上线大约三周后,客户在晚上反馈网站变卡了。当时我们看了网络、磁盘、内存这些指标,都还算正常,CPU使用率却一直顶在100%。奇怪的是,这台实例是t3.medium,白天高峰期都能扛住,晚上流量不大反而不行了。我登录实例后用top看进程,也没发现异常进程,负载就是莫名其妙地下不来。
这时候真正的问题浮出水面:t系列是突发性能实例,CPU使用率100%不代表这台机器真的需要那么多算力,很可能是因为CPU积分已经耗尽,实例被强制限制在基准性能之下。t3.medium的基准CPU大约只有20%左右,持续超过这个基准就会消耗积分,积分耗尽后如果不启用无限制模式,CPU会被压到非常低。
4.2 CPU积分机制:1个积分到底能干什么
AWS官方对CPU积分的定义是:一个CPU积分等于一个vCPU以100%利用率运行一分钟。T系列实例会按一个固定速率持续获得积分,当实例空闲时积分攒下来,当实例以高于基准的水平运行时积分被消耗。如果实例长时间跑在基准之上,积分池就会见底。
这台t3.medium在业务上线初期,搭建和导数据阶段长时间高负载,已经把攒下的积分消耗殆尽。进入平稳运行期后晚上虽然流量不大,但后台可能有日志轮转、安全扫描、数据库维护之类的固定任务,加上T系CPU被限制后任务完成速度变慢,反而拖长了高CPU占用的时间,形成恶性循环。
我在CloudWatch里调出CPUCreditBalance这个指标后,曲线非常直观:白天下跌、夜里略有回积,但总体趋势是往下走的,最终接近零。
4.3 解决办法:升规格还是换实例族群
处理办法不是简单粗暴地把实例改成更大一档的T系,那样只是暂时扩大积分池,本质上还是在“借未来”。我当时的判断是:这个客户的核心业务需要持续、稳定的计算能力,更适合切到M系通用型实例,而不是继续依赖T系的突发机制。
切到M系之后,我顺手做了几件收尾的动作:第一,给监控加了告警,当CPU使用率持续10分钟超过80%时通知到人;第二,排查后台有哪些定时任务可以挪到非业务高峰期执行,减少不必要的CPU竞争;第三,把日志轮转和系统更新调整到凌晨低峰期,避免和业务请求抢资源。这个案例对我来说最大的价值是更正了一个认知:T系便宜,但它默认不是一个可以24小时持续满载的环境,适合T系的应该是“大部分时间都很闲,偶尔需要爆发”的场景。
5. 当问题蔓延到ECS和ECR:权限排查的经典链路
5.1 执行角色和任务角色到底有什么区别
EC2跑着跑着,客户提了一个新需求:想逐步把一部分服务容器化,放到ECS上。结果第一次部署就卡住了,任务一直起不来,事件里写着拉取镜像失败。当时客户问了一个很有代表性的问题:“ECS怎么看ECR的权限是不是有拉镜像的功能?”
这个问题的本质是AWS的权限模型。要理解为什么拉不到镜像,需要先分清ECS任务定义里的两个角色。executionRoleArn叫执行角色,是ECS代理去拉取容器镜像、写入CloudWatch日志时使用的身份;taskRoleArn叫任务角色,是容器里的应用在运行时访问其他AWS服务,比如读S3、发SQS消息时使用的身份。很多人的第一反应是去改任务角色权限,但拉镜像这个动作根本不走任务角色,而是走执行角色,改错了地方当然不生效。
5.2 通过CLI一步步确认问题出在哪
我排查这类问题时有一套固定顺序,先用AWS CLI把链路里的每个节点都确认一遍,避免只看现象猜原因。
查看任务定义里到底配置了哪些角色,命令是:
bash复制aws ecs describe-task-definition \
--task-definition my-app:1 \
--query "taskDefinition.{executionRoleArn:executionRoleArn,taskRoleArn:taskRoleArn}"
如果执行角色为空,或者指向一个不存在的角色,那拉取镜像失败就非常正常。要确认这个角色是否真的具备拉ECR镜像权限,可以用IAM策略模拟命令:
bash复制aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:role/ecsTaskExecutionRole \
--action-names ecr:BatchGetImage \
--resource-arns arn:aws:ecr:us-east-1:123456789012:repository/my-app
如果输出结果是allowed,角色权限没问题;如果是explicitDeny或implicitDeny,再去看角色上挂的策略内容。
另外还有一个很容易踩的坑:ECS实例所在的子网无法访问ECR服务的终端节点。ECR仓库通常是私有的,拉镜像时要先向ECR服务获取认证令牌,这一步需要网络能访问ECR的公共端点或VPC终端节点。如果子网没有NAT网关,也没有配置VPC端点,即使权限全对,也一样会超时。命令行里可以用一个简单操作验证网络连通性,比如用带AWS CLI的容器手动执行一次登录:
bash复制aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin \
123456789012.dkr.ecr.us-east-1.amazonaws.com
这条命令能顺利执行,说明网络和认证本身问题不大;如果卡在超时,基本可以判断是网络路径的问题,而不是IAM权限。
5.3 可以直接套用的最小权限策略
给客户最小权限始终是对的。拉取镜像最核心的权限只需要三四个action,不需要额外给一大堆ECR管理权限。下面这份策略可以挂在ECS执行角色上:
json复制{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability"
],
"Resource": "arn:aws:ecr:us-east-1:123456789012:repository/my-app"
},
{
"Effect": "Allow",
"Action": "ecr:GetAuthorizationToken",
"Resource": "*"
}
]
}
实际运维中很多人会在Resource里写"*",虽然能跑,但不推荐。比这更隐蔽的是把这条策略挂到了任务角色上而不是执行角色上,或者策略挂了但角色没有被ECS任务定义引用。每一层都要检查,不能只看其中一个环节。
另外,AWS官方其实提供了托管策略AmazonECSTaskExecutionRolePolicy,里面已经包含了拉取ECR镜像和写CloudWatch日志的权限。如果不是特别严格的合规场景,直接把这个托管策略挂给执行角色是最省事的做法。自己写最小权限策略的适合场景,是你需要明确限制只能拉某一个仓库镜像,不想让执行角色拥有全部仓库的拉取权。
6. 渠道商交付的收尾工作,决定这个项目是“一次性买卖”还是长期服务
6.1 交给客户的一页交付清单里有什么
很多项目做到“系统能访问”就算交付了,但后面客户遇到问题还是会来找你。既然要长期服务,不如在交付那天就把必要的资产信息整理清楚,既是对客户负责,也方便自己后续维护。我一般会把EC2相关资源整理成一张清单,内容包括实例ID、实例类型、所在可用区、绑定的安全组、IAM角色、EIP地址、系统盘和数据盘大小及类型、最近的AMI备份点、以及关联的标签。
标签是我特别强调的事情。每台EC2都应该打上清晰的标签,至少包含Name、Environment、CostCenter这类字段。小项目感觉不到标签的价值,等客户业务变大,开了几十台实例之后,没有标签的账单几乎无法分析——Cost Explorer和预算全部依赖标签来归类,打标签这件事在做资源创建时就该顺手做好,而不是事后补。
6.2 长期成本控制的三个固定动作
渠道商和客户的信任,往往不是建立在架构多完美上,而是建立在月底账单是否可控上。我做EC2项目的长期成本控制通常会做三件事。
第一件事是基于真实的资源使用率按节奏做实例规格调整。客户业务增长后,很多人第一反应就是升配,但有时只是某一段时间的假性高峰,跑一个月数据再决定才更稳。反过来,很多实例配置明显过高,CPU长期低于5%却仍在按最高规格付费,这时候降配能省下不小的成本。
第二件事是善用托管服务和存储生命周期管理。不是所有数据都需要放在EC2的高速磁盘上,日志、备份可以放进对象存储并设置生命周期规则,几个月前的数据自动转冷存储,账单会好看很多。
第三件事是设置预算告警。我在每一套交付环境里都会创建一个预算,当月度预计费用超过指定阈值时,自动发通知。这样月度账单还没出来,异常消耗就可能被预先发现。曾经有一台被遗忘的实例连续跑了两周,就是因为预算告警提前发现了,避免了更大额度的浪费。
6.3 从这台EC2延伸出去的服务空间
EC2本身只是云服务的一个起点,渠道商的价值是把客户真正的业务需求和具体云产品串联起来。这个B2B客户后来逐步把容器化服务放到ECS上,我们把EC2、ECS、ECR的权限模型梳理清楚之后,整套环境的自动扩缩容也随之落地。
EC2的很多知识是相通的,比如在T系算力受限这个坑里学到的经验,放到ECS的容量提供方选择上也成立;在安全组和IAM上积累的习惯,放到其他服务上同样适用。做渠道商这件事,我自己的体会是:每交付一个项目,都要沉淀出一套自己的检查清单,而不是每一次都从零开始靠记忆和运气。把常见问题变成固定排查流程,把可复用脚本整理成自己的工具箱,后面的项目才会越做越轻松。
