用户登录

技术文章

外部链接将在新标签页打开。

Amazon ECS Gateway 迁移评估:账户级托管入口怎么落地

一句话回答

ECS Gateway 把 ALB、ACM 证书、WAF 与安全组收拢为账户级资源,一个 ALB 最多承载 25 个服务。服务数超过 15、入口规范需要统一的 ECS 账户值得迁移;服务少于 5 个或依赖 Nginx Ingress 注解的团队,改造成本高于收益。

核心要点 TL;DR
  • 单网关单 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"
  }]
}
  1. 建基础设施角色(Infrastructure Role)。信任策略如上,权限至少覆盖 elasticloadbalancing:CreateLoadBalancer、elasticloadbalancing:CreateRule、acm:RequestCertificate、ec2:CreateSecurityGroup、wafv2:AssociateWebACL。这一步权限少了,后面 provisioning 会静默失败,排查很费时间。
  2. 平台队建 gateway。子网至少选 2 个可用区,安全组按客户端 CIDR 放行,TLS 证书填 ACM ARN,监听器 443,WAF Web ACL 一并挂上。
  3. 把 gateway 关联到目标 ECS 集群。
  4. 挑一个非核心服务,更新服务时加上 gateway connector 参数。ECS 会自动补证书、主机名、规则、目标组、服务安全组 [6]。
  5. 验证:DNS 解析、证书链、健康检查、host 路由四项都过。
  6. 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?
不会。网关负责把 ALB、证书、安全组、host 路由这些入口设施收口,WAF Web ACL 仍然要显式在 gateway 上配置并维护规则,DDoS 清洗依旧由 AWS Shield 承担。
迁移期间新旧入口能并存吗?
可以。给服务加上 gateway connector 参数后,新入口会分配独立 DNS 主机名,旧 ALB 不删除,用 Route 53 加权记录从 10% 逐步切到 100%,观察 24 小时再回收旧资源。
如何把现有服务切到账户级网关?六步与回滚点?
规范模板:基础设施角色的信任策略,ECS 代入它在你的账户里建 ALB、安全组、证书 [6]

参考来源

  1. Introducing Amazon ECS Gateway: A fully-managed ingress solution for ECS services
  2. AWS Weekly Roundup: Amazon Polly Generative engine, TorchNeuron for Trainium, and more (October 26, 2026)

以上为本文写作时的参考资料,引用观点以原文为准。

作者:沐小悠

本文约 21 分钟读完 · 关键词:Amazon ECS Gateway、ECS 托管入口、ALB 共享、容器 Ingress 迁移、API.PLUS

更多文章 GET 示例接口

「」标签下的其他文章