aws codesuit workshop
参考:
- Introduction to AWS Code Family
使用 AWS CodeCommit 作为 Git 存储库来存储我们的代码,并使用 AWS CodeArtifact 来管理软件包。我们将使用 AWS CodeBuild 编译 Java 应用程序,并使用 AWS CodeDeploy 将应用程序部署到 EC2 Web 服务器。AWS CodePipeline 将帮助协调整个过程。
环境配置
安装maven
sudo wget https://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
sudo sed -i s/\$releasever/6/g /etc/yum.repos.d/epel-apache-maven.repo
sudo yum install -y apache-maven
安装jdk
sudo amazon-linux-extras enable corretto8
sudo yum install -y java-1.8.0-amazon-corretto-devel
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64
export PATH=/usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64/jre/bin/:$PATH
确认安装
java -version
mvn -v
生成测试javaweb程序
mvn archetype:generate \
-DgroupId=com.wildrydes.app \
-DartifactId=unicorn-web-project \
-DarchetypeArtifactId=maven-archetype-webapp \
-DinteractiveMode=false
修改index.jsp
<p>This is my first version of the Wild Rydes application!</p>
创建codecomit仓库
创建并复制url
https://git-codecommit.cn-north-1.amazonaws.com.cn/v1/repos/web-project
配置git
git config --global user.name "<your name>"
git config --global user.email <your email>
添加remote
cd ./unicorn-web-project
git init -b main
git remote add origin https://git-codecommit.cn-north-1.amazonaws.com.cn/v1/repos/web-project
需要提前在iam获取https凭证
提交代码
git push -u origin main
Username for 'https://git-codecommit.cn-north-1.amazonaws.com.cn': xxxxxx
Password for 'https://xxxxxx@git-codecommit.cn-north-1.amazonaws.com.cn':
可以看到codecomimit上传成功
可以在当前项目下配置maven仓库,编辑setting.xml
<mirror>
<id>aliyun</id>
<mirrorOf>central</mirrorOf>
<name>aliyun-public</name>
<url>https://maven.aliyun.com/repository/public/</url>
</mirror>
编译maven项目
mvn compile
mvn package
mvn install
配置codebuild编译
创建s3
创建web-build项目
- 源选择codecommit,分支为main
- 目标选择s3存储桶,指定name和类型(zip)
- 托管环境为al2,创建服务角色保留默认值(每个build项目会创建一个单独的角色)
- Buildspec 下,将默认选项保留为Use a buildspec file,该文件将查找名为 buildspec.yml 的配置文件
- 默认将log发送到cw logs中
在项目根下创建buildspec.yml
version: 0.2
phases:
install:
runtime-versions:
java: corretto8
pre_build:
commands:
- echo Initializing environment
build:
commands:
- echo Build started on `date`
#使用项目配置,mvn -s settings.xml compile
- mvn compile
post_build:
commands:
- echo Build completed on `date`
- mvn package
artifacts:
files:
- target/unicorn-web-project.war
discard-paths: no
保存并推送
git add *
git commit -m "Adding buildspec.yml file"
git push -u origin main
开始build
进入build查看信息
- build logs,build日志
- phase details,分阶段信息
cw日志和控制台(只会显示1000条最新)相同
在目标s3中看到打包文件,即web-porject的war包
使用codedeploy部署
部署目标可以是 Amazon EC2、AWS Fargate、AWS Lambda或本地
目标:使用codedeploy部署war到安装tomcat的ec2上
逻辑:创建application和deployment group,设定deployment的source,将application部署在deployment group中
按照文档的说明,codedeploy分阶段进行部署,也就是ec2上的appspec生命周期钩子事件
注意:部署中的 Start、DownloadBundle、Install 和 End 事件无法脚本化
具体来说:
- ApplicationStop:下载app之前(这个脚本来自上一次成功的revision,首次部署没有appspec,所以不执行该阶段)
- DownloadBundle:预留,下载app到临时位置,
opt/codedeploy-agent/deployment-root/deployment-group-id/deployment-id/deployment-archive
- BeforeInstall:预安装
- Install:cd agent会将修订文件从临时位置复制到最终目标文件夹中,该阶段为预留无法运行脚本
- AfterInstall:配置app和修改权限
- ApplicationStart:启动服务
- ValidateService:验证部署
- BeforeBlockTraffic:从负载均衡器取消注册实例之前运行逻辑
- BlockTraffic:预留阶段,阻止 Internet 流量访问当前正在处理流量的实例
- AfterBlockTraffic:从负载均衡器取消注册实例之后运行逻辑
- BeforeAllowTraffic:将实例注册到负载均衡器之前运行逻辑
- AllowTraffic,预留,允许 Internet 流量在部署后访问实例
- AfterAllowTraffic:将实例注册到负载均衡器之后运行逻辑
install_dependencies.sh,配置httpd转发和tomcat
#!/bin/bash
sudo yum install tomcat -y
sudo yum -y install httpd
sudo cat << EOF > /etc/httpd/conf.d/tomcat_manager.conf
<VirtualHost *:80>
ServerAdmin root@localhost
ServerName app.wildrydes.com
DefaultType text/html
ProxyRequests off
ProxyPreserveHost On
ProxyPass / http://localhost:8080/unicorn-web-project/
ProxyPassReverse / http://localhost:8080/unicorn-web-project/
</VirtualHost>
EOF
start_server.sh
#!/bin/bash
sudo systemctl start tomcat.service
sudo systemctl enable tomcat.service
sudo systemctl start httpd.service
sudo systemctl enable httpd.service
stop_server.sh
#!/bin/bash
isExistApp=pgrep httpd
if [[ -n $isExistApp ]]; then
sudo systemctl stop httpd.service
fi
isExistApp=pgrep tomcat
if [[ -n $isExistApp ]]; then
sudo systemctl stop tomcat.service
fi
appspec.yml指定部署期间的执行逻辑,AppSpec 文件必须命名为appspec.yml并放置在源代码的根目录中
version: 0.0
os: linux
files:
- source: /target/unicorn-web-project.war
destination: /usr/share/tomcat/webapps/
hooks:
BeforeInstall:
- location: scripts/install_dependencies.sh
timeout: 300
runas: root
ApplicationStart:
- location: scripts/start_server.sh
timeout: 300
runas: root
ApplicationStop:
- location: scripts/stop_server.sh
timeout: 300
runas: root
build之后的目录自动配置appsec,需要在在buildspec.yml中添加
artifacts:
files:
- target/unicorn-web-project.war
- appspec.yml
- scripts/**/*
# 目录展平
discard-paths: no
当前目录
$ tree
.
├── appspec.yml
├── buildspec.yml
├── pom.xml
├── scripts
│ ├── install_dependencies.sh
│ ├── start_server.sh
│ └── stop_server.sh
└── src
└── main
├── resources
└── webapp
├── index.jsp
└── WEB-INF
└── web.xml
推送
git add *
git commit -m "Adding CodeDeploy files"
git push -u origin main
创建带有AWSCodeDeployRole
托管策略的codedeploy服务角色
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "codedeploy.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
创建codedeploy,选择ec2
创建部署组,即在什么地方部署,通过tag识别
在application中创建deployment,选择部署组和源
创建之后开始自动部署,此处的部署目标是AL2
部署的错误代码
- APPLICATION_MISSING:应用程序丢失。如果在创建部署之后但在启动之前删除应用程序,则很可能会引发此错误代码。
- DEPLOYMENT_GROUP_MISSING:部署组丢失。如果在创建部署之后但在启动之前删除了部署组,则很可能会引发此错误代码。
- HEALTH_CONSTRAINTS:部署在太多实例上失败,无法在指定的实例运行状况约束内成功部署。
- HEALTH_CONSTRAINTS_INVALID:无法在指定的实例运行状况约束内成功部署修订。
- IAM_ROLE_MISSING:无法访问服务角色。
- IAM_ROLE_PERMISSIONS:服务角色没有正确的权限。
- INTERNAL_ERROR:出现内部错误。
- NO_EC2_SUBSCRIPTION:主叫账户未订阅 Amazon EC2。
- NO_INSTANCES:没有指定实例,或者找不到实例。
- OVER_MAX_INSTANCES:超出最大实例数。
- THROTTLED:操作被限制,因为调用账户超出了一项或多项 Amazon 服务的限制。
- TIMEOUT:部署已超时。
- REVISION_MISSING:缺少修订 ID。如果在创建部署之后但在启动之前删除修订,则很可能会引发此错误代码。
可以在deployment中的event中看到具体的错误原因
报错信息显示CodeDeploy agent was not able to receive the lifecycle event. Check the CodeDeploy agent logs on your host and make sure the agent is running and can connect to the CodeDeploy server.
通常来说,创建部署组时可以选择使用ssm安装codedeploy agent,但是需要ec2的iam role,由于之前没有配置,导致ssm agent无法与aws service交互,所以codedeploy agent安装和响应失败
向ec2手动添加codedelpoyment权限并安装agent
wget https://aws-codedeploy-cn-north-1.s3.cn-north-1.amazonaws.com.cn/latest/install
chmod +x ./install
sudo ./install auto
sudo service codedeploy-agent start
sudo service codedeploy-agent status
重新部署,再次报错
The CodeDeploy agent did not find an AppSpec file within the unpacked revision directory at revision-relative path "appspec.yml".
The revision was unpacked to directory "/opt/codedeploy-agent/deployment-root/e2403155-2f1e-44f2-8da0-9a302e75d2d4/d-7LJEI5L3I/deployment-archive", and the AppSpec file was expected but not found at path "/opt/codedeploy-agent/deployment-root/e2403155-2f1e-44f2-8da0-9a302e75d2d4/d-7LJEI5L3I/deployment-archive/appspec.yml".
Consult the AWS CodeDeploy Appspec documentation for more information at http://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file.html
显示没有找到appsec.yml文件,由于我们之前修改了源文件(没有配置自动触发build),需要重新build之后重新部署
codepipeline集成
cloudwatch events检测codecommit更改
实际上是在event bus中创建一条规则(每个规则最多 5 个目标),检测codecommot的创建和更新自动触发pipeline
{
"source": ["aws.codecommit"],
"detail-type": ["CodeCommit Repository State Change"],
"resources": ["arn:aws-cn:codecommit:cn-north-1:xxxxxxxx:web-project"],
"detail": {
"event": ["referenceCreated", "referenceUpdated"],
"referenceType": ["branch"],
"referenceName": ["main"]
}
}
将之前创建的codemit,codebuild和codedeploy配置到pipeline中
修改index.jsp,便于查看效果
推送修改到codecommit中,自动build和deploy
git add *
git commit -m "Visual improvements to homepage"
git push -u origin main
增加stage
手动审批,使用sns的邮件订阅
更新codepipeline,在build之后添加新阶段(manual approve)
重新修改推送到commit
查看部署结果
构建container
构建容器Dockerfile
FROM public.ecr.aws/bitnami/tomcat:9.0
COPY ./target/unicorn-web-project.war /usr/local/tomcat/webapps/ROOT.war
创建buildspec_docker.yml
version: 0.2
phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
- docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com.cn/$IMAGE_REPO_NAME:$IMAGE_TAG
post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker image...
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com.cn/$IMAGE_REPO_NAME:$IMAGE_TAG
修改buildspec.yml
version: 0.2
phases:
[..]
artifacts:
files:
- target/unicorn-web-project.war
- appspec.yml
- scripts/**/*
- Dockerfile
- buildspec_docker.yml
discard-paths: no
需要在创建codedeploy时设置环境变量,和buildspec_docker.yml中相对应
指定buildspec name为 buildspec_docker.yml
部署serverless
参考:
- https://catalog.us-east-1.prod.workshops.aws/workshops/752fd04a-f7c3-49a0-a9a0-c9b5ed40061b/en-US/additional-exercises/serverlessdeploy