Jenkinsfile 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. properties([
  2. parameters([
  3. [$class: 'ChoiceParameter',
  4. choiceType: 'PT_SINGLE_SELECT',
  5. description: '选择要部署 API',
  6. name: 'modulePrefix',
  7. randomName: 'choice-parameter-5631314439613978',
  8. script: [
  9. $class: 'GroovyScript',
  10. fallbackScript: [
  11. classpath: [],
  12. sandbox: true,
  13. script:
  14. 'return[\'Could not get Env\']'
  15. ],
  16. script: [
  17. classpath: [],
  18. sandbox: true,
  19. script:
  20. 'return["java"]'
  21. ]
  22. ]
  23. ],
  24. [$class: 'CascadeChoiceParameter',
  25. choiceType: 'PT_SINGLE_SELECT',
  26. description: '选择要部署的项目',
  27. name: 'module',
  28. randomName: 'choice-parameter-5631314456178619',
  29. referencedParameters: 'modulePrefix',
  30. script: [
  31. $class: 'GroovyScript',
  32. fallbackScript: [
  33. classpath: [],
  34. sandbox: true,
  35. script:
  36. 'return[\'Could not get Environment from Env Param\']'
  37. ],
  38. script: [
  39. classpath: [],
  40. sandbox: true,
  41. script:
  42. 'return["storlead-ai-api"]'
  43. ]
  44. ]
  45. ]
  46. ])
  47. ])
  48. pipeline {
  49. options {
  50. timestamps()
  51. }
  52. environment {
  53. GROUPID = readMavenPom().getGroupId()//com.storlead
  54. ARTIFACTID = readMavenPom().getArtifactId()//sp-project
  55. VERSION = readMavenPom().getVersion()
  56. }
  57. // 参数
  58. parameters {
  59. choice(
  60. name: 'profile',
  61. choices: ['prod'],
  62. description: '选择要部署的配置文件'
  63. )
  64. }
  65. agent any
  66. stages {
  67. stage('处理参数') {
  68. steps {
  69. script {
  70. echo "处理参数"
  71. script {
  72. //服务器配置
  73. MODULE_PREFIX = "${params.modulePrefix}"
  74. SERVER_SSH_PORT = 53023
  75. SERVER_HOST = "node1.storlead.com"
  76. SWARM_INIT_REPLICAS_NUM = 1
  77. //服务配置
  78. API_PORT = 9200
  79. API_REMOTE_DEBUG_PORT = 9201
  80. API_NAMESPACE_RESTFUL = "${params.module}"
  81. //DOCKER配置
  82. DOCKER_REGISTRY = "reg-aliyun"
  83. DOCKER_HOST = "registry.cn-shenzhen.aliyuncs.com"
  84. //Docker私服登陆url https://registry-vpc.cn-shenzhen.aliyuncs.com
  85. DOCKER_LOGIN_REGISTRY = "https://${DOCKER_HOST}"
  86. BUILD_PREFIX = "storlead-huawei"
  87. VERSION = "1.0"
  88. //镜像完整名称 registry-vpc.cn-shenzhen.aliyuncs.com/storlead/sp-project-management-prod:1.0
  89. DOCKER_IMG_NAME = "${DOCKER_HOST}/${BUILD_PREFIX}/${ARTIFACTID}-${params.module}-${params.profile}:${VERSION}"
  90. //镜像名 storlead/sp-project-management-prod:1.0
  91. IMG_NAME = "${BUILD_PREFIX}/${ARTIFACTID}-${params.module}-${params.profile}:${VERSION}"
  92. PUSH_DOCK_IMG = true
  93. SERVER_HOST_NAME = "test1"
  94. echo "为指定 module 设定对应 服务器及端口"
  95. echo "处理 ${params.module} 项目"
  96. if (params.modulePrefix == "java") {
  97. echo "---- gpt"
  98. script {
  99. if (params.profile == "test") {
  100. SWARM_INIT_REPLICAS_NUM = 1
  101. SERVER_HOST = "test1.storlead.com"
  102. API_PORT = 8780
  103. API_REMOTE_DEBUG_PORT = 8781
  104. SERVER_HOST_NAME = "test1"
  105. } else if (params.profile == "prod") {
  106. SWARM_INIT_REPLICAS_NUM = 1
  107. SERVER_HOST = "110.41.82.21"
  108. API_PORT = 8780
  109. API_REMOTE_DEBUG_PORT = 8781
  110. SERVER_HOST_NAME = "node1"
  111. }
  112. }
  113. }
  114. echo "处理MODULE_NAMESPACE_RESTFUL"
  115. //把 module 名 从 sp-xxx 变成 xxx 也就是 项目 的 namespace
  116. if (API_NAMESPACE_RESTFUL == "storlead-ai-api") {
  117. API_NAMESPACE_RESTFUL = "/router/rest"
  118. }
  119. echo "处理镜像推送"
  120. }
  121. }
  122. }
  123. }
  124. stage('Maven 编译') {
  125. when {
  126. environment name: 'modulePrefix', value: 'java'
  127. }
  128. agent {
  129. docker {
  130. image 'maven:3-amazoncorretto-17' // 会自己下载
  131. //让docker 使用 host 宿主机的 m2仓库 使用root用户来运行 以让指定的~/.m2/config/setting.xml 阿里加速下载maven 依赖生效
  132. args '-v /app:/app:z -v $HOME/.m2:/root/.m2:z -u root'
  133. reuseNode true
  134. }
  135. }
  136. steps {
  137. echo "编译 API 代码"
  138. sh "mvn clean package -U -am -pl ${params.module} -P${params.profile} -Dmaven.test.skip=true"
  139. }
  140. }
  141. // 项目打包到镜像并推送到镜像仓库
  142. stage('构建Docker镜像') {
  143. when {
  144. environment name: 'modulePrefix', value: 'java'
  145. }
  146. steps {
  147. echo "构建Dcoker镜像-------------------"
  148. script {
  149. docker.withRegistry(DOCKER_LOGIN_REGISTRY, DOCKER_REGISTRY) {
  150. BASE_IMAGE = 'eclipse-temurin:17'
  151. //获取最新的镜像底包
  152. sh "docker pull ${BASE_IMAGE}"
  153. sh """
  154. echo '
  155. FROM ${BASE_IMAGE}
  156. COPY ${params.module}/target/${params.module}.jar app.jar
  157. EXPOSE ${API_PORT}
  158. EXPOSE ${API_REMOTE_DEBUG_PORT}
  159. HEALTHCHECK --interval=1m --timeout=10s CMD curl -f http://localhost:${API_PORT}/${API_NAMESPACE_RESTFUL}/actuator
  160. ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom", "-Djava.awt.headless=true","-Dspring.profiles.active=${params.profile}", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:${API_REMOTE_DEBUG_PORT}","-jar","/app.jar"]' > Dockerfile
  161. docker build -t ${DOCKER_IMG_NAME} .
  162. """
  163. sh "docker push ${DOCKER_IMG_NAME}"
  164. }
  165. }
  166. }
  167. }
  168. stage('启动服务') {
  169. when {
  170. environment name: 'modulePrefix', value: 'java'
  171. }
  172. steps {
  173. withCredentials([
  174. usernamePassword(credentialsId: 'storleadHW', usernameVariable: 'usernameHW', passwordVariable: 'passwordHW'),
  175. usernamePassword(credentialsId: 'storlead', usernameVariable: 'username', passwordVariable: 'password'),
  176. usernamePassword(credentialsId: 'reg-aliyun', usernameVariable: 'aliUsername', passwordVariable: 'aliPassword'),
  177. ]) {
  178. script {
  179. echo "启动服务"
  180. def remote = [:]
  181. remote.name = "${SERVER_HOST}"
  182. remote.host = "${SERVER_HOST}"
  183. remote.port = 53023
  184. remote.user = username
  185. remote.password = password
  186. remote.allowAnyHosts = true
  187. //因为使用 docker swarm 发布 只能在 manage node 执行部署
  188. if (params.profile == "dev") {
  189. remote.port = 22
  190. remote.user = "root"
  191. }
  192. if (params.profile == "prod") {
  193. remote.port = 22
  194. remote.user = "root"
  195. remote.user = usernameHW
  196. remote.password = passwordHW
  197. }
  198. if (PUSH_DOCK_IMG) {
  199. //docker 认证
  200. sshCommand remote: remote, command: "docker login -u ${aliUsername} -p ${aliPassword} ${DOCKER_LOGIN_REGISTRY}"
  201. //如果选择推送才使用远程的版本 如果不选择推送到远程则直接运行本机刚打包的镜像版本即可
  202. sshCommand remote: remote, command: "docker pull ${DOCKER_IMG_NAME}"
  203. }
  204. sh """
  205. echo '
  206. version: "3.7"
  207. services:
  208. ${ARTIFACTID}-${params.module}-${params.profile}:
  209. image: ${DOCKER_IMG_NAME}
  210. deploy:
  211. replicas: ${SWARM_INIT_REPLICAS_NUM}
  212. placement:
  213. constraints:
  214. - 'node.hostname == ${SERVER_HOST_NAME}'
  215. update_config:
  216. parallelism: 1
  217. delay: 1m
  218. restart_policy:
  219. condition: on-failure
  220. # 最多连续重试3次如果仍然失败则放弃重试
  221. max_attempts: 3
  222. healthcheck:
  223. test: ["CMD", "curl", "-f", "http://localhost:${API_PORT}/router/rest/actuator"]
  224. interval: 1m
  225. timeout: 5s
  226. retries: 3
  227. start_period: 30s
  228. environment:
  229. - "TZ=Asia/Shanghai"
  230. - "SPRING_PROFILES_ACTIVE=${params.profile}"
  231. volumes:
  232. - /app:/app
  233. ports:
  234. - "${API_PORT}:${API_PORT}"
  235. - "${API_REMOTE_DEBUG_PORT}:${API_REMOTE_DEBUG_PORT}"
  236. networks:
  237. - vonedao_net
  238. extra_hosts:
  239. - "test1.storlead.com:172.18.194.168"
  240. - "node1:110.41.82.21"
  241. - "node2:110.41.174.46"
  242. - "node3:121.37.226.174"
  243. networks:
  244. vonedao_net:
  245. external: true
  246. ' > ${ARTIFACTID}-${params.module}-${params.profile}-stack.yml
  247. """
  248. // if (params.profile =="dev") {
  249. // sh "docker stack deploy -c ${ARTIFACTID}-${params.profile}-stack.yml ${ARTIFACTID}-${params.profile}"
  250. // sh "docker ps -f name=${ARTIFACTID} -q | xargs --no-run-if-empty docker container stop"
  251. // sh "docker container ls -a -fname=${ARTIFACTID} -q | xargs -r docker container rm"
  252. // sh "docker run -d --restart=always -p ${API_PORT}:${API_PORT} -p ${API_REMOTE_DEBUG_PORT}:${API_REMOTE_DEBUG_PORT} -v /app:/app --name ${ARTIFACTID} ${DOCKER_IMG_NAME}"
  253. // } else {
  254. // 全部都以swarm 模式启动
  255. sshPut remote: remote, from: "${ARTIFACTID}-${params.module}-${params.profile}-stack.yml", into: "/docker/sp/${ARTIFACTID}-${params.module}-${params.profile}-stack.yml"
  256. sshCommand remote: remote, command: "docker stack deploy --resolve-image=always --with-registry-auth -c /docker/sp/${ARTIFACTID}-${params.module}-${params.profile}-stack.yml ${params.module}-${params.profile}"
  257. // }
  258. }
  259. }
  260. }
  261. }
  262. }
  263. }