WYDevOps敏捷工具的架构设计(二)——部署图、参数配置及其扩展机制

      上篇文章描述了我们设计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敏捷工具的架构设计(二)——语言级扩展机制》

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值