小白用AWS ECS + GitHub Action 实现自动部署
代码写完后,我们需要把应用们部署到服务器上,有了 GitHub Action 我们实现了分支(Branch)自动 push,即每此有新代码提交到分支,代码就会自动部署新服务到 AWS 已绑定的 ECS。可谓一劳永逸。
1.1 ECS Fargate VS ECS VS EC2
EC2 即 AWS 明星产品 Elastic Compute Cloud,简单理解就是我们常说的虚拟机,服务器 VM,virtual machine。
ECS 即在 EC2 基础上引用“盒子”(Docker Container),全称 Elastic Container Service。简单理解就是我们获得了一台已经安装好 Docker 环境的虚拟机,用户无需自己再为了部署需要另外自己安装 Docker。
ECS Fargate,顾名思义具备了自带 Docker 盒子环境的虚拟机,但这里的虚拟机用户无需管控操作系统等基础设施(infrastructure)级别的工作,这部分工作有服务提供商 AWS,用户只需自己管理自己应用软件代码等。简单理解 ECS 仍然属于 EC2 类别的 IaaS 类型的云服务,ECS Fargate 属于 PaaS 类型的云服务。

用户根据自身需求选择所需服务类型。没有了操作系统等需求的管理工作,限制更多,但是更加灵活,节省了不必要的时间+人力成本。
1.2 GitHub Action
GitHub Action 为用户提供了一键部署代码到 AWS Fargat 的模板。实现自动部署之前,我们需要将存放代码的 GitHub Repo 绑定 AWS 账户。
此服务对应 AWS IAM 里面的 credentials。

在 AWS 账户里创建好用于三方服务接入的密钥以后,我们将密钥输出要预备部署到 AWS 的 GitHub repo 里面。
GitHub 绑定地点对应 Repo settings 里的 Actions secrets and variables 层面

1.3 Docker
当前最流行的部署技术。代码需要在使用 Docker 的 ECS Fargate 上跑,首先需要创建 Docker 文件。
我们可以在项目根目录,创建 dockerfile,指定让代码跑起来需要的环境,代码版本,安装包……
确保 docker 文件无误,可以再本地环境先跑跑……
准备工作就绪以后我们开始 ECS 部署
2.1 ECS 服务权限
从安全角度,第一次配置 ECS 服务都需要在 AWS 里面开启。我们需要在 IAM role 里面创建一个角色,这个角色有执行 ECS 任务的权限。后续创建的所有 ECS 服务,需要获得此角色权限才能运作。

对于 ECS 服务,需要赋予 ECS 任务执行权限。如果 ECS 需要关了 AWS secret(例如数据库密码等存放于 AWS Secret Manager),还需要添加 ecsTaskExecutionRoleWithSecrets。
ecsTaskExecutionRoleWithSecrets 需要自行创建,比较简单的办法是复制粘贴 json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource":
"arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:SECRET_NAME"
}]
}
2.2 创建 AWS ECS Repo
在 Amazon ECR - Private registry - Repositories 里面创建 Repo,需要指定 Repo 的名字。
ECR 即 Elastic Container Registry,专门用于 ECS 里面注册 repo,container image 等。
2.3 创建 Task Definition
Task Definition 可以点鼠标也可以用 json 导入,用于指定服务所需资源,环境变量等。
在任务定义里面,我们需要指定任务获得 ECS 执行权限,即我们在 2.1 步骤里创建的角色。

同时还需要指定 ECS 服务所需的资源配置。

这里选择 Fargate,即让 AWS 替我们管理基础设施,同时指定虚拟机的操作环境等配置信息。
在指定任务时,还需要根据需求设定环境变量(Environment variables)。例如数据库密码等。

对于数据库密码这种敏感信息,我们可以选择将其先存入 AWS Secrets Manager,再导入,以提高应用安全性能。对于普通环境参数,例如 token 过期时间,可以选择直接填入 value 值在环境变量设置栏位。
2.4 创建 ECS Clusters
Amazon Elastic Container Service - Clusters 创建 Cluster,指定 Cluster 的名字。
Cluster 类似于文件夹,一个 cluster 里面可以存放创建一个或多个 ECS 服务。例如 cluster A 放后端服务,cluster B 放前端服务,cluster C 放测试……
2.5 创建 ECS Farget 服务
有了 cluster 后,我们在对应的 cluster 里面创建服务。

给新建服务取名时,我们还需要指定 Task definition,即 2.3 步骤里面完成的工作,指定服务将按怎样的资源定义跑起来。

以上为配置 ECS 服务需要勾选的必填信息。AWS 端的各种服务创建工作完成后,我们可以在 GitHub 里进行配置,实现一劳永逸自动部署。
2.6 创建 workflow yml 文件
在项目根目录创建 workflows 文件,指定 AWS 服务提供。yml 文件模板可以在 GitHub Action 里“Deploy to Amazon ECS”教程里面免费获取,无需自己手动输入。

如图所示,我们在 workflows 里面创建了 2 个 yml 文件,aws 用于正式 branch 部署,即有新代码上传到 master 分支以后,自动执行完成 AWS ECS 部署;aws-dev 用于开发分支部署,一有新代码上传到 dev 分支以后,自动完成 AWS ECS 部署,方便团队成员做正式上线前的测试。

如图所示,我们需要在 aws yml 里面指定部署分支,以及对应的 AWS 环境设施

在 jobs 里面设置我们用于 GitHub repo 和 AWS 账户绑定的密钥。
以上步骤完成以后,当有新代码被 pushed 到 master 分支后,GitHub Action 自动执行将新代码部署到对应的 AWS ECS 服务,所需时间 10 分钟。

所有部署工作完成以后,我们在 AWS 账户里面看到我们有 ECS 服务任务正在运行。

实际操作中,成功完成以上步骤,可能需要多次调试,检测。
AWS 每次完成 ECS 部署都会重新分配新 IP 地址(和 Azure 不一样)。实际生产环境,我们需要给用户提供固定 IP 用于服务访问。所以在 ECS 服务配置中还需要多几个步骤,并同时引入 AWS balance 服务……
在 ECS 服务创建步骤的选填步骤中,我们需要创建 namespace 和 Service discovery name,让该服务可以被 load balance 找到。

接下来在 Load Balance 里面创建 Application Load Balancer。

这样用户可以用过固定 URL 访问服务。每次有用户访问时,Application Load Balancer 自动 map 到 ECS 服务。除了固定访问地址外,可以屏蔽一些攻击(外部只能访问 load balancer),需要绕过 load balancer 才能攻击服务。
我记得以前使用 Azure 时,每次完成部署队伍 IP 地址不变,面对 AWS 莫名其妙改动 IP 访问地址,又找了好些资料才完成。
实际一通操作下来,在 AWS 完成类似功能部署,看似有了很多灵活性和各种用户自定义的安全策略和服务提升,但步骤多了很多,而且经常因为 AWS 的各种权限配置操作搞得程序员自己被挡在服务外部,略头疼。
对于小白如我,好像还是 Azure 那种“懒人式”比较适合。
喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!