stages.k8s-prod.groovy 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. sharedLibsPath = "${env.WORKSPACE}/sharedLibs"
  2. backup_destination = '/var/jenkins_home/backups'
  3. backup_targetFile = 'javaDockerImage.tar'
  4. BACKUP_MAX = 2
  5. generateFullImageUri = {Map DOCKER, String base_branch, String BUILD_NUMBER ->
  6. return "${DOCKER.registry}/${DOCKER.image}:${base_branch}-${BUILD_NUMBER}"
  7. }
  8. generateImageName = {Map DOCKER, String base_branch, String BUILD_NUMBER ->
  9. return "${DOCKER.image}:${base_branch}-${BUILD_NUMBER}"
  10. }
  11. def processString(String content) {
  12. return content
  13. }
  14. def buildJar(Object SERVICE, String path='projdir') {
  15. echo "-----> Building project package ..."
  16. dir(path) {
  17. if (SERVICE.module != null && SERVICE.module.trim())
  18. sh "$MAVEN_HOME/bin/mvn clean package -pl \"${SERVICE.module}\" -am -Dmaven.test.skip=true"
  19. else
  20. sh "$MAVEN_HOME/bin/mvn clean package -Dmaven.test.skip=true"
  21. }
  22. return path
  23. }
  24. @Deprecated
  25. def backup_jar(Object SERVICE, String srcPath, String workingPath='projdir') {
  26. echo "-----> Backup project artifact ..."
  27. def module = SERVICE.module == null ? '' : (SERVICE.module[-1] == '/' ? SERVICE.module : SERVICE.module + '/')
  28. path = "${backup_destination}/${JOB_NAME}/${BUILD_NUMBER}/target"
  29. sh """if [ -d ${path} ];
  30. then
  31. echo \"${path} already exists\"
  32. else
  33. mkdir -p ${path}
  34. fi
  35. cp ${workingPath}/${module}${srcPath} ${path}
  36. """
  37. }
  38. def cleanDockerImage(String dockerImgName) {
  39. sh "docker rmi ${dockerImgName}"
  40. }
  41. def backupDockerImage(String dockerImgName) {
  42. echo "-----> Backup artifact(docker image : ${dockerImgName}) ..."
  43. path = "${backup_destination}/${JOB_NAME}/${BUILD_NUMBER}"
  44. sh """
  45. docker save ${dockerImgName} -o ${backup_targetFile}
  46. if [ -d ${path} ];
  47. then
  48. echo \"${path} already exists\"
  49. else
  50. mkdir -p ${path}
  51. mv ${backup_targetFile} ${path}
  52. fi
  53. """
  54. }
  55. def backupK8sConfigs(String[] files2backup) {
  56. path = "${backup_destination}/${JOB_NAME}/${BUILD_NUMBER}/k8s"
  57. sh """if [ -d ${path} ];
  58. then
  59. echo \"${path} already exists!\"
  60. else
  61. mkdir -p ${path}
  62. fi
  63. """
  64. for(file in files2backup) {
  65. sh "cp -r ${file} ${path}"
  66. }
  67. }
  68. def cleanJar(String path='projdir') {
  69. echo "-----> Cleaning project package ..."
  70. dir(path){
  71. sh '$MAVEN_HOME/bin/mvn clean'
  72. }
  73. return path
  74. }
  75. def generateDockerfile(Object SERVICE, String pathOfDockerfile='projdir') {
  76. def module = SERVICE.module == null ? '' : (SERVICE.module[-1] == '/' ? SERVICE.module : SERVICE.module + '/')
  77. echo "-----> Generating Dockerfile: ${pathOfDockerfile}/Dockerfile ..."
  78. sh """cat > ${pathOfDockerfile}/Dockerfile<<EOF
  79. FROM openjdk:17-alpine as final
  80. ADD ${module}target/${SERVICE.jar} /app/target/${SERVICE.jar}
  81. EOF
  82. """
  83. return pathOfDockerfile
  84. }
  85. def buildDockerImage(Object SERVICE, Object DOCKER, String base_branch, projDir='projdir', String filter2Remove=null) {
  86. def imageUri = generateFullImageUri(DOCKER, base_branch, BUILD_NUMBER)
  87. echo "-----> Building docker image: ${imageUri} ..."
  88. dir(projDir) {
  89. docker.withRegistry("http://${DOCKER.registry}", "${DOCKER.push_credentialId}") {
  90. def imageName = generateImageName(DOCKER, base_branch, BUILD_NUMBER)
  91. def image = docker.build(imageName)
  92. image.push()
  93. sh "docker rmi ${imageName}"
  94. if(filter2Remove != null)
  95. sh "docker image prune --filter label=${filter2Remove} -f"
  96. }
  97. }
  98. return imageUri
  99. }
  100. def restoreDockerImage(Object DOCKER, String workspace, String base_branch, String rollbackBuildNumber) {
  101. dir(workspace) {
  102. imageUri = generateFullImageUri(DOCKER, base_branch, rollbackBuildNumber)
  103. sh "docker load -i ${backup_targetFile}"
  104. docker.withRegistry("http://${DOCKER.registry}", "${DOCKER.push_credentialId}") {
  105. def image = docker.image(imageUri)
  106. image.push()
  107. }
  108. }
  109. return imageUri
  110. }
  111. // 灰度发布: 部署Canary版本pod
  112. def deployCanaryWithConfigmapEnvOnly(SERVICE, K3S, String base_branch, String[] args, namespace='default') {
  113. print "loading ${sharedLibsPath}/k3sUtil.groovy ..."
  114. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  115. def version = 'canary'
  116. def configmap_env_name = k3sUtils.applyCanaryConfigMapEnv(SERVICE, K3S, version, "./configmap-env.ini", namespace)
  117. print "get configmap_env_name: ${configmap_env_name}"
  118. def java_args = '['
  119. args.each{item -> java_args += "\"$item\", "}
  120. java_args = java_args[0..-2] + ']'
  121. def kvs = [:]
  122. kvs.put('<namespace>', namespace)
  123. kvs.put('<service_name>', SERVICE.name)
  124. kvs.put('<service_version>', SERVICE.version)
  125. kvs.put('<gray_version>', version)
  126. kvs.put('<release>', base_branch)
  127. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  128. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  129. kvs.put('<docker_image>', imageUri)
  130. kvs.put('<java_args>', java_args)
  131. if (SERVICE.health != null)
  132. kvs.put('<service_health>', SERVICE.health)
  133. kvs.put('<configmap_env_name>', configmap_env_name)
  134. def canaryDeploy = k3sUtils.generateCanaryDeployment(kvs, version, "./deployment.yaml")
  135. k3sUtils.applyDeployment(K3S, canaryDeploy)
  136. if (!fileExists('./service.yaml')) {
  137. print "skip applying service. './service.yaml' file does not exists"
  138. return
  139. }
  140. def canaryService = k3sUtils.generateCanaryService(kvs, version, './service.yaml')
  141. k3sUtils.applyService(K3S, canaryService)
  142. }
  143. def deployWithConfigmapEnvOnly(SERVICE, K3S, String base_branch, String[] args, configmapEnv="./configmap-env.ini", namespace='default') {
  144. print "loading ${sharedLibsPath}/k3sUtil.groovy..."
  145. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  146. def configmap_env_name = k3sUtils.applyConfigMapEnv(SERVICE, K3S, configmapEnv, namespace)
  147. def java_args = '['
  148. args.each{item -> java_args += "\"$item\","}
  149. java_args = java_args[0..-2] + ']'
  150. kvs = [:]
  151. kvs.put('<service_name>', SERVICE.name)
  152. kvs.put('<service_version>', SERVICE.version)
  153. kvs.put('<release>', base_branch)
  154. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  155. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  156. kvs.put('<docker_image>', imageUri)
  157. kvs.put('<java_args>', java_args)
  158. if (SERVICE.health != null)
  159. kvs.put('<service_health>', SERVICE.health)
  160. kvs.put('<configmap_env_name>', configmap_env_name)
  161. k3sUtils.generateDeployment(kvs, 'deployment.yaml')
  162. k3sUtils.applyDeployment(K3S, 'deployment.yaml')
  163. k3sUtils.generateService(kvs, 'service.yaml')
  164. k3sUtils.applyService(K3S, 'service.yaml')
  165. }
  166. def deployWithConfigmapEnvOnly_rollback(SERVICE, K3S, String rollbackBuildNumber, String[] args, configmapEnv="./configmap-env.ini", namespace='default') {
  167. print "loading ${sharedLibsPath}/k3sUtil.groovy..."
  168. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  169. dir("${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}/k8s") {
  170. def configmap_env_name = k3sUtils.applyConfigMapEnv(SERVICE, K3S, configmapEnv, namespace)
  171. def java_args = '['
  172. args.each{item -> java_args += "\"$item\","}
  173. java_args = java_args[0..-2] + ']'
  174. kvs = [:]
  175. kvs.put('<service_name>', SERVICE.name)
  176. kvs.put('<service_version>', SERVICE.version)
  177. kvs.put('<release>', BASE_BRANCH)
  178. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  179. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  180. kvs.put('<docker_image>', imageUri)
  181. kvs.put('<java_args>', java_args)
  182. if (SERVICE.health != null)
  183. kvs.put('<service_health>', SERVICE.health)
  184. kvs.put('<configmap_env_name>', configmap_env_name)
  185. k3sUtils.generateDeployment(kvs, 'deployment.yaml')
  186. k3sUtils.applyDeployment(K3S, 'deployment.yaml')
  187. k3sUtils.generateService(kvs, 'service.yaml')
  188. k3sUtils.applyService(K3S, 'service.yaml')
  189. }
  190. }
  191. def deployWithConfigmapEnvOnly2nd(SERVICE, K3S, String base_branch, String[] args, configmapEnv="./configmap-env.ini", namespace='default') {
  192. print "loading ${sharedLibsPath}/k3sUtil.groovy..."
  193. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  194. def configmap_env_name = k3sUtils.applyConfigMapEnv(SERVICE, K3S, configmapEnv, namespace)
  195. def java_args = '['
  196. args.each{item -> java_args += "\"$item\","}
  197. java_args = java_args[0..-2] + ']'
  198. kvs = [:]
  199. kvs.put('<service_name>', SERVICE.name)
  200. kvs.put('<service_version>', SERVICE.version)
  201. kvs.put('<release>', base_branch)
  202. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  203. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  204. kvs.put('<docker_image>', imageUri)
  205. kvs.put('<java_args>', java_args)
  206. if (SERVICE.health != null)
  207. kvs.put('<service_health>', SERVICE.health)
  208. kvs.put('<configmap_env_name>', configmap_env_name)
  209. k3sUtils.generateDeployment(kvs, 'deployment2.yaml')
  210. k3sUtils.applyDeployment(K3S, 'deployment2.yaml')
  211. k3sUtils.generateService(kvs, 'service2.yaml')
  212. k3sUtils.applyService(K3S, 'service2.yaml')
  213. }
  214. def deployWithConfigmapEnvOnly2nd_rollback(SERVICE, K3S, String rollbackBuildNumber, String[] args, configmapEnv="./configmap-env.ini", namespace='default') {
  215. print "loading ${sharedLibsPath}/k3sUtil.groovy..."
  216. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  217. dir("${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}/k8s") {
  218. def configmap_env_name = k3sUtils.applyConfigMapEnv(SERVICE, K3S, configmapEnv, namespace)
  219. def java_args = '['
  220. args.each{item -> java_args += "\"$item\","}
  221. java_args = java_args[0..-2] + ']'
  222. kvs = [:]
  223. kvs.put('<service_name>', SERVICE.name)
  224. kvs.put('<service_version>', SERVICE.version)
  225. kvs.put('<release>', BASE_BRANCH)
  226. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  227. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  228. kvs.put('<docker_image>', imageUri)
  229. kvs.put('<java_args>', java_args)
  230. if (SERVICE.health != null)
  231. kvs.put('<service_health>', SERVICE.health)
  232. kvs.put('<configmap_env_name>', configmap_env_name)
  233. k3sUtils.generateDeployment(kvs, 'deployment2.yaml')
  234. k3sUtils.applyDeployment(K3S, 'deployment2.yaml')
  235. k3sUtils.generateService(kvs, 'service2.yaml')
  236. k3sUtils.applyService(K3S, 'service2.yaml')
  237. }
  238. }
  239. def deployWithConfigmaps_rollback(SERVICE, K3S, String rollbackBuildNumber, String[] args, configmapEnv="./configmap-env.ini", configmapConf="./configmap") {
  240. print "loading ${sharedLibsPath}/k3sUtil.groovy..."
  241. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  242. dir("${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}/k8s") {
  243. def configmap_env_name = k3sUtils.applyConfigMapEnv(SERVICE, K3S, configmapEnv)
  244. def configmap_conf_name = k3sUtils.applyConfigMapConfig(SERVICE, K3S, configmapConf)
  245. def java_args = '['
  246. args.each{item -> java_args += "\"$item\","}
  247. java_args = java_args[0..-2] + ']'
  248. kvs = [:]
  249. kvs.put('<service_name>', SERVICE.name)
  250. kvs.put('<service_version>', SERVICE.version)
  251. kvs.put('<release>', BASE_BRANCH)
  252. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  253. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  254. kvs.put('<docker_image>', imageUri)
  255. kvs.put('<java_args>', java_args)
  256. if (SERVICE.health != null)
  257. kvs.put('<service_health>', SERVICE.health)
  258. kvs.put('<configmap_env_name>', configmap_env_name)
  259. kvs.put('<configmap_conf_name>', configmap_conf_name)
  260. k3sUtils.generateDeployment(kvs, 'deployment.yaml')
  261. k3sUtils.applyDeployment(K3S, 'deployment.yaml')
  262. k3sUtils.generateService(kvs, 'service.yaml')
  263. k3sUtils.applyService(K3S, 'service.yaml')
  264. }
  265. }
  266. // 灰度发布: 部署Canary版本pod
  267. def deployCanaryWithConfigmaps(SERVICE, K3S, String base_branch, String[] args, namespace = "default") {
  268. print "loading ${sharedLibsPath}/k3sUtil.groovy..."
  269. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  270. def version = 'canary'
  271. def configmap_env_name = k3sUtils.applyCanaryConfigMapEnv(SERVICE, K3S, version, "./configmap-env.ini", namespace)
  272. def configmap_conf_name = k3sUtils.applyCanaryConfigMapConfig(SERVICE, K3S, version, "./configmap")
  273. def java_args = '['
  274. args.each{item -> java_args += "\"$item\","}
  275. java_args = java_args[0..-2] + ']'
  276. def kvs = [:]
  277. kvs.put('<namespace>', namespace)
  278. kvs.put('<service_name>', SERVICE.name)
  279. kvs.put('<service_version>', SERVICE.version)
  280. kvs.put('<gray_version>', version)
  281. kvs.put('<release>', base_branch)
  282. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  283. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  284. kvs.put('<docker_image>', imageUri)
  285. kvs.put('<java_args>', java_args)
  286. if (SERVICE.health != null)
  287. kvs.put('<service_health>', SERVICE.health)
  288. kvs.put('<configmap_env_name>', configmap_env_name)
  289. kvs.put('<configmap_conf_name>', configmap_conf_name)
  290. def canaryDeploy = k3sUtils.generateCanaryDeployment(kvs, version, "./deployment.yaml")
  291. print 'Generated ${canaryDeploy}. skip applying deployment.yaml'
  292. k3sUtils.applyDeployment(K3S, canaryDeploy)
  293. if (!fileExists('./service.yaml')) {
  294. print "skip applying service. './service.yaml' file does not exists"
  295. return
  296. }
  297. def canaryService = k3sUtils.generateCanaryService(kvs, version, './service.yaml')
  298. k3sUtils.applyService(K3S, canaryService)
  299. }
  300. def deployWithConfigmaps(SERVICE, K3S, String base_branch, String[] args, configmapEnv="./configmap-env.ini", configmapConf="./configmap") {
  301. print "loading ${sharedLibsPath}/k3sUtil.groovy..."
  302. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  303. def configmap_env_name = k3sUtils.applyConfigMapEnv(SERVICE, K3S, configmapEnv)
  304. def configmap_conf_name = k3sUtils.applyConfigMapConfig(SERVICE, K3S, configmapConf)
  305. def java_args = '['
  306. args.each{item -> java_args += "\"$item\","}
  307. java_args = java_args[0..-2] + ']'
  308. kvs = [:]
  309. kvs.put('<service_name>', SERVICE.name)
  310. kvs.put('<service_version>', SERVICE.version)
  311. kvs.put('<release>', base_branch)
  312. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  313. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  314. kvs.put('<docker_image>', imageUri)
  315. kvs.put('<java_args>', java_args)
  316. if (SERVICE.health != null)
  317. kvs.put('<service_health>', SERVICE.health)
  318. kvs.put('<configmap_env_name>', configmap_env_name)
  319. kvs.put('<configmap_conf_name>', configmap_conf_name)
  320. k3sUtils.generateDeployment(kvs, 'deployment.yaml')
  321. k3sUtils.applyDeployment(K3S, 'deployment.yaml')
  322. k3sUtils.generateService(kvs, 'service.yaml')
  323. k3sUtils.applyService(K3S, 'service.yaml')
  324. }
  325. def deployWithConfigmaps2nd(SERVICE, K3S, String base_branch, String[] args, configmapEnv="./configmap-env.ini", configmapConf="./configmap") {
  326. print "loading ${sharedLibsPath}/k3sUtil.groovy..."
  327. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  328. def configmap_env_name = k3sUtils.applyConfigMapEnv(SERVICE, K3S, configmapEnv)
  329. def configmap_conf_name = k3sUtils.applyConfigMapConfig(SERVICE, K3S, configmapConf)
  330. def java_args = '['
  331. args.each{item -> java_args += "\"$item\","}
  332. java_args = java_args[0..-2] + ']'
  333. kvs = [:]
  334. kvs.put('<service_name>', SERVICE.name)
  335. kvs.put('<service_version>', SERVICE.version)
  336. kvs.put('<release>', base_branch)
  337. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  338. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  339. kvs.put('<docker_image>', imageUri)
  340. kvs.put('<java_args>', java_args)
  341. if (SERVICE.health != null)
  342. kvs.put('<service_health>', SERVICE.health)
  343. kvs.put('<configmap_env_name>', configmap_env_name)
  344. kvs.put('<configmap_conf_name>', configmap_conf_name)
  345. k3sUtils.generateDeployment(kvs, 'deployment2.yaml')
  346. k3sUtils.applyDeployment(K3S, 'deployment2.yaml')
  347. k3sUtils.generateService(kvs, 'service2.yaml')
  348. k3sUtils.applyService(K3S, 'service2.yaml')
  349. }
  350. def execute(CONFIG, base_branch, closures=[:]) { //配置文件,当前分支,自定义闭包
  351. stage('source code check out') {
  352. println "loading ${sharedLibsPath}/gitUtil.groovy..." //打印信息共享库路径,变量路径,存储加载的录像本身地址,脚本名称
  353. def gitUtils = load "${sharedLibsPath}/gitUtil.groovy" //load方法加载对象,赋值给gitUtils
  354. COMMIT_SHA = closures.GITCLONE == null ? gitUtils.clone(CONFIG.git, base_branch) : closures.GITCLONE() //定义变量,为空则调用git配置中git仓库信息branch当前分支,不空调用自定义闭包
  355. }
  356. stage("docker image build") {
  357. def projDir = 'projdir' //定义变量,项目目录
  358. if (closures.BUILDJAR != null) //检查是否自定义闭包,有就使用,没有就使用默认方法
  359. projDir = closures.BUILDJAR()
  360. else
  361. projDir = buildJar(CONFIG.service, projDir) //default
  362. if (closures.BACKUP != null)
  363. closures.BACKUP()
  364. if (closures.GENERATEDOCKERFILE != null)
  365. projDir = closures.GENERATEDOCKERFILE()
  366. else
  367. projDir = generateDockerfile(CONFIG.service) //default
  368. if (closures.BUILDIMAGE != null)
  369. imageUri = closures.BUILDIMAGE()
  370. else
  371. imageUri = buildDockerImage(CONFIG.service, CONFIG.docker, base_branch, projDir)
  372. if (closures.CLEANJAR != null)
  373. closures.CLEANJAR()
  374. else
  375. cleanJar(projDir)
  376. }
  377. stage("notify when build") {
  378. //notifywhenbuild(base_branch, CONFIG.service.name)
  379. }
  380. stage("apply K8S ConfigMaps && Deployment") {
  381. if (closures.K3SDEPLOY != null) {
  382. closures.K3SDEPLOY()
  383. return
  384. }
  385. }
  386. }
  387. // 灰度发布: 部署stable版本pod
  388. def deployStableWithConfigmaps(SERVICE, K3S, String BASE_BRANCH, String rollbackBuildNumber, String[] args, namespace='default') {
  389. print "loading ${sharedLibsPath}/k3sUtil.groovy..."
  390. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  391. def release = 'stable'
  392. dir("${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}/k8s") {
  393. def configmap_env_name = k3sUtils.applyCanaryConfigMapEnv(SERVICE, K3S, release, "./configmap-env.ini", namespace)
  394. def configmap_conf_name = k3sUtils.applyCanaryConfigMapConfig(SERVICE, K3S, release, "./configmap")
  395. def java_args = '['
  396. args.each{item -> java_args += "\"$item\","}
  397. java_args = java_args[0..-2] + ']'
  398. def kvs = [:]
  399. kvs.put('<namespace>', namespace)
  400. kvs.put('<service_name>', SERVICE.name)
  401. kvs.put('<service_version>', SERVICE.version)
  402. kvs.put('<gray_version>', release)
  403. kvs.put('<release>', BASE_BRANCH)
  404. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  405. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  406. kvs.put('<docker_image>', imageUri)
  407. kvs.put('<java_args>', java_args)
  408. if (SERVICE.health != null)
  409. kvs.put('<service_health>', SERVICE.health)
  410. kvs.put('<configmap_env_name>', configmap_env_name)
  411. kvs.put('<configmap_conf_name>', configmap_conf_name)
  412. def stableDeploy = k3sUtils.generateCanaryDeployment(kvs, release, './deployment.yaml')
  413. k3sUtils.applyDeployment(K3S, stableDeploy)
  414. if (!fileExists('./service.yaml')) {
  415. print "skip applying service. './service.yaml' file does not exists"
  416. return
  417. }
  418. def stableService = k3sUtils.generateCanaryService(kvs, release, './service.yaml')
  419. k3sUtils.applyService(K3S, stableService)
  420. }
  421. }
  422. // 灰度发布: 部署stable版本pod
  423. def deployStableWithConfigmapEnvOnly(SERVICE, K3S, String base_branch, String[] args, namespace='default') {
  424. print "loading ${sharedLibsPath}/k3sUtil.groovy ..."
  425. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  426. def release = 'stable'
  427. dir("${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}/k8s") {
  428. def configmap_env_name = k3sUtils.applyCanaryConfigMapEnv(SERVICE, K3S, release, "./configmap-env.ini", namespace)
  429. def java_args = '['
  430. args.each{item -> java_args += "\"$item\", "}
  431. java_args = java_args[0..-2] + ']'
  432. def kvs = [:]
  433. kvs.put('<namespace>', namespace)
  434. kvs.put('<service_name>', SERVICE.name)
  435. kvs.put('<service_version>', SERVICE.version)
  436. kvs.put('<gray_version>', release)
  437. kvs.put('<release>', base_branch)
  438. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  439. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  440. kvs.put('<docker_image>', imageUri)
  441. kvs.put('<java_args>', java_args)
  442. if (SERVICE.health != null)
  443. kvs.put('<service_health>', SERVICE.health)
  444. kvs.put('<configmap_env_name>', configmap_env_name)
  445. def canaryDeploy = k3sUtils.generateCanaryDeployment(kvs, release, "./deployment.yaml")
  446. k3sUtils.applyDeployment(K3S, canaryDeploy)
  447. if (!fileExists(canaryService)) {
  448. print "skip applying service. './service.yaml' file does not exists"
  449. return
  450. }
  451. def canaryService = k3sUtils.generateCanaryService(kvs, release, './service.yaml')
  452. k3sUtils.applyService(K3S, canaryService)
  453. }
  454. }
  455. // 灰度发布: 升级stable版本
  456. def upgrade_stable(Object CONFIG, String base_branch, String rollbackBuildNumber, closures = [:]) {
  457. // stage('find latest Canary version') {
  458. // def basePath = "${backup_destination}/${JOB_NAME}"
  459. // def baseDir = new File(basePath)
  460. // if (!baseDir.exists() || !baseDir.isDirectory()) {
  461. // error "Path does not exist or is not a directory: ${basePath}"
  462. // return
  463. // }
  464. // latestDir = baseDir.listFiles()
  465. // ?.findAll { f ->
  466. // f.isDirectory() && (f.name ==~ /^\d+$/)
  467. // }
  468. // ?.max { it.lastModified() }
  469. // rollbackBuildNumber = latestDir.name
  470. // }
  471. // 2. docker image build
  472. stage("docker image restore") {
  473. def envFile = new File("${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}/env")
  474. def lines = envFile.readLines()
  475. COMMIT_SHA = lines[0]
  476. BASE_BRANCH = lines[1]
  477. def path = "${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}"
  478. print("restore docker image from rollbackBuildNo. #${rollbackBuildNumber}")
  479. // imageUri = restoreDockerImage(CONFIG.docker, path, BASE_BRANCH, rollbackBuildNumber)
  480. imageUri = generateFullImageUri(CONFIG.docker, BASE_BRANCH, rollbackBuildNumber)
  481. print "restore docker image: ${imageUri}"
  482. // cleanDockerImage(imageUri)
  483. }
  484. stage("apply Release(Canary:${rollbackBuildNumber}) K8S ConfigMaps && Deployment") {
  485. if (closures.K3SDEPLOY != null)
  486. closures.K3SDEPLOY()
  487. }
  488. stage("Post Execution Script") {
  489. // print "Clear rollback workspace"
  490. // 清理rollback工作目录
  491. // dir("${backup_destination}/${JOB_NAME}") {
  492. // sh "rm -rf *@tmp"
  493. // }
  494. }
  495. }
  496. // 灰度发布: 升级canary版本
  497. def upgrade(Object CONFIG, String base_branch, String[] k8sBackupFiles, closures=[:]) {
  498. stage('source code check out') {
  499. println "loading ${sharedLibsPath}/gitUtil.groovy..."
  500. def gitUtils = load "${sharedLibsPath}/gitUtil.groovy"
  501. COMMIT_SHA = closures.GITCLONE == null ? gitUtils.clone(CONFIG.git, base_branch) : closures.GITCLONE()
  502. if (closures.POST_GITCLONE != null)
  503. closures.POST_GITCLONE()
  504. }
  505. stage("docker image build") {
  506. def projDir = 'projdir'
  507. if (closures.BUILDJAR != null)
  508. projDir = closures.BUILDJAR()
  509. else
  510. projDir = buildJar(CONFIG.service, projDir) //default
  511. if (closures.GENERATEDOCKERFILE != null)
  512. projDir = closures.GENERATEDOCKERFILE()
  513. else
  514. projDir = generateDockerfile(CONFIG.service) //default
  515. if (closures.BUILDIMAGE != null)
  516. imageUri = closures.BUILDIMAGE()
  517. else
  518. imageUri = buildDockerImage(CONFIG.service, CONFIG.docker, base_branch, projDir)
  519. if (closures.CLEANJAR != null)
  520. closures.CLEANJAR()
  521. else
  522. cleanJar(projDir)
  523. if (k8sBackupFiles != null && k8sBackupFiles.size() > 0) {
  524. backupDockerImage(imageUri)
  525. envFile = new File("${backup_destination}/${JOB_NAME}/${BUILD_NUMBER}/env")
  526. envFile << "${COMMIT_SHA}\n"
  527. envFile << "${base_branch}\n"
  528. }
  529. cleanDockerImage(imageUri)
  530. }
  531. stage("apply K8S ConfigMaps && Deployment") {
  532. if (k8sBackupFiles != null && k8sBackupFiles.size() > 0)
  533. backupK8sConfigs(k8sBackupFiles)
  534. if (closures.K3SDEPLOY != null) {
  535. closures.K3SDEPLOY()
  536. return
  537. }
  538. }
  539. stage("notify after build") {
  540. if (closures.BUILDINFO != null) {
  541. def buildInfo = closures.ALLCHANGES()
  542. if (buildInfo.length() > 800) {
  543. buildInfo = buildInfo.substring(buildInfo.length() - 800)
  544. }
  545. def title = closures.BUILDINFO()+"正在发布"
  546. def content = "变更:"+buildInfo+"\\n"+
  547. "分支:"+base_branch+"\\n"+
  548. "版本:"+BUILD_NUMBER+"\\n"
  549. sendGroupNotification(title, content)
  550. }
  551. }
  552. stage("Post Execution Script") {
  553. print "Clear older backup version"
  554. // 清理旧的备份
  555. dir("${backup_destination}/${JOB_NAME}") {
  556. sh """
  557. save_file=`ls -ltr | tail -${BACKUP_MAX} | awk '{print \$NF}'`
  558. ls | grep -v "\$save_file" | xargs rm -rf
  559. """
  560. }
  561. }
  562. }
  563. def rollback(CONFIG, rollbackBuildNumber, closures=[:]) {
  564. // 1. restore specified version
  565. path = "${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}"
  566. if (fileExists(path)) {
  567. stage('source code check out') {
  568. print("souce code check out. Skipped!")
  569. }
  570. envFile = new File("${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}/env")
  571. def lines = envFile.readLines()
  572. COMMIT_SHA = lines[0]
  573. BASE_BRANCH = lines[1]
  574. // 2. docker image build
  575. stage("docker image build") {
  576. print("restore docker image from rollbackNo. #${rollbackBuildNumber}")
  577. imageUri = restoreDockerImage(CONFIG.docker, path, BASE_BRANCH, rollbackBuildNumber)
  578. cleanDockerImage(imageUri)
  579. }
  580. // 3. k8s configmap && deployment apply
  581. stage("apply K8S ConfigMaps && Deployment") {
  582. if (closures.K3SDEPLOY != null)
  583. closures.K3SDEPLOY()
  584. }
  585. stage("Post Execution Script") {
  586. print "Clear rollback workspace"
  587. // 清理rollback工作目录
  588. dir("${backup_destination}/${JOB_NAME}") {
  589. sh "rm -rf *@tmp"
  590. }
  591. }
  592. }
  593. }
  594. def sendGroupNotification(String title, String content) {
  595. WECHAT_ROBOT_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=92059925-97db-4830-8438-1514a246a143"
  596. stage('Send Message') {
  597. // 构建要发送的企业微信消息
  598. def message = """
  599. {
  600. "msgtype": "text",
  601. "text": {
  602. "content": "【${title}】\n${content}"
  603. }
  604. }
  605. """
  606. // 发送消息到企业微信
  607. sh """
  608. curl -X POST -H 'Content-Type: application/json' -d '${message}' ${WECHAT_ROBOT_URL}
  609. """
  610. }
  611. }
  612. return this