WYDevOps敏捷工具的架构设计(二)——部署图、参数配置及其扩展机制
在实际项目中,我们首先需要定义好ci-cd.yaml文件的内容,这个文件也是ci-cd-template.yaml文件的标准模板(ci-cd-template.yaml文件的内容必须是ci-cd.yaml文件的全量内容)。一般情况下,项目中配置好ci-cd-config.yaml文件,工具集读取ci-cd-config.yaml中的参数值覆盖模板文件_ci-cd-config.yaml文件中的参数
上篇文章描述了我们设计WYDevOps敏捷工具时关注的关键目标和部分核心策略。本篇文章将描述WYDevOps敏捷工具的顶层架构框图、参数配置及其扩展机制。
1. 定义WYDevOps敏捷工具
WYDevOps工具是一套可扩展的、支持多语言构建、打包、发布的纯Shell脚本集合。这套Shell脚本集合仅有一个程序入口,根据传入的参数控制模块运行的顺序和详细功能,其功能覆盖了项目构建/编译、docker镜像构建和推送、项目部署、离线安装包生成(仅本地模式有)等4个核心部分。各部分功能可独立运行,也可依序连续执行;并且各部分都提供了灵活的功能扩展机制。
对于离线安装包的安装,工具集中提供了Shell安装脚本和K8S服务安装器(Vue前端服务 + Java后端服务)。K8S服务安装器有较为完备的管理界面,可监测安装的服务的实时运行状态和资源使用情况(内存、CPU、硬盘),并提供服务参数修改、服务升级、服务重启、服务暂停、服务卸载等操作。
2. 系统部署图
上图是WYDevOps工具的用于K8S微服务场景下的顶层部署图。上图展示了工具支持的三种调用模式:本地调用模式、WebHook触发模式、JenkinsUI触发模式。所有调用模式本质上都是对工具集入口脚本(wydevops.sh)的调用。上图还展示了Jenkins流水线的阶段划分:代码拉取、项目编译/构建、docker镜像生成和推送、chart镜像生成和推送、项目部署。流水线样例代码如下:
pipeline { agent { label "${AGENT_LABEL}"} environment { AGENT_LABEL = 'maven1' JENKINS_SCRIPT = '${BUILD_SCRIPT_ROOT}/wydevops.sh' //此处填入从Gitee拉取源码时使用的用户ID GITHUB_USER_ID = '...' } parameters { string(name: 'GIT_PROJECT_NAME', defaultValue: 'JOB_NAME', description: 'gitee仓库名') //GITHUB_GROUP的取值由Gitee仓库决定。 choice(name: 'GITHUB_GROUP', choices: ['tech', 'java'], description: 'checkout git group') choice(name: 'GITHUB_BRANCH', choices: ['develop', 'master'], description: 'checkout git branch') choice(name: 'JOB_LANGUAGE', choices: ['java', 'golang', 'c++', 'python', 'shell', 'vue'], description: '') choice(name: 'ARCH_TYPES', choices: ['undefine', 'linux/amd64,linux/arm64', 'linux/amd64', 'linux/arm64'], description: '架构类型') choice(name: 'BUILD_TYPE', choices: ['single', 'double', 'base', 'business', 'all'], description: '构建类型') //AGENT_LABEL取值由Jenkins各节点的标签决定。 string(name: 'AGENT_LABEL', defaultValue: 'maven1', description: 'agent label') string(name: 'BUILD_PATH', defaultValue: './', description: '执行编译的路径') } stages { stage('Checkout') { options { timeout(time: 2, unit: 'MINUTES') } steps { dir("${GIT_PROJECT_NAME}") { echo "----Checkout----" git credentialsId: "${GITHUB_USER_ID}", url: "https://gitee.com/${GITHUB_GROUP}/${GIT_PROJECT_NAME}.git", branch: "${GITHUB_BRANCH}".split("/")[-1] } script{ currentBuild.result = 'SUCCESS' echo "${JOB_LANGUAGE}" } } } stage('Build') { when { allOf{ expression {currentBuild.result == 'SUCCESS'} } } steps { dir("${GIT_PROJECT_NAME}") { script { catchError { echo "Build with ${JENKINS_SCRIPT} ${JOB_LANGUAGE}" sh "${JENKINS_SCRIPT} -e -S 'build' -L ${JOB_LANGUAGE} -P ${BUILD_PATH} -B ${BUILD_TYPE} -A ${ARCH_TYPES} -M 'jenkins'" } } } script{ currentBuild.result = 'SUCCESS' echo "Build completed" } } } stage('Docker') { when { allOf{ expression {currentBuild.result == 'SUCCESS'} } } steps { dir("${GIT_PROJECT_NAME}") { script { catchError { sh "${JENKINS_SCRIPT} -e -S 'docker' -L ${JOB_LANGUAGE} -P ${BUILD_PATH} -B ${BUILD_TYPE} -A ${ARCH_TYPES} -M 'jenkins'" } echo 'finish creating docker images' currentBuild.result = 'SUCCESS' } } } } stage('Chart') { when { allOf{ expression {currentBuild.result == 'SUCCESS'} } } steps { dir("${GIT_PROJECT_NAME}") { script { catchError { sh "${JENKINS_SCRIPT} -e -S 'chart' -L ${JOB_LANGUAGE} -P ${BUILD_PATH} -B ${BUILD_TYPE} -A ${ARCH_TYPES} -M 'jenkins'" } echo 'finish creating chart image' currentBuild.result = 'SUCCESS' } } } } stage('Deploy') { when { allOf{ expression {currentBuild.result == 'SUCCESS'} } } steps { echo "Start deploy application ...${GIT_PROJECT_NAME}" dir("${GIT_PROJECT_NAME}") { script { catchError { sh "${JENKINS_SCRIPT} -e -S 'deploy' -L ${JOB_LANGUAGE} -P ${BUILD_PATH} -B ${BUILD_TYPE} -A ${ARCH_TYPES} -M 'jenkins'" } echo 'Deploy completed' } } } } } }
从上述流水线可以看出,除了Checkout阶段外,其他阶段的核心代码都是调用wydevops.sh脚本,仅是传入的参数不同。wydevops.sh脚本是工具集的入口脚本, 后续内容将围绕wydevops.sh的功能展开。
注意:工具集正常运行的前提:本地需要安装helm、docker。
3. 定义WYDevOps工具的全局参数
工具集接收全局参数的方式有两种:命令行参数和配置文件参数。
3.1 命令行参数如下(wydevops.sh --help):
参数说明: [开关量] -d, --debug 启用DEBUG模式输出测试信息 -e, --enableNotify 使能向外部接口发送CICD过程通知(需要配置-N参数) -h, --help 显示帮助信息 -i, --deleteImage 构建结束后删除使用过的Docker镜像。 -m, --multipleModel 指明要构建的目标项目是多模块项目。 -t, --template 忽略项目根目录下的Dockerfile系列文件,强制使用匹配的docker模板文件;等同 -T ture。 -v, --version 显示本脚本的版本 [可选项] -A, --archTypes string 要构建的Docker镜像的架构类型,默认值=undefine, 可选值有:\"linux/amd64,linux/arm64\",\"linux/amd64\",\"linux/arm64\",\"undefine\" -B, --buildType string 构建类型: single、base、business、double(=base + business)、all(=single + base + double)、none -C, --chartRepo string Chart镜像仓库信息, 格式:\"{repoName},{repoAccount},{repoPassword}\" -D, --dockerRepo string Docker镜像仓库信息, 格式:\"{repoName},{repoAccount},{repoPassword}\" -L, --language string 项目语言类型:java、python、vue、nodejs等 -M, --workMode string 工作模式:jenkins、local -N, --notify string 外部通知接口的地址 -O, --outArchTypes string 要导出的离线安装包的架构类型,默认值=linux/amd64,linux/arm64 -P, --buildPath string 构建目录,一般为目标工程的根目录或主模块目录(例如:Java多模块项目) -S, --buildStages string 构建阶段包括:build、docker、chart、deploy、all,有效值为:前四个阶段的有序组合,或all -T, --template string 是否忽略项目根目录下的Dockerfile系列文件,与开关量-t作用相同。有效取值:false或true -W, --workDir string 仅当workMode=local时,用于指定本脚本所在的目录
特别说明:工具集支持通过配置的通知接口向外发送CICD构建过程信息。
3.2 配置文件中的参数
配置文件参数不仅包含命令行参数,还包括更为详细的与各种构建场景相关的参数。例如,K8S相关的配置信息等。为了减轻配置复杂度,配置文件按复杂度(或配置能力)由强到弱依次为ci-cd.yaml、ci-cd-template.yaml、ci-cd-config.yaml。各种语言可进一步优化配置文件,甚至做到不需要配置文件的程度(例如,大部分Java微服务项目)。
4. 全局参数初始化流程
一般情况下,项目中配置好ci-cd-config.yaml文件,工具集读取ci-cd-config.yaml中的参数值覆盖模板文件_ci-cd-config.yaml文件中的参数。接着工具集再用_ci-cd-config.yaml文件中的参数覆盖模板文件_ci-cd-template.yaml文件中的同名参数。最后根据_ci-cd-template.yaml文件生成ci-cd.yaml文件。工具集会根据ci-cd.yaml文件中的参数,继续执行后续的CICD过程。实际流程如下:
如上图,项目也可直接提供ci-cd-template.yaml文件,该配置文件的优先级高于ci-cd-config.yaml文件。ci-cd.yaml文件中有三个配置节:templates、dockerFile、packages;ci-cd-config.yaml仅提供简单参数(非对象类参数)的配置功能,仅能配置templates节的参数;ci-cd-template.yaml提供了复杂参数(对象类参数)的配置功能,三个配置节的参数都能进行配置。
配置参数扩展性说明:各类语言项目或各种打包部署场景中需要配置参数各不相同,我们需要提供一种灵活的配置参数扩展机制。在实际项目中,我们首先需要定义好ci-cd.yaml文件的内容,这个文件也是ci-cd-template.yaml文件的标准模板(ci-cd-template.yaml文件的内容必须是ci-cd.yaml文件的全量内容)。ci-cd.yaml文件中dockerFile配置节的内容用于项目docker镜像的构建过程; packages配置节用于离线安装包的生成过程、部署模式(docker或k8s)相关配置过程。而templates配置节是为dockerFile和packages配置节中的配置参数提供参数值。举例说明(以Java项目为例):
上图为某个复杂的Java项目(简单的不需要配置文件)的ci-cd-template.yaml文件templates配置节的截图。可以看到serviceName参数被配置后,其后续参数的值中即可引语该参数的值(红框部分)。蓝框部分的参数在dockerFile配置节中使用了,如下图。注意yaml格式的列表参数的配置方式,见archTypes参数。
ci-cd-template.yaml文件的packages部分包含很多对象型参数的配置,我们参考上述说明,也可方便的在templates配置节为对象型参数的某个属性提供参数值,如下package配置节下的services配置字节的样例(packages[0].services[0]):
通过上面描述的机制,项目开发人员可定义出符合各种项目和部署场景的配置文件、配置模板文件。WYDevOps工具能提供这么强大的yaml文件配置能力,得益于其核心的脚本yaml-helper.sh脚本,该脚本提供了对yaml文件的强大操作能力。例如:
a. 读取某个yaml文件中某个配置节的第一行数据
b. 读取某个yaml文件中的某个配置节全部数据,并写人到另一个yaml文件中指定配置节下
c. 支持数组数据的读取
上面不厌其烦的讲述参数配置机制,主要是向读者介绍参数定义和扩展机制。希望读者掌握和理解参数配置的机制,然后根据自己的需要自定义符合自己语言或部署环境的配置文件。例如上述举例的配置中,有向K8S集群部署服务的相关配置,具体项目中我们使用的是helm工具进行K8S服务的发布和卸载。因此参数中对象类参数的格式是完全按照k8s资源定义文件(yaml)中对象参数定义格式进行定义的。不仅要授人与鱼,还要授人与渔!
本来想一章把架构设计写完,结果想多了。敬请期待下一章:《WYDevOps敏捷工具的架构设计(二)——语言级扩展机制》
更多推荐
所有评论(0)