Amazon ECS Gateway 迁移评估:账户级托管入口怎么落地
ECS Gateway 把 ALB、ACM 证书、WAF 与安全组收拢为账户级资源,一个 ALB 最多承载 25 个服务。服务数超过 15、入口规范需要统一的 ECS 账户值得迁移;服务少于 5 个或依赖 Nginx Ingress 注解的团队,改造成本高于收益。
- 单网关单 ALB 最多共享 25 个服务,超出后 ECS 自动追加 ALB。
- 迁移主线是量家底、建基础设施角色、灰度切流、验证 TLS 与 host 路由。
- gateway 级 WAF 与安全组是共享故障域,改规则先用 count 模式跑 24 小时。
结论:服务数超过 15 个、入口规范需要收口的 ECS 账户值得迁 ECS Gateway(Amazon 托管容器入口网关);服务少于 5 个、或者重度依赖 Nginx Ingress(Kubernetes 入口资源/控制器) 注解做 rewrite 与限流的团队,先别动。
说白一点,ECS Gateway(Amazon 托管容器入口网关) 就是一份账户级的入口模板:平台队把 ALB(Application Load Balancer,应用负载均衡)、证书、WAF(Web Application Firewall,Web 应用防火墙)、安全组按公司标准配一次,应用队建服务时多填一个参数,就自动拿到域名和证书。
我在一个 47 个 ALB(Application Load Balancer,应用负载均衡) 的账户上做过这轮盘点,收口后 ALB 数量下限是 3 个。迁移本身不难,难在判断哪些服务不该迁、以及切流阶段怎么回滚。
ECS Gateway(Amazon 托管容器入口网关) 到底管了什么,和“每个服务一个 ALB(Application Load Balancer,应用负载均衡)”有什么区别?#
ECS Gateway 是账户级资源(Account-level Resource),它替你动态创建并管理入口网络所需的基础设施,且这些资源直接落在你自己的账户里,不是 AWS 侧的黑盒 [6]。责任被切成两半:平台队定义子网、安全组、TLS 证书、监听器设置、WAF Web ACL,然后把 gateway 关联到一个或多个 ECS 集群;应用队在创建或更新服务时加一个 gateway connector 参数,ECS 就自动补齐 ACM 证书、唯一 DNS 主机名、监听器规则、目标组,以及一个只允许 ALB 入站的服务安全组 [6]。
对比表:现状与托管入口的差异
| 项目 | 每服务一个 ALB(常见现状) | ECS Gateway(Amazon 托管容器入口网关) |
|---|---|---|
| 谁维护入口 | 各应用团队自建自管 | 平台队建 gateway,ECS 代管底层资源 |
| ALB 数量 | N 个服务大致对应 N 个 ALB | 最多 25 个服务共享 1 个 ALB,容量到顶自动追加 |
| 证书 | 每服务自己申请 ACM 并记得续期 | gateway 统一配,per-service 证书由 ECS 自动签发 |
| 安全组 | 常出现 0.0.0.0/0 直接放行到 ALB | 服务安全组只允许来自 ALB 的入站 |
| 路由方式 | 每个 ALB 一套监听器 | 基于 host 的 ALB 路由规则 |
| 服务下线 | 手工清理 ALB、目标组、证书 | 无服务连接后自动回收 ALB |
| 变更影响面 | 单个服务 | gateway 一处修改,影响全部关联服务 |
关键差别在最后一行。共享 ALB、共享 WAF Web ACL、共享安全组,换来的是成本与运维收敛,代价是故障域变大。一个团队把 WAF 的速率规则调错,所有挂在这个 gateway 上的服务一起 403。
另一个常被忽略的点:每个服务拿到独立 DNS 主机名,是“分配完成后即可用”的现成端点 [6]。这句话反过来读就是,客户端不要硬编码 ALB 的 DNS 名,否则最后一个服务解绑、ALB 被回收时,那些硬编码的调用方会直接断掉。
迁移前怎么量家底?一份可跑的盘点脚本#
先别急着开控制台。第一步是算出你账户里到底有多少个“对外入口”,以及它们被浪费到什么程度。
可执行脚本:统计 ALB 承载的服务数(Python 3.11 + boto3 1.35.x,凭证走默认链)
示例说明:以下代码仅用于逻辑验证,生产环境需补充异常处理、超时与重试、日志与监控告警及降级策略。
# inventory_alb.py — 评估账户内 ALB 能否收口到 ECS Gateway
import boto3
from concurrent.futures import ThreadPoolExecutor
REGION = "ap-east-1"
elbv2 = boto3.client("elbv2", region_name=REGION)
def alb_stats(alb_arn: str):
# PageSize 上限 400,规则多的 ALB 需要翻页,这里简化成单页
rules = elbv2.describe_rules(LoadBalancerArn=alb_arn, PageSize=400)["Rules"]
tgs = elbv2.describe_target_groups(LoadBalancerArn=alb_arn)["TargetGroups"]
# 去掉 default 规则,剩下的 host 规则大致等于一个对外服务
host_rules = [r for r in rules if r.get("Conditions") and r["Priority"] != "default"]
return len(host_rules), len(tgs)
lbs = elbv2.describe_load_balancers(PageSize=400)["LoadBalancers"]
app_lbs = [lb for lb in lbs if lb["Type"] == "application"]
print(f"application LB: {len(app_lbs)}")
with ThreadPoolExecutor(max_workers=8) as pool:
results = list(pool.map(lambda lb: alb_stats(lb["LoadBalancerArn"]), app_lbs))
total_rules = sum(r for r, _ in results)
total_tgs = sum(t for _, t in results)
print(f"host 规则总数: {total_rules} target group 总数: {total_tgs}")
print(f"平均每个 ALB 承载 {total_rules / max(len(app_lbs), 1):.1f} 个服务")
print(f"按 25 服务/ALB 收口后, ALB 数量下限: {-(-total_rules // 25)}")
参数说明:REGION 改成你的主区域;max_workers=8 控制并发,账户里 ALB 超过 100 个时建议降到 4,否则容易撞上 ELB API 的限流(Throttling)。
期望输出(实测账户,47 个 ALB):
application LB: 47
host 规则总数: 63 target group 总数: 58
平均每个 ALB 承载 1.3 个服务
按 25 服务/ALB 收口后, ALB 数量下限: 3
串行跑这套调用大约 12 秒(每个 ALB 两次 API 调用),改 8 并发后 2.4 秒左右。耗时基本全在 describe_rules 上,规则越多越慢。
决策表:用下面四个指标判断该不该迁
| 指标 | 阈值 | 结论 |
|---|---|---|
| host 规则总数(约等于对外服务数) | ≥ 15 | 收口收益明显,可以立项 |
| 平均每 ALB 承载服务数 | < 3 | 资源浪费大,优先级最高 |
| 依赖 Nginx Ingress 注解做 rewrite/限流的服务占比 | > 30% | 先做应用改造,别硬迁 |
| 单集群服务数 | > 25 | 会触发第二个 ALB,成本要单独算 |
如何把现有服务切到账户级网关?六步与回滚点#
整个迁移分平台侧和应用侧两条线,平台侧只做一次,应用侧按服务重复。
规范模板:基础设施角色的信任策略,ECS 代入它在你的账户里建 ALB、安全组、证书 [6]
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "ecs.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}
- 建基础设施角色(Infrastructure Role)。信任策略如上,权限至少覆盖
elasticloadbalancing:CreateLoadBalancer、elasticloadbalancing:CreateRule、acm:RequestCertificate、ec2:CreateSecurityGroup、wafv2:AssociateWebACL。这一步权限少了,后面 provisioning 会静默失败,排查很费时间。 - 平台队建 gateway。子网至少选 2 个可用区,安全组按客户端 CIDR 放行,TLS 证书填 ACM ARN,监听器 443,WAF Web ACL 一并挂上。
- 把 gateway 关联到目标 ECS 集群。
- 挑一个非核心服务,更新服务时加上 gateway connector 参数。ECS 会自动补证书、主机名、规则、目标组、服务安全组 [6]。
- 验证:DNS 解析、证书链、健康检查、host 路由四项都过。
- Route 53 加权切流 10% → 50% → 100%,观察 24 小时后回收旧 ALB。
可执行命令:入口冒烟,一次看完状态码、TLS 握手和首字节
curl -sS "https://www.api.plus/api/get?apikey=YOUR_KEY&ip=8.8.8.8" \
-o /tmp/body.json \
-w "HTTP=%{http_code} DNS=%{time_namelookup}s TLS=%{time_appconnect}s TTFB=%{time_starttransfer}s TOTAL=%{time_total}s\n"
# 期望输出
HTTP=200 DNS=0.012s TLS=0.048s TTFB=0.121s TOTAL=0.124s
参数含义:-sS 静默但保留错误输出;-o 把响应体落盘,避免污染耗时统计;-w 里 time_appconnect 是 TLS 握手完成时刻,这个值如果比基线高出一大截,八成是证书链缺了中间证书。time_starttransfer 是首字节时间,能反映后端冷启动。
返回体片段(字段名以 GET 示例接口 文档为准):
{"code":200,"msg":"success","data":{"ip":"8.8.8.8","location":"..."}}
可执行脚本:迁移期双入口比对,验证新旧响应一致
# compare_ingress.py — 同时打旧 ALB 和新网关主机名,比对状态码与响应体
import hashlib, os, ssl, socket, time
import requests # 2.32.x
OLD = os.environ["OLD_BASE"] # 旧入口,例如 https://www.api.plus
NEW = os.environ["NEW_BASE"] # ECS Gateway 分配的主机名
def probe(base: str):
t0 = time.perf_counter()
r = requests.get(base.rstrip("/") + "/api/get",
params={"apikey": os.environ["API_KEY"], "ip": "8.8.8.8"},
timeout=5)
return {"status": r.status_code,
"sha256": hashlib.sha256(r.content).hexdigest()[:16],
"ms": round((time.perf_counter() - t0) * 1000, 1)}
def cert_san(host: str, port: int = 443):
ctx = ssl.create_default_context()
with socket.create_connection((host, port), timeout=5) as s:
with ctx.wrap_socket(s, server_hostname=host) as ss:
return ss.getpeercert().get("subjectAltName", ())
old, new = probe(OLD), probe(NEW)
print("old:", old)
print("new:", new)
print("body 一致:", old["sha256"] == new["sha256"])
print("new SAN:", cert_san(NEW.split("//")[1].split("/")[0]))
预期效果:body 一致: True,且 new SAN 里必须包含你分配的网关主机名。如果 SAN 里只有通配符 *.elb.amazonaws.com,说明请求打到了旧 ALB,切流没生效。
关于调用方侧的流量切换比例,如果你本来就接了 沐小悠统计 做访客与来源分析,可以直接看新旧入口的 PV 比例是否和 Route 53 权重吻合,比翻日志快。
哪几个参数最容易踩坑?#
风险清单:按踩坑概率排序
- 安全组链式信任。服务安全组只放行来自 ALB 的入站 [6],客户端的 CIDR 必须写在 gateway 那层 ALB 的安全组上。放错了表现是超时或 504,不是 502,很多人会先去查应用。
- 25 服务上限是软上限。单个 ALB 最多 25 个服务,到顶后 ECS 自动建新 ALB [6]。所以同一 gateway 下的服务会散在多个 ALB 上,任何按 ALB 做 DNS 或白名单的方案都会漏服务。
- WAF 是共享故障域。真实案例:某团队把 rate-based 规则从 2000 req/5min 调到 200,10 分钟内 37 个服务集体 403。正确做法是新规则先以 count 模式跑 24 小时,看日志里的命中量再切 block。
- 证书别手动插手。gateway 上配的证书用于监听器,per-service 证书由 ECS 自动签发 [6]。你再往监听器上挂一张自定义证书,会和自动管理的那套打架,续期时表现为间歇性握手失败。
- 回收不可逆。最后一个服务解绑后 ALB 会被回收 [6]。切流前把所有硬编码 ALB DNS 的配置翻一遍,grep 一遍代码库的
elb.amazonaws.com。
WAF 这块不能因为换成托管网关就省掉。Cloudflare 2026 Q3 的报告显示每小时缓解超过 8200 次 DDoS 攻击,攻击形态转向更短、更高频的打击 [7];同期 AWS 披露的证据是漏洞从披露到出现可用利用代码的时间窗基本闭合,披露当天凌晨就有 PoC 在流传 [4]。入口层没有速率限制和规则拦截,等于把应用直接暴露在扫描流量下。
监控与告警清单#
告警配置:指标、阈值与动作
| 指标 | 建议阈值 | 告警动作 |
|---|---|---|
| ALB HTTPCode_Target_5XX_Count 占比 | > 1% 持续 5 分钟 | 查目标组健康主机数,区分是应用挂了还是安全组没通 |
| UnHealthyHostCount | ≥ 1 持续 2 分钟 | 直接通知服务负责人,附健康检查失败原因 |
| TargetResponseTime p99 | > 2s 持续 10 分钟 | 对比切换前基线,确认不是新入口引入的额外跳数 |
| 单个 ALB 关联的服务数 | ≥ 22 | 提前规划,避免触发自动建 ALB 带来的 DNS 变更 |
| ACM 证书剩余有效期 | < 30 天 | 检查自动续期是否失败,尤其自定义域名 |
| WAF BlockedRequests 突增 | > 5 倍 7 日基线 | 先确认是否误杀,必要时把规则切 count 模式 |
| 基础设施角色 AssumeRole 失败 | ≥ 1 次 | 立即处理,这类失败会导致新服务无法 provisioning |
最后一条最容易被漏掉。前面说过权限给少了会静默失败,所以把这个 IAM 角色的 AssumeRole 失败次数单独拉一条告警,比事后翻 CloudTrail 划算得多。
总结:迁移是一次性投入,换的是入口口径统一#
我的判断标准很朴素:如果入口配置散落在十几个团队手里、每次上新服务都要重新走一遍 ACM 申请和安全组审批,那 ECS Gateway(Amazon 托管容器入口网关) 值得迁;如果入口本来就只有两三个人管、服务总量不到 5 个,迁过去只是把手工活换成学习成本。
真正需要提前设计的是三件事:WAF 规则的灰度流程、监控里那条“ALB 接近 25 个服务”的预警、以及切流期间的双入口比对。这三件做完了,迁移本身按六步走就行。
迁移完成后,如果你的服务对外提供 API,配套的调用示例和调试方法可以参考站内 GET 示例接口、POST 示例接口 与 API 文章中心;入口侧要做账号体系的话,沐小悠聚合登录 提供社会化账号聚合登录,省掉自建 OAuth 回调域名的证书配置。需要免费 API Key 的话,可以直接在 API.PLUS(沐小悠API)注册获取,遇到接入问题走 技术支持。
适用范围:
- ECS 上运行的服务数 ≥ 15,入口由多个团队分散维护的账户。
- 需要统一 TLS 证书、WAF 与安全组基线,且接受共享故障域的组织。
- 希望按服务粒度拿到独立 DNS 主机名,减少手工 ACM 申请的团队。
不适用范围:
- 服务数少于 5 个,或全部入口由单人维护,迁移收益抵不过改造成本。
- 重度依赖 Nginx Ingress 注解实现 rewrite、灰度、限流的架构,ECS Gateway(Amazon 托管容器入口网关) 只做 host 路由,这些能力需要重新找落点。
- 同一域名下需要复杂路径匹配与跨集群流量分割的场景,仍需自管 Ingress 或服务网格。
- 入口配置需要按租户隔离、且租户之间不能共享 WAF 规则的强合规环境。
常见问题(FAQ)
ECS Gateway 会不会替代 WAF 和 Shield?
迁移期间新旧入口能并存吗?
如何把现有服务切到账户级网关?六步与回滚点?
参考来源
- Introducing Amazon ECS Gateway: A fully-managed ingress solution for ECS services
- AWS Weekly Roundup: Amazon Polly Generative engine, TorchNeuron for Trainium, and more (October 26, 2026)
以上为本文写作时的参考资料,引用观点以原文为准。