简介
在“AWS CICD 之 CodeCommit/Build/Deploy 下篇”文章中,我们利用 Lamdba 函数,把 Code Commit/Build/Deploy 连接起来,形成一个完整的 CICD 流水线。
图 52
在“AWS CICD Step Function 上篇 邮件审批”文章中,我们介绍了如何用 Step Funcion 实现邮件审批。
图 28
本文中,我们把 Step Function 加入 CICD 流水线,实现带邮件审批的 CICD 部署流水线,如下图。
图 1
目录
- 环境(配置)
- 实战步骤
1. 创建 Cloudwatch rule
- 新建 IAM Role
- 新建 Rule/Trigger
2. 修改 Step Function
- 增加调用 Lambda 权限
- 修改 Step Function 定义
3. 测试带邮件审批的 CICD 流程
- 总结
- 引申
- 资源下载
- 后记
环境(配置)
- AWS 中国或 Global 帐号,可在官网申请,一年内使用指定资源免费
- AWS cli,Win10 + terminal
- 公网邮箱
实战步骤
1. 创建 Cloudwatch rule
我们将新建一个 Cloudwatch Rule。当 Codebuild 成功完成时,通过 Rule 触发 Step Function 的审批邮件功能。
新建 IAM Role
首先,我们建一个 IAM Role,这个 Role 赋予 Cloudwatch event 运行 Step Function 的权限。
在 IAM 界面选择“Roles”,点击“Create role”
图 10-13
依次选择“AWS Service”,“Elastic Container Service”,“Elastic Container Service Task”后,点击“Next:Permissions”
注意:我们的 Role 是给 events 用的,即 trusted entity 是 events,但选项中并没有 events 选项,我们先选择 ECS,最后会把 trusted entity 改为 events
图 10-14
在搜索框中输入“step”,然后选中“AWSStepFunctionsFullAccess”,点击“Next:Tags”
图 4
点击“Next:Review”,添加 Role 名称“tsEventforTriggerSF”后,点击“Create Role”。
建好 Role 后,选择“Trust relationships”后,点击“Edit trust relationship”
图 5
粘贴以下内容,把 trusted entity 改成 events
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
图 6
更改 trusted entity 完成
图 7
新建 Rule/Trigger
在中国区的 Cloudwatch Rule 的界面上,当把 Trigger 选择成 Step Function 时,我们找不到任何 SF。
图 8
所以这里我们用 AWS cli 创建新的 Cloudwatch Rule/Trigger,当 CodeBuild 成功完成时触发 Step Function。
在安装有 AWS Cli 的环境中运行以下命令
aws events put-rule --name "tsCodeBuildTriggerSF" --event-pattern "{\"source\":[\"aws.codebuild\"],\"detail-type\":[\"CodeBuild Build Phase Change\"],\"detail\":{\"completed-phase\":[\"POST_BUILD\"],\"completed-phase-status\":[\"SUCCEEDED\"],\"project-name\":[\"tstestCodeCommit\"]}}" --description "codebuild trigger Step machine"
说明:
- name Rule 的名称
- event-pattern codebuild 的事件 pattern,与“AWS CICD 之 CodeCommit/Build/Deploy 下篇”文章中 Rule “tsCodeDeploytrigger”中的 event pattern 相同
- description rule 的描述信息
event pattern 内容如下
{
"source": [
"aws.codebuild"
],
"detail-type": [
"CodeBuild Build Phase Change"
],
"detail": {
"completed-phase": [
"POST_BUILD"
],
"completed-phase-status": [
"SUCCEEDED"
],
"project-name": [
"tstestCodeCommit"
]
}
}
运行结果,创建 Cloudwatch Rule 成功返回 Rule 的 ARN
图 2
接下来运行以下命令,建 Rule 中的 Trigger,用来触发 Step Function
aws events put-targets --rule tsCodeBuildTriggerSF --targets "Id"="Target1","Arn"="arn:aws-cn:states:cn-north-1:XXXX:stateMachine:tsSFcallBack","RoleArn"="arn:aws-cn:iam::XXXX:role/tsEventforTriggerSF"
说明:
- rule 上面创建的 Rule 的名称
- targets SF 的 ARN 和上面创建的 Event Role 信息,这里也可以注册多个 Targets
运行结果,创建 Trigger 成功
图 3
现在可以在 Cloudwatch 的 Rule 中看到新建的 Rule
图 9
新 Rule 建好后,我们把原来 CICD 中直接触发 CodeDeploy 的 Rule “tsCodeDeploytrigger”停掉。
运行以下命令
aws events disable-rule --name tsCodeDeploytrigger --no-verify-ssl
灰色表示 disable
图 10
2. 修改 Step Function
增加调用 Lambda 权限
在之前的 CICD 中,Lambda 函数“tsCodeBuildTriggerDeploy”用来启动 Codedeploy 的部署,本文中继续用这个函数来启动部署。
我们需要给 SF 的 role 添加调用此 Lambda 函数的权限,在 SF 界面选择“tsSFcallBack”,点击“IAM role ARN”部分,打开 IAM Role 界面
图 14-19
展开上篇文章中创建的 Policy“tslambda-policy”,点击“Edit policy”
图 11
选择 JSON,粘贴以下内容
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"arn:aws-cn:lambda:cn-north-1:YOUR_AWS_ACCOUNT:function:tsSendMailforSF:*",
"arn:aws-cn:lambda:cn-north-1:YOUR_AWS_ACCOUNT:function:tsCodeBuildTriggerDeploy:*"
]
},
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"arn:aws-cn:lambda:cn-north-1:YOUR_AWS_ACCOUNT:function:tsSendMailforSF",
"arn:aws-cn:lambda:cn-north-1:YOUR_AWS_ACCOUNT:function:tsCodeBuildTriggerDeploy"
]
}
]
}
说明:其中增加了 SF 对 Lambda 函数“tsCodeBuildTriggerDeploy”的调用权限
点击“Review policy”,再点击“Save Changes”保存更改
图 12
修改 Step Function 定义
下面我们修改 SF “tsSFcallBack”,在 Approve 分支增加调用 Lambda 函数“tsCodeBuildTriggerDeploy”的功能。
在 Step Function 界面,选择“State machines”,选择“tsSFcallBack”,点击“Edit”
图 13
在 Definition 部分,粘贴资源下载中 sf.json 文件中的内容。
主要修改部分是 ApprovedPassState 这部分,增加了调用 Lambda 函数
...
"ApprovedPassState": {
"Type": "Task",
"Resource": "arn:aws-cn:states:::lambda:invoke",
"Parameters": {
"FunctionName": "arn:aws-cn:lambda:cn-north-1:XXXX:function:tsCodeBuildTriggerDeploy"
},
"End": true
},
...
然后点击“Save”保存
图 14
3. 测试带邮件审批的 CICD 流程
在本地 Git Repo 中 touch file,然后 push 代码,启动 CICD 流水线
图 15
在 CodeBuild 中观察到 Build 项目启动
图 16
图 17
Build 项目成功结束
图 20
这时在 SF 界面,可以看到 SF 运行到“Lambda CallBack”的状态。这时正在等待邮件审批结果(callback)
图 21
过 1-2 分钟,收到审批邮件后,点击“Approve”下面的链接
图 18
在 CodeDeploy 界面可以看到部署开始了,而这时 SF 已经成功结束了
图 22
图 19
过一段时间,CodeDeploy 会部署完成。Fargate 的部署 Task 过程就不截图了,和直接用 CodeDeploy 部署没差别了
总结
我们再把整个 CICD 流程梳理一下
图 1图 28
- 用户在客户端用 Git 命令 Push 代码到 CodeCommit 的代码仓库中
- CloudWatch 通过设置的 Rule 触发 CodeBuild 构建项目
- 构建项目启动后,从代码仓库中拉到代码,生成镜像,然后把镜像推送至 ECR
- 在构建项目 POST_BUILD 成功后,CloudWatch 通过设置的 Rule 触发 Step Function
- Step Function 触发 sendmail Lambda 函数,生成含有 taskToken 的 approve/reject 链接,并通过 SNS 发送邮件给客户
- 客户点击邮件中 approve/reject 链接,把请求发送至 ALB。
- ALB 把请求转发给 apporve Lambda 函数,apporve 函数把审批结果返回给 Step Function
- Step Function 根据 callBack 的结果选择 approve 或 reject 分支
- 如果选择 approve 分支,则 Step Function 触发部署 CodeDeploy 的 Lambda 函数,函数启动 CodeDeploy 后终于,SF 终止
- 如果选择 reject 分支,则 SF 终止
引申
如果 push 两次的时间很近,Codebuild 会按先后顺序同时开始 Build,同时 SF 也会被调用两次,发两次邮件。
如果两次邮件都点 Approve,第二个 SF 会报错停止。
Error
DeploymentLimitExceededException
{
"errorMessage": "An error occurred (DeploymentLimitExceededException) when calling the CreateDeployment operation: The Deployment Group 'tstestDGrp' already has an active Deployment 'd-FLZE9E3H8'",
"errorType": "DeploymentLimitExceededException",
图 23
原因在于 CodeDeploy 每个 Deploy Group 只能同时运行一个部署
Feature | Limit |
Maximum number of concurrent deployments to a deployment group¹ | 1 |
https://docs.aws.amazon.com/codedeploy/latest/userguide/limits.html#limits-deployments
资源下载
相关 policy 文件可在下列链接中下载https://github.com/tansong0091/realCrapForAWS/tree/main/StepFunction2
后记
CICD 部署流水线,没有固定的工具和方法。只要实现了自动化,不管是用 AWS 提供的服务也好,还是自己写的 shell 脚本,效果都是一样的。
本文的例子用到了多个 AWS 服务,但这只是 CICD 实现的一种具体方式。如果有朋友还有更好的方法,可以私信我一起研究学习。
喜欢请点赞,欢迎转发
微信公众号“全是 AWS 干货”