Jenkins自动构建并滚动升级部署到ServiceStage的组件
- 场景一:使用Jenkins构建生成的是软件包,如Jar包,就使用脚本中的软件包部署场景,软件包部署会将构建出来的软件包上传到OBS桶中并升级ServiceStage组件。
- 场景二:使用Jenkins构建生成的是镜像包,就使用脚本中的镜像部署场景,镜像部署会将构建出来的镜像包上传到SWR镜像仓库中并升级ServiceStage组件。
本章节以配置流水线脚本中的实例为Jar包的场景进行说明。
在执行本操作之前,您需要已经在ServiceStage上完成了待操作组件的创建及部署。创建及部署组件,请参考使用容器部署方式基于界面配置创建组件。
创建GitLab凭证
使用具有GitLab代码仓库权限的账号密码在Jenkins中创建凭证,用于拉取GitLab代码。
- 在浏览器地址栏输入http://{安装Jenkins的Linux虚拟机IP}:8080,登录Jenkins。
- 选择“系统管理 > 系统配置”,在“配置”中选择“Gitlab”。
- 单击“Credentials”下方的“添加”,选择“Jenkins”。
- 配置GitLab账号密码,单击“添加”,保存配置。
- 选择“系统管理 > Manage Credentials”,查看配置的凭据。
唯一标识在配置流水线脚本中会用到。
创建流水线任务
- 在浏览器地址栏输入http://{安装Jenkins的Linux虚拟机IP}:8080,登录Jenkins。
- 单击“新建任务”。
- 输入任务名称,示例:test-upgrade,选择“流水线”,单击“确定”。
配置构建触发器
- 配置Jenkins构建触发器。
- 勾选“Build when a change is pushed to GitLab”,保存GitLab webhook URL(配置Gitlab webhook时需使用),然后单击右下角“高级”。
- 选择“Filter branches by regex ”,配置指定分支变更后触发构建任务,示例中的分支名称为main,单击右下角“Generate”生成Secret token并保存,在配置GitLab webhook时需使用。
- 配置GitLab webhook。
- 登录GitLab,进入代码仓库,示例中的仓库名称是“test”,选择settings中的“Webhooks”,URL和Secret token填写1获取到的GitLab webhook URL和Secret token。
- 取消勾选SSL verification的“Enable SSL verification”,单击“Add webhook”。
配置流水线脚本
流水线脚本是构建时运行的构建命令。
- 选择“流水线”页签,在下拉框选择“Pipeline script”。
- 配置如下所示流水线脚本,示例中使用的是构建jar包场景。
- 请使用您环境下的实际参数替换脚本中的参数变量。脚本参数说明,请参考表1。
- 流水线脚本运行时会调用upgrade.sh。脚本详细说明,请参考upgrade.sh脚本。
- 需要设置脚本文件upgrade.sh为可执行文件。
node { // 定义代码仓库地址,例如:http://10.95.156.58:8090/zmg/test.git def git_url = '{代码仓库地址}' // GitLab凭据id def credentials_id = '{GitLab凭据id}' // git代码仓库分支名称,例如:main def branch_name = '{git代码仓库分支名称}' // maven安装的可执行文件路径,例如 :/root/app/maven/apache-maven-3.8.6/bin/mvn def maven = '{maven安装的可执行文件路径}' // upgrade.sh脚本存放路径,例如:/root/jar/upgrade.sh def upgrade_shell = '{upgrade.sh脚本存放路径}' stage('Clone sources') { git branch: branch_name, credentialsId: credentials_id, url: git_url } stage('Build') { // 构建jar包 sh "'$maven' clean package -Dmaven.test.failure.ignore=true -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true" } stage('upgrade') { // 执行脚本,使用构建上传到obs的jar包升级ServiceStage组件,超时时间5分钟 sh "timeout 300s '$upgrade_shell'" } }
表1 流水线脚本参数说明 参数
是否必须
参数类型
描述
git_url
是
String
GitLab代码仓库地址。
credentials_id
是
String
使用账号密码配置的GitLab凭据id,请参考创建GitLab凭证。
branch_name
是
String
GitLab代码仓库分支名称。
maven
是
String
maven安装的可执行文件路径,例如:/root/app/maven/apache-maven-3.8.6/bin/mvn。
upgrade_shell
是
String
upgrade.sh脚本在Jenkins所在虚拟机上存放的路径,例如:/root/jar/upgrade.sh。脚本内容,请参考upgrade.sh脚本。
- 执行构建并验证构建结果,请参考构建验证。
upgrade.sh脚本
请使用您环境下的实际参数替换脚本中的参数变量。
#!/bin/bash # 项目id project_id='{项目id}' # 应用id application_id='{应用id}' # 组件id component_id='{组件id}' # 分批信息 rolling_release_batches=1 # 部署类型 deploy_type="package" ### 方法简要说明: ### 1. 查找一个字符串,如下述代码里面的key所示。如果没找到,则直接返回defaultValue。 ### 2. 查找最近的冒号(:),找到后则冒号后的内容即为值的内容。 ### 3. 如果有多个同名key,只打印第一个value。 ### ### 4. params: json, key, defaultValue function getJsonValuesByAwk() { awk -v json="$1" -v key="$2" -v defaultValue="$3" 'BEGIN{ foundKeyCount = 0 pos = match(json, "\""key"\"[ \\t]*?:[ \\t]*"); if (pos == 0) {if (foundKeyCount == 0) {print defaultValue;} exit 0;} ++foundKeyCount; start = 0; stop = 0; layer = 0; for (i = pos + length(key) + 1; i <= length(json); ++i) { lastChar = substr(json, i - 1, 1) currChar = substr(json, i, 1) if (start <= 0) { if (lastChar == ":") { start = currChar == " " ? i + 1: i; if (currChar == "{" || currChar == "[") { layer = 1; } } } else { if (currChar == "{" || currChar == "[") { ++layer; } if (currChar == "}" || currChar == "]") { --layer; } if ((currChar == "," || currChar == "}" || currChar == "]") && layer <= 0) { stop = currChar == "," ? i : i + 1 + layer; break; } } } if (start <= 0 || stop <= 0 || start > length(json) || stop > length(json) || start >= stop) { if (foundKeyCount == 0) {print defaultValue;} exit 0; } else { print substr(json, start, stop-start); } }' } #查询组件信息 function getComponentInfo() { # 查询组件信息 component_details=`hcloud ServiceStage ShowComponentInfo/v3 --project_id="$project_id" --application_id="$application_id" --component_id="$component_id"` # 打印组件信息 echo "$component_details" # 获取组件当前的名称 test_name=`getJsonValuesByAwk "$component_details" "name" "defaultValue"` lenj=${#test_name} component_name=${test_name:1:lenj-2} echo "name : $component_name" data_time=$(date +%Y.%m%d.%H%M) seconds=$(date +%S) component_version="${data_time}${seconds:1:1}" echo "version: $component_version" } # 镜像部署使用场景 function swr_image_upgrade() { # 项目打包后生成的镜像:镜像名称:版本名称 machine_image_name='java-test:v1' # 上传到swr的镜像仓库路径 swr_image_url='{镜像仓库地址}/{组织名称}/{镜像名称}:{版本}' # AK 用于登录swr镜像仓库 AK='BMCKUPO9HZMI6BRDJGBD' #SWR登录密钥,用于登录SWR镜像仓库 SK='{SWR登录密钥}' # SWR镜像仓库地址 swr_url='{SWR镜像仓库地址}' #region名称 region="{region名称}" echo "upload image to swr" docker tag "$machine_image_name" "$swr_image_url" login_secret=`printf "$AK" | openssl dgst -binary -sha256 -hmac "$SK" | od -An -vtx1 | sed 's/[ \n]//g' | sed 'N;s/\n//'` login_result=`docker login -u "$region"@"$AK" -p "$login_secret" "$swr_url"` # 打印登录swr镜像仓库结果 echo "$login_result" push_result=`docker push "$swr_image_url"` # 打印推送镜像结果 #echo "$push_result" logout_result=`docker logout "$swr_url"` # 打印退出登录swr镜像仓库的结果 echo "$logout_result" # 清除所有的历史记录,历史记录中可能会存在swr登录密钥信息,可以使用该命令清理所有的历史记录 #history -c echo "upgrade component" action_result=`hcloud ServiceStage ModifyComponent/v3 --project_id="$project_id" --application_id="$application_id" --component_id="$component_id" --version="$component_version" --runtime_stack.name="Docker" --runtime_stack.type="Docker" --source.kind="image" --source.storage="swr" --source.url="$swr_image_url" --name="$component_name" --deploy_strategy.rolling_release.batches=$rolling_release_batches --deploy_strategy.type="RollingRelease" ` } # jar包部署使用场景 function obs_jar_upgrade() { # obsutil安装的可执行文件绝对路径 obsutil='/root/tools/obsutil/obsutil_linux_amd64_5.4.6/obsutil' # obs桶名 bucket='obs://{obs桶名}' echo "upload jar to obs" # 将项目下构建生成的jar包上传到obs obs_result=`"$obsutil" cp ./target/*.jar "$bucket"` # 打印上传结果 echo "$obs_result" # 上传到obs的jar包链接 obs_jar_url='obs://{obs桶名}/{Jar包名称}' echo "upgrade component" action_result=`hcloud ServiceStage ModifyComponent/v3 --project_id="$project_id" --application_id="$application_id" --component_id="$component_id" --version="$component_version" --runtime_stack.name="OpenJDK8" --runtime_stack.type="Java" --source.kind="package" --source.storage="obs" --source.url="$obs_jar_url" --name="$component_name" --deploy_strategy.rolling_release.batches=$rolling_release_batches --deploy_strategy.type="RollingRelease" ` } # 每隔15秒查询一次job状态,直到job完成 function waitDeployFinish() { sleep 10s id="$1" leni=${#id} id=${id:1:leni-2} echo "job_id= $id" job_status="" while [[ "$job_status" != "SUCCEEDED" ]]; do job_status_result=`hcloud ServiceStage ShowJobDetail/v2 --project_id="$project_id" --job_id="$id"` job_status=`getJsonValuesByAwk "$job_status_result" "EXECUTION_STATUS" "defaultValue"` lenj=${#job_status} job_status=${job_status:1:lenj-2} echo "$job_status" if [[ "$job_status" != "RUNNING" && "$job_status" != "SUCCEEDED" ]]; then echo '部署失败' echo "$job_status_result" return fi sleep 15s done echo '部署成功' } function upgradeTask() { if [[ "$deploy_type" == "package" ]]; then obs_jar_upgrade elif [[ "$deploy_type" == "image" ]]; then swr_image_upgrade else return fi # 打印升级组件的结果 echo "$action_result" # 获取结果中的job_id job_id=`getJsonValuesByAwk "$action_result" "job_id" "defaultValue"` echo "$job_id" # 等待升级完成 waitDeployFinish "$job_id" } function main() { getComponentInfo upgradeTask } main
脚本参数说明
参数 |
是否必须 |
参数类型 |
描述 |
---|---|---|---|
region |
是 |
String |
Region名称。获取方法,请参考参数值获取。 |
project_id |
是 |
String |
项目ID。获取方法,请参考参数值获取。 |
application_id |
是 |
String |
应用ID。获取方法,请参考参数值获取。 |
component_id |
是 |
String |
组件ID。获取方法,请参考参数值获取。 |
rolling_release_batches |
是 |
int |
分批部署批次。 |
deploy_type |
是 |
String |
部署类型。
|
obsutil |
否 |
String |
当使用软件包部署如jar包部署时为必选参数,上传jar包到obs的工具安装的绝对路径。例如:/root/tools/obsutil/obsutil_linux_amd64_5.4.6/obsutil。 |
bucket |
否 |
String |
当使用软件包部署时为必选参数,上传到obs的桶路径,格式为obs://{桶名称},例如:obs://obs-mzc。 |
obs_jar_url |
否 |
String |
当使用软件包部署时为必选参数。软件包上传obs后的链接,格式为obs://{桶名}/{软件包名}。例如,obs://obs-mzc/spring-demo-0.0.1-SNAPSHOT.jar。 |
machine_image_name |
否 |
String |
当使用镜像部署时为必选参数,Jenkins打包构建后生成的镜像,格式为:{镜像名称}:{版本},例如:java-test:v1。 |
swr_image_url |
否 |
String |
当使用镜像部署时为必选参数,上传到SWR镜像仓库的镜像包路径,格式为:{镜像仓库地址}/{组织名称}/{镜像包名称}:{版本},其中SWR镜像仓库地址格式为:swr.{区域所属项目名称}.myhuaweicloud.com。 |
AK |
否 |
String |
当使用镜像部署时为必选参数。访问密钥ID,即AK,用于登录SWR镜像仓库。获取方法,请参考访问密钥。 |
SK |
否 |
String |
当使用镜像部署时为必选参数。与访问密钥ID(AK)结合使用的密钥,即SK,用于登录SWR镜像仓库。获取方法,请参考访问密钥。 |
login_secret |
否 |
String |
当使用镜像部署时为必选参数。SWR镜像仓库的登录密钥,用于登录SWR镜像仓库。执行如下命令,返回的结果就是登录密钥: printf "{AK}" | openssl dgst -binary -sha256 -hmac "{SK}" | od -An -vtx1 | sed 's/[ \n]//g' | sed 'N;s/\n//' {AK}、{SK}请替换为已获取到的AK、SK的值。 |
swr_url |
否 |
String |
当使用镜像部署时为必选参数。SWR镜像仓库地址,格式为:swr.{区域所属项目名称}.myhuaweicloud.com |