AWS用CodeDeploy来做部署、更新和回退
一、准备工作和先决条件
(1)被部署的实例,需要安装codedeploy-agent,安装方法
git clone https://github.com/aws/aws-codedeploy-agent.git cd aws-codedeploy-agent/bin ./install auto
或者用我从安装过程中截获的rpm包安装也行,分享给大家wget即可
http://cypay-filesharing.s3.amazonaws.com/public/wangfei/codedeploy-agent-1.0-1.643.noarch.rpm
(2)创建一个存放代码包的S3 bucket,此例中叫s3://CYPayCodeDeployBucket
,美东地区
(3)创建一个Instance Profile,并使新创建的EC2实例使用该Instance Profile,这个过程中还需要创建个IAM Role,并让Role与Profile关联,该过程授权EC2实例内部的CodeDeploy-Agent能从S3下载版本包。然后再创建一个 Service Role给Codedeploy服务用,该服务需要一些EC2权限
大概创建过程:创建个IAM Role,授权AssumeRole和访问版本存放S3,再创建个Instance Profile,然后将之前的Role关联到Profile上;再创建个Role给CodeDeploy服务用;
具体过程:
创建文件 CodeDeployInstanceProfile-Trust.json
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
再创建一个文件CodeDeployInstanceProfile-Permissions.json
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:Get*", "s3:List*" ], "Effect": "Allow", "Resource":"arn:aws:s3:::CYPayCodeDeployBucket/*" } ] }
然后创建角色叫CodeDeployInstanceRole,并给Role加策略
aws iam create-role \ --role-name CodeDeployInstanceRole \ --assume-role-policy-document file://CodeDeployInstanceProfile-Trust.json aws iam put-role-policy \ --role-name CodeDeployInstanceRole \ --policy-name CDInstanceRole-Permissions \ --policy-document file://CodeDeployInstanceProfile-Permissions.json
然后创建instance profile,并把刚才创建的Role附加到instance profile上,这样使用这个instance profile创建的EC2实例,就拥有Role对应的权限和策略
aws iam create-instance-profile \ --instance-profile-name CodeDeployInstanceProfile aws iam add-role-to-instance-profile \ --instance-profile-name CodeDeployInstanceProfile \ --role-name CodeDeployInstanceRole
至此,一个具有codedeploy相关权限的Instance Profile就创建好了,创建自动部署的EC2实例的时候需要使用该Profile
接下来创建一个Service Role 这个是codedeploy服务用来在EC2实例中部署代码的
创建文件 CodeDeployServiceRole-Trust.json
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": [ "codedeploy.us-east-1.amazonaws.com", "codedeploy.us-west-2.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ] }
再创建一个文件CodeDeployServiceRole-Permissions.json
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "autoscaling:PutLifecycleHook", "autoscaling:DeleteLifecycleHook", "autoscaling:RecordLifecycleActionHeartbeat", "autoscaling:CompleteLifecycleAction", "autoscaling:DescribeAutoscalingGroups", "autoscaling:PutInstanceInStandby", "autoscaling:PutInstanceInService", "ec2:Describe*" ], "Effect": "Allow", "Resource": "*" } ] }
创建一个角色CodeDeployServiceRole,然后将角色策略与角色相关联
aws iam create-role \ --role-name CodeDeployServiceRole \ --assume-role-policy-document file://CodeDeployServiceRole-Trust.json aws iam put-role-policy \ --role-name CodeDeployServiceRole \ --policy-name CDServiceRole-Permissions \ --policy-document file://CodeDeployServiceRole-Permissions.json
获取Role的相关信息,复制下来备用
aws iam get-role --role-name CodeDeployServiceRole --query "Role.Arn" --output text arn:aws:iam::154xxxxx7698:role/CodeDeployServiceRole # mark this down
第(3)步总结:
创建两个Role
CodeDeployInstanceRole
CodeDeployServiceRole
创建一个InstanceProfile
CodeDeployInstanceProfile
注意事项:
Instance Profile必须创建实例的时候选择,事后暂无办法让没选InstanceProfile的实例使用某个Profile
CodeDeploy-agent目前只在最新版的Amazon Linux,Ubuntu,Windows 上测试过,而且自带yum源中没有
二、用CodeDeploy部署个新项目
(1)上一步已经创建好使用CodeDeployInstanceProfile这个Profile的EC2实例,并且打好标签的(例如Name=cms.front),而且实例上已经装好了codedeploy-agent
(2)准备代码,此处用tomcat应用举例。
解压代码,在工程目录目录里添加scripts目录和一个appspec.yml,例如下面这样的目录结构,scripts里面放部署时使用的脚本,appspec.yml文件定义代码部署到哪个,用什么用户在什么阶段执行什么脚本
cms.front/ ├── appspec.yml ├── css/ ├── error.jsp ├── fonts/ ├── html/ ├── images/ ├── index.jsp ├── js/ ├── META-INF/ ├── scripts/ ├── static/ └── WEB-INF/
appspec.yml文件内容,格式要求非常严格,不允许多余空白
version: 0.0 os: linux files: - source: / destination: /home/ec2-user/tomcat/webapps/ hooks: BeforeInstall: - location: scripts/check_dependencies.sh timeout: 300 runas: root AfterInstall: - location: scripts/change_permissions.sh timeout: 300 runas: root ApplicationStart: - location: scripts/start_server.sh timeout: 300 runas: ec2-user ApplicationStop: - location: scripts/stop_server.sh timeout: 300 runas: ec2-user
首次部署,需要安装依赖软件和环境,之后做代码更新时就不需要了
可以把启动脚本写成重启脚本
这四个脚本我就不多说了,自定义性比较强
然后重新打包,只包含内容,不要将上级目录也打进包
cd ~/version/cms.front/ && zip -r cms.front.v1.0.zip *
然后将版本包上传到上述创建的Bucket里CYPayCodeDeployBucket
官方文档中介绍用aws deploy push
上传,但是报错了,也没找到解决办法,就用aws s3 cp
上传的
Missing required parameter in input: "UploadId"
Unknown parameter in input: "uploadId", must be one of: Bucket, Key, UploadId
更新aws-cli也无用,有解决此错误的请告诉我
然后创建一个Application,理解成一个具有相同功能的一个代码工程,此例为cms.front
aws deploy create-application --application-name CMSTomcatApplication
然后将重新打包好的版本包push到S3上(这步报错了,所以手动传的)
aws deploy push \ --application-name CMSTomcatApplication \ --s3-location s3://CYPayCodeDeployBucket/cms.front.v1.0.zip \ --ignore-hidden-files
然后创建DeploymentGroup,理解成一组需要被部署相同代码的EC2实例,此例为cms.tomcat,按Tag来区分,或则按autoscal组来区分
aws deploy create-deployment-group \ --application-name CMSTomcatApplication \ --deployment-group-name CMSTomcatApplication \ --deployment-config-name CodeDeployDefault.OneAtATime \ --ec2-tag-filters Key=Name,Value=cms.tomcat,Type=KEY_AND_VALUE \ --service-role-arn arn:aws:iam::15xxxxxx698:role/CodeDeployServiceRole
最后一行为上面创建的ServiceRole(让吧返回值记录下来来着,现在用到了)
然后创建一个部署,首次部署,跟代码更新部署,和回滚部署,本质是一样,没区别
aws deploy create-deployment \ --application-name CMSTomcatApplication \ --deployment-config-name CodeDeployDefault.OneAtATime \ --deployment-group-name CMSTomcatApplication \ --s3-location bucket=CYPayCodeDeployBucket,bundleType=zip,key=cms.front.v1.0.zip
返回值
{ "deploymentId": "d-ROL5D7YPZ" }
可以查看该部署的状态
aws deploy get-deployment --deployment-id d-ROL5D7YPZ --query 'deploymentInfo.status' "InProgress"
等进度从InProgress变成Succeeded就成功了,然后浏览器访问下自己的代码是否OK
三、 做次代码更新和回滚
本质是一样的,只不过版本包不同而已,可以吧首次部署的一些无用脚本删除,回滚的话,会删除就得部署新的
命令行的话,还是这样
aws deploy create-deployment \ --application-name CMSTomcatApplication \ --deployment-config-name CodeDeployDefault.OneAtATime \ --deployment-group-name CMSTomcatApplication \ --s3-location bucket=CYPayCodeDeployBucket,bundleType=zip,key=cms.front.v1.1.zip
区别在于使用的版本包版本不同
版本更新和回退,使用web console用浏览器来做最爽
选择你的Application,进到DeploymentGroup里,然后选择Deploy New Revision
此时Application和DeploymentGroup的下拉菜单应该已经都默认选好了,还可以改
选择Revision Type,可选为S3或者github,此例为S3 bucket
Revision Location里写上版本包的全路径,s3://CYPayCodeDeployBucket/cms.front.v1.1.zip
File Type会自动识别,支持zip,tar,tar.gz,别的格式没试过,war跟zip一样的吧
Deployment Description写上版本说明
Deployment Config有三种可选
CodeDeployDefault.AllAtOnce, CodeDeployDefault.HalfAtATime, CodeDeployDefault.AllAtATime.
AllAtOnce:组中所有实例一次部署完(同时并发),有成功的实例就算此次部署成功,都部署失败就算此次部署失败
HalfAtATime:一次部署一半实例,分两次部署完,一半以上实例成功才算部署成功,一半以上失败就算部署失败
AllAtATime:一次部署一台,直至全部完成,所有实例都部署成功才算成功,有失败的就算部署失败(这个最符合我的需求,可以在起服脚本中加上sleep来实现一台一台来更新,并间隔几百秒)
点击Deploy Now来完成部署,等到刷新状态为Succeeded就成功了,接下来就是测试
总结:
创建好Application和DeploymentGroup之后,跟配置管理工程师协定好往版本中添加的文件,然后按时间+项目+版本号的方式打包,并上传到S3上,然后代码的更新回退,由测试和开发同学在浏览器上就能完成,省的自己写代码更新平台了
上新项目的时候,也可以直接利用这个服务来实现,首次部署脚本是得写的复杂点,装上依赖软件和设置环境
用好之后,甚至能不用碰ssh工具就能在浏览器或者用代码把活干完