1. AWS容器平台全景与交付链路

在 AWS 上交付一个容器化应用,从来不是“把镜像推到仓库、再跑一条部署命令”这么简单。真正决定交付是否稳定、可观测、可回滚的,是背后一整套组件的协作:容器运行时负责把镜像变成进程,编排服务负责把进程调度到合适的位置,镜像仓库负责分发不可变的制品,网络组件负责让流量找到正确的 Pod,安全组件则贯穿从拉取镜像到访问后端服务的每一个环节。理解这条链路上每个角色的职责与接口,是后续所有实操章节的基础。

一、四类核心组件及其职责边界

可以把 AWS 容器平台拆成四个层次来理解。

容器运行时层:这是最贴近操作系统的一层。在 EC2 上,Docker 或 containerd 负责拉取镜像、解压层、创建命名空间与 cgroup 隔离,最终启动容器进程。在 AWS Fargate 上,运行时被托管,用户看不到节点,但仍遵循同样的镜像与进程模型。运行时的关键输入是镜像引用(如 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/order-api:v1.4.2)和启动参数(环境变量、端口、CPU/内存限制),输出是一个正在运行的容器进程。

编排服务层:Amazon ECS 和 Amazon EKS 是两种主流选择。ECS 使用 Task Definition 描述“一个任务需要哪些容器、多少 CPU/内存、暴露哪些端口”,再由 Service 维持期望副本数;EKS 则基于 Kubernetes 的 Deployment、Service、Ingress 等对象,由控制平面完成调度与自愈。编排层解决的是“在哪里跑、跑几个、挂了怎么办”的问题,它不关心镜像内部是什么,只关心声明的期望状态是否被满足。

镜像仓库层:Amazon ECR 承担镜像的存储与分发。它提供私有仓库、镜像扫描、跨区域复制和生命周期策略。交付链路上,CI 流水线构建镜像后推送到 ECR,运行时再从 ECR 拉取。ECR 的镜像标签应当与 Git 提交或构建号绑定,避免使用 latest 这类可变标签,否则回滚时无法确定具体版本。

网络与安全层:网络方面,VPC、子网、安全组、ALB/NLB 以及 EKS 的 VPC CNI 共同决定 Pod 的 IP 分配和流量路径;安全方面,IAM 角色(Task Role / IRSA)、Secrets Manager、KMS、安全组规则和镜像扫描共同构成最小权限与数据保护的基础。这一层往往是最容易被忽视、却最容易在故障排查时暴露问题的部分。

AWS 容器应用交付链路:从代码到可访问服务 开发者 / CI 流水线 git commit → build Amazon ECR 镜像存储 / 扫描 / 复制 编排服务 ECS / EKS 调度 / 自愈 / 期望副本 容器运行时 containerd / Fargate push image ref pull & run 网络层:VPC / 子网 / 安全组 / ALB / VPC CNI 决定 Pod IP 分配、入站流量路径与东西向通信 安全层:IAM Task Role / IRSA / Secrets Manager / KMS 最小权限、密钥注入、镜像扫描与访问控制 网络接入 角色绑定 终端用户 HTTPS 请求 流量入口 交付链路关键判断点 ① 镜像标签是否与构建号绑定,能否精确回滚;② 编排层期望副本数与实际运行数是否一致; ③ 安全组与 ALB 监听规则是否放行目标端口;④ Task Role / IRSA 是否具备访问后端所需的最小权限。

二、交付链路上的数据流与依赖顺序

把上述组件串起来看,一次典型的交付会经历如下顺序。CI 系统在代码合并后构建镜像,打上形如 v1.4.2-20240612 的标签并推送到 ECR。随后更新 ECS Task Definition 或 EKS Deployment 中的镜像引用,触发一次新的部署。编排服务读取新的期望状态,向运行时下发拉取指令;运行时从 ECR 拉取镜像层,创建容器进程。容器启动后,VPC CNI 为其分配 IP,安全组决定哪些来源可以访问该端口,ALB 通过目标组健康检查确认实例可用后,才开始转发用户流量。整个过程里,IAM 角色在容器启动时被注入,Secrets Manager 中的数据库密码通过环境变量或挂载卷进入容器。

这条链路有一个重要特征:依赖是单向的,但故障排查是反向的。部署失败时,现象可能出现在最上层(用户访问 502),但根因可能在最下层(安全组未放行、镜像拉取失败、IAM 权限不足)。因此,理解每一层的输入输出,比记住某个命令更重要。

三、一个可复现的示例:部署 order-api 到 ECS Fargate

下面以一个订单服务为例,给出关键参数与观察点。示例中的账号、区域和镜像标签均为教学假设值。

# 1. 构建并推送镜像(CI 阶段)
docker build -t order-api:v1.4.2-20240612 .
docker tag order-api:v1.4.2-20240612 \
  123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/order-api:v1.4.2-20240612
docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/order-api:v1.4.2-20240612

# 2. Task Definition 关键字段(节选)
{
  "family": "order-api",
  "cpu": "512",
  "memory": "1024",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "containerDefinitions": [{
    "name": "order-api",
    "image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/order-api:v1.4.2-20240612",
    "portMappings": [{"containerPort": 8080, "protocol": "tcp"}],
    "environment": [{"name": "APP_ENV", "value": "prod"}],
    "secrets": [{"name": "DB_PASSWORD",
                 "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:order-api/db-xxxx"}]
  }]
}

部署后,按以下顺序观察结果。第一,在 ECS 控制台查看 Service 的 desiredCount 与 runningCount 是否一致;若 runningCount 长期为 0,优先查看 Stopped Task 的 stoppedReason,常见原因是镜像拉取失败或 Secrets 权限不足。第二,查看目标组的健康检查状态,若为 unhealthy,检查容器端口是否与 containerPort 一致、安全组是否放行 ALB 所在子网的流量。第三,从 ALB DNS 名称发起一次请求,确认返回 200 且响应体包含预期字段。第四,在 CloudWatch Logs 中确认应用启动日志无异常。

判断部署是否真正成功的标准不是“任务在运行”,而是“用户请求能稳定返回正确结果”。任务运行只说明运行时和编排层正常,网络与安全层是否打通,必须通过实际请求验证。

四、常见误区与排查方向

初学者最容易踩的坑有三个。其一,使用 latest 标签,导致回滚时无法定位具体版本,也无法判断线上运行的是哪次构建。其二,把 IAM 权限直接给到节点角色而非 Task Role,造成权限过大且难以审计;在 EKS 中应优先使用 IRSA 将角色绑定到 ServiceAccount。其三,忽略安全组的“最小放行”原则,直接开放 0.0.0.0/0 到容器端口,使服务绕过 ALB 暴露在公网。

当出现访问异常时,建议按“运行时 → 编排 → 网络 → 安全”的顺序反向排查:先确认容器是否启动、日志是否正常,再确认编排层期望状态是否达成,然后检查安全组与目标组,最后核对 IAM 与 Secrets 权限。这条排查路径与交付链路的依赖方向相反,但正是它让每一层的职责边界变得清晰。