1 什么是DevOps

软件开发最高效的组织形式是“One Man Work”,只有一个人干活,写个小项目,从需求到开发,从测试到部署全部独立完成,非常高效。但随着业务的增长,项目开始逐渐变得庞大,变成团队,出现了分工,出现了产品经理、项目经理、开发、数据、测试、运维等等角色。这些角色间存在天然的工作目标上的矛盾。

安卓系统安装docker环境 安卓 运行docker_java

举个例子,对于运维来说,稳定压倒一切,新 Feature 越少越好。而对于研发来说,却希望能开发更多的功能。这种矛盾会导致大量的资源和时间的浪费。就像两匹马拉一辆车,如果马头向着的方向不一致,肯定是没法全速前进的。

DevOps 的理念就是希望能打破这种屏障,让研发(Development)和运维(Operations)一体化,让团队从业务需求出发,向着同一个目标前进。

字面意思上说 DevOps 是指“开发运维一体化”,即通过工具辅助开发完成运维的部分工作,减少成本。但深入理解了 DevOps 之后,你会发现 DevOps 其实是一种软件研发管理的思想,方法论,他追求的是一种没有隔阂的理想的研发协作的状态,可能涉及到的角色有开发、测试、产品、项目管理、运维等等。所以我们认为,为了帮助研发团队在保持质量的前提下提高交付效率的方法和方法论都隶属于 DevOps 的范畴。
比如 Google 提出的 5 个 DevOps 原则,这套原则中必须依赖于工具辅助的部分只有后两点,更多的则是对于开发组织形式的内省:

(1) 精简组织架构;
(2) 愿意承担一部分试错带来的损失;
(3) 分阶段地一小步一小步地进行转型;
(4) 最大化地利用工具和自动化流程;
(5) 对所有的过程和结果进行记录和分析。

所以 DevOps 不是简单的开发软件化,而是企业的学习能力不断提升的结果,将企业改造成敏捷应对的学习型组织,运用新的工具,优化组织架构和流程,不断地进行自我革命和创新的方式。工具是辅助,而非基础。

2 CI/CD

如果把我们一个项目从开发到部署结束,我们可以抽出一个过程,编码、打包、集成、测试、交付、部署。

安卓系统安装docker环境 安卓 运行docker_安卓 持续集成 docker_02

2.1 持续集成 (Continuous Integration)

持续集成(CI)可以帮助开发人员更加频繁地(有时甚至每天)将代码更改合并到共享分支或“主干”中。一旦开发人员对应用所做的更改被合并,系统就会通过自动构建应用并运行不同级别的自动化测试(通常是单元测试和集成测试)来验证这些更改,确保这些更改没有对应用造成破坏。这意味着测试内容涵盖了从类和函数到构成整个应用的不同模块。如果自动化测试发现新代码和现有代码之间存在冲突,CI 可以更加轻松地快速修复这些错误。

2.2 持续交付(Continuous Delivery)

完成 CI 中构建及单元测试和集成测试的自动化流程后,持续交付可自动将已验证的代码发布到存储库。为了实现高效的持续交付流程,务必要确保 CI 已内置于开发管道。持续交付的目标是拥有一个可随时部署到生产环境的代码库。

2.3 持续部署(Continuous Deployment)

对于一个成熟的 CI/CD 管道来说,最后的阶段是持续部署。作为持续交付——自动将生产就绪型构建版本发布到代码存储库——的延伸,持续部署可以自动将应用发布到生产环境。由于在生产之前的管道阶段没有手动门控,因此持续部署在很大程度上都得依赖精心设计的测试自动化。

安卓系统安装docker环境 安卓 运行docker_docker_03

3 SpringCloud持续集成解决方案

安卓系统安装docker环境 安卓 运行docker_docker_04

3.1 将代码上传到gitlab

安卓系统安装docker环境 安卓 运行docker_java_05

3.2 Jenkins整合gitlab

3.2.1 新建pipeline项目

安卓系统安装docker环境 安卓 运行docker_java_06

3.2.2 Webhook Trigger

(1) 配置webhook

安卓系统安装docker环境 安卓 运行docker_安卓系统安装docker环境_07

(2) 配置 Generic Webhook Trigger

安卓系统安装docker环境 安卓 运行docker_spring_08

安卓系统安装docker环境 安卓 运行docker_docker_09

安卓系统安装docker环境 安卓 运行docker_java_10

(3) 获取Jenkinsfile

安卓系统安装docker环境 安卓 运行docker_安卓系统安装docker环境_11

3.2.3 Gitlab 设置 WebHook

http://192.168.38.45:8000/jenkins/generic-webhook-trigger/invoke?token=springcloud

安卓系统安装docker环境 安卓 运行docker_java_12

3.2.4 生成拉取代码脚本

checkout([$class: 'GitSCM', branches: [[name: '*/develop']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '0543fa76-913f-4600-9a3b-30ac70c0fc86', url: 'git@192.168.38.45:root/springcloud-demo.git']]])

安卓系统安装docker环境 安卓 运行docker_java_13

3.2.5 编写Jenkinsfile

安卓系统安装docker环境 安卓 运行docker_spring_14

node  {  stage('拉取代码') {      checkout([$class: 'GitSCM', branches: [[name: '*/develop']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '0543fa76-913f-4600-9a3b-30ac70c0fc86', url: 'git@192.168.38.45:root/springcloud-demo.git']]])  }}

3.2.6 集成测试

安卓系统安装docker环境 安卓 运行docker_spring_15

安卓系统安装docker环境 安卓 运行docker_安卓 持续集成 docker_16

3.3 制作镜像,上传harbor

3.3.1 每个服务添加Dokcerfile

###############端口不同########################FROM java:8FROM openjdk:8-jdk-alpineARG JAR_FILECOPY ${JAR_FILE} app.jarEXPOSE 9000ENTRYPOINT ["java","-jar","/app.jar"]#FROM java:8FROM openjdk:8-jdk-alpineARG JAR_FILECOPY ${JAR_FILE} app.jarEXPOSE 8001ENTRYPOINT ["java","-jar","/app.jar"]#FROM java:8FROM openjdk:8-jdk-alpineARG JAR_FILECOPY ${JAR_FILE} app.jarEXPOSE 8002ENTRYPOINT ["java","-jar","/app.jar"]

安卓系统安装docker环境 安卓 运行docker_docker_17

3.3.2 Maven添加Dockerfile插件

com.spotifydockerfile-maven-plugin1.3.6${project.artifactId}target/${project.build.finalName}.jar

3.3.3 清除上次镜像脚本


安卓系统安装docker环境 安卓 运行docker_docker_18

3.3.4 Jenkins集成Harbor

(1) 创建Harbor凭证

安卓系统安装docker环境 安卓 运行docker_docker_19

(2)记录生成的ID

dd671782-a857-4884-8307-f1084aef867d
  • 1

安卓系统安装docker环境 安卓 运行docker_java_20

(3) 生成脚本

withCredentials([usernamePassword(credentialsId: 'dd671782-a857-4884-8307-f1084aef867d', passwordVariable: 'password', usernameVariable: 'username')]) {
    // some block}
  • 1
  • 2
  • 3

安卓系统安装docker环境 安卓 运行docker_java_21

3.3.5 修改Jenkinsfile

//=================定义公用信息===============//harbor地址def harborUrl = "192.168.38.100"//harbor仓库名称def harborRepository = "springcloud"//构建版本tagdef tag = "latest"//harbor凭证def harborAuth = "dd671782-a857-4884-8307-f1084aef867d"//定义函数,获取有效的服务def getValidServerList(){//需要构建的服务名   def buildServerNames = ['gateway-server','student-server']//所有服务列表   def springCloudServers= [['serverName':'gateway-server','serverPort':9000],                            ['serverName':'student-server','serverPort':8001],                            ['serverName':'teacher-server','serverPort':8002]]//返回结果集     def rs=[];for(int i=0;ifor(int j=0;jif("${buildServerNames[i]}" == "${springCloudServers[j].serverName}"){                  rs.add(springCloudServers[j])             }        }     }return rs;}node  {//有效的服务列表    def validServerList=getValidServerList()  stage('拉取代码') {      checkout([$class: 'GitSCM', branches: [[name: '*/develop']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '0543fa76-913f-4600-9a3b-30ac70c0fc86', url: 'git@192.168.38.45:root/springcloud-demo.git']]])  }  stage('制作镜像,上传harbor'){for(int i=0;i            echo "制作镜像: ${validServerList[i].serverName}"//服务名称           def serverName = "${validServerList[i].serverName}"//每次构建前,清除上次构建的镜像           sh "/usr/local/shell/jenkins/clearImages.sh  ${serverName}"//打包,构建镜像           sh "mvn -f ${serverName} clean package dockerfile:build"// 定义镜像名称           def imageName="${serverName}:${tag}"// 打tag           sh "docker tag ${imageName} ${harborUrl}/${harborRepository}/${imageName}"// 上传镜像            withCredentials([usernamePassword(credentialsId: "${harborAuth}", passwordVariable: 'password', usernameVariable: 'username')]) {//登录                sh "docker login -u ${username} -p ${password} ${harborUrl}"//上传                sh "docker push ${harborUrl}/${harborRepository}/${imageName}"            }          }  }}

3.3.6 集成测试

(1) 推develop分支代码到gitlab

(2) 触发流水线

安卓系统安装docker环境 安卓 运行docker_安卓系统安装docker环境_22

(3) 查看镜像

安卓系统安装docker环境 安卓 运行docker_spring_23

(4) 查看harbor

安卓系统安装docker环境 安卓 运行docker_spring_24

3.4 SonarQube代码审查

3.4.1 添加sonar配置文件

安卓系统安装docker环境 安卓 运行docker_安卓系统安装docker环境_25

(1) gateway-server

#SonarQube 实例名称,唯一sonar.projectKey=gateway-server#项目名称sonar.projectName=gateway-server#版本号sonar.projectVersion=1.0#指定扫描目录sonar.sources=.sonar.exclusions=**/test/**#jdk版本sonar.java.source=1.8sonar.java.target=1.8#扫描编写类的项目sonar.java.binaries=target/classes#编码格式sonar.sourceEncoding=UTF-8

(2) student-server

#SonarQube 实例名称,唯一sonar.projectKey=student-server#项目名称sonar.projectName=student-server#版本号sonar.projectVersion=1.0#指定扫描目录sonar.sources=.sonar.exclusions=**/test/**#jdk版本sonar.java.source=1.8sonar.java.target=1.8#扫描编写类的项目sonar.java.binaries=target/classes#编码格式sonar.sourceEncoding=UTF-8

(3) teacher-server

#SonarQube 实例名称,唯一sonar.projectKey=teacher-server#项目名称sonar.projectName=teacher-server#版本号sonar.projectVersion=1.0#指定扫描目录sonar.sources=.sonar.exclusions=**/test/**#jdk版本sonar.java.source=1.8sonar.java.target=1.8#扫描编写类的项目sonar.java.binaries=target/classes#编码格式sonar.sourceEncoding=UTF-8

3.4.2 修改Jenkinsfile

//=================定义公用信息===============//harbor地址def harborUrl = "192.168.38.100"//harbor仓库名称def harborRepository = "springcloud"//构建版本tagdef tag = "latest"//harbor凭证def harborAuth = "dd671782-a857-4884-8307-f1084aef867d"//定义函数,获取有效的服务def getValidServerList(){//需要构建的服务名   def buildServerNames = ['gateway-server','student-server']//所有服务列表   def springCloudServers= [['serverName':'gateway-server','serverPort':9000],                            ['serverName':'student-server','serverPort':8001],                            ['serverName':'teacher-server','serverPort':8002]]//返回结果集     def rs=[];for(int i=0;ifor(int j=0;jif("${buildServerNames[i]}" == "${springCloudServers[j].serverName}"){                  rs.add(springCloudServers[j])             }        }     }return rs;}node  {//有效的服务列表    def validServerList=getValidServerList()  stage('拉取代码') {      checkout([$class: 'GitSCM', branches: [[name: '*/develop']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '0543fa76-913f-4600-9a3b-30ac70c0fc86', url: 'git@192.168.38.45:root/springcloud-demo.git']]])  }  stage('制作镜像,上传harbor'){for(int i=0;i            echo "制作镜像: ${validServerList[i].serverName}"//服务名称           def serverName = "${validServerList[i].serverName}"//每次构建前,清除上次构建的镜像           sh "/usr/local/shell/jenkins/clearImages.sh  ${serverName}"//打包,构建镜像           sh "mvn -f ${serverName} clean package dockerfile:build"// 定义镜像名称           def imageName="${serverName}:${tag}"// 打tag           sh "docker tag ${imageName} ${harborUrl}/${harborRepository}/${imageName}"// 上传镜像            withCredentials([usernamePassword(credentialsId: "${harborAuth}", passwordVariable: 'password', usernameVariable: 'username')]) {//登录                sh "docker login -u ${username} -p ${password} ${harborUrl}"//上传                sh "docker push ${harborUrl}/${harborRepository}/${imageName}"            }          }  }  stage('代码审查'){//定义当前Jenkins的SonarQubeScanner工具       def scannerHome = tool 'sonarqube-scanner'for(int i=0;i//引用当前JenkinsSonarQube环境           withSonarQubeEnv('sonarqube') {                sh """cd ${validServerList[i].serverName}${scannerHome}/bin/sonar-scanner"""           }     }  }}

3.4.3 集成测试

(1) 推送develop代码到gitlab

(2) 查看流水线

安卓系统安装docker环境 安卓 运行docker_spring_26

(3) 查看SonarQube

安卓系统安装docker环境 安卓 运行docker_java_27

3.5 远程部署

3.5.1 环境概述

(1) jenkins服务、docker服务

#Jenkins
192.168.38.45#Dokcer
192.168.38.40
  • 1
  • 2
  • 3
  • 4

(2) 配置jenkins服务免密登录docker服务

#把Jenkins公钥发送到Dokcer服务
ssh-copy-id  192.168.38.40
  • 1
  • 2

(3) 配置 Publish over SSH

安卓系统安装docker环境 安卓 运行docker_安卓系统安装docker环境_28

安卓系统安装docker环境 安卓 运行docker_安卓系统安装docker环境_29

3.5.2 生成流水线脚本

安卓系统安装docker环境 安卓 运行docker_安卓 持续集成 docker_30

sshPublisher(publishers: [sshPublisherDesc(configName: 'docker_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
  • 1

安卓系统安装docker环境 安卓 运行docker_java_31

3.5.3 Dokcer服务器部署脚本

#! /bin/sh#接收外部参数,harbor地址、仓库名、项目名称、tag、端口harbor_url=$1harbor_repository=$2project_name=$3tag=$4port=$5imageName=$harbor_url/$harbor_repository/$project_name:$tagecho "$imageName"#查询容器是否存在,存在则删除containerId=`docker ps -a | grep -w ${project_name}:${tag}  | awk '{print $1}'`if [ "$containerId" !=  "" ] ; then#停掉容器    docker stop $containerId#删除容器    docker rm $containerIdecho "成功删除容器"fi#查询镜像是否存在,存在则删除imageId=`docker images | grep -w $project_name  | awk '{print $3}'`if [ "$imageId" !=  "" ] ; then#删除镜像    docker rmi -f $imageIdecho "成功删除镜像"fi# 登录Harbordocker login -u rosh -p Aa123456 $harbor_url# 下载镜像docker pull $imageName# 启动容器,挂载日志docker run -di -p $port:$port -v /usr/local/$harbor_repository/$project_name/logs:$project_name/logs  $imageNameecho "容器启动成功"

3.5.4 修改Jenkinsfile

//=================定义公用信息===============//harbor地址def harborUrl = "192.168.38.100"//harbor仓库名称def harborRepository = "springcloud"//构建版本tagdef tag = "latest"//harbor凭证def harborAuth = "dd671782-a857-4884-8307-f1084aef867d"//定义函数,获取有效的服务def getValidServerList(){//需要构建的服务名   def buildServerNames = ['gateway-server','student-server']//所有服务列表   def springCloudServers= [['serverName':'gateway-server','serverPort':9000],                            ['serverName':'student-server','serverPort':8001],                            ['serverName':'teacher-server','serverPort':8002]]//返回结果集     def rs=[];for(int i=0;ifor(int j=0;jif("${buildServerNames[i]}" == "${springCloudServers[j].serverName}"){                  rs.add(springCloudServers[j])             }        }     }return rs;}node  {//有效的服务列表    def validServerList=getValidServerList()  stage('拉取代码') {      checkout([$class: 'GitSCM', branches: [[name: '*/develop']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '0543fa76-913f-4600-9a3b-30ac70c0fc86', url: 'git@192.168.38.45:root/springcloud-demo.git']]])  }  stage('制作镜像,上传harbor'){for(int i=0;i            echo "制作镜像: ${validServerList[i].serverName}"//服务名称           def serverName = "${validServerList[i].serverName}"//每次构建前,清除上次构建的镜像           sh "/usr/local/shell/jenkins/clearImages.sh  ${serverName}"//打包,构建镜像           sh "mvn -f ${serverName} clean package dockerfile:build"// 定义镜像名称           def imageName="${serverName}:${tag}"// 打tag           sh "docker tag ${imageName} ${harborUrl}/${harborRepository}/${imageName}"// 上传镜像            withCredentials([usernamePassword(credentialsId: "${harborAuth}", passwordVariable: 'password', usernameVariable: 'username')]) {//登录                sh "docker login -u ${username} -p ${password} ${harborUrl}"//上传                sh "docker push ${harborUrl}/${harborRepository}/${imageName}"            }          }  }  stage('代码审查'){//定义当前Jenkins的SonarQubeScanner工具       def scannerHome = tool 'sonarqube-scanner'for(int i=0;i//引用当前JenkinsSonarQube环境           withSonarQubeEnv('sonarqube') {                sh """cd ${validServerList[i].serverName}${scannerHome}/bin/sonar-scanner"""           }     }  }    stage('远程部署'){for(int i=0;i           sshPublisher(publishers: [sshPublisherDesc(configName: 'docker_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/usr/local/shell/jenkins/springcloudDeploy.sh ${harborUrl} ${harborRepository} ${validServerList[i].serverName} ${tag} ${validServerList[i].serverPort}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])        }    }}

3.5.5 集成测试

(1) 推送develop分支代码到gitlab

(2) 查看流水线

安卓系统安装docker环境 安卓 运行docker_安卓 持续集成 docker_32

(3) 查看nacos

安卓系统安装docker环境 安卓 运行docker_安卓系统安装docker环境_33

(4) 查看docker服务器

安卓系统安装docker环境 安卓 运行docker_spring_34

安卓系统安装docker环境 安卓 运行docker_安卓系统安装docker环境_35

(5) 测试url

安卓系统安装docker环境 安卓 运行docker_docker_36

3.6 最终测试

3.6.1 部署全部服务

(1) 修改Jenkinsfile

安卓系统安装docker环境 安卓 运行docker_安卓 持续集成 docker_37

(2) 推送develop分支到gitlab(3) 查看流水线

安卓系统安装docker环境 安卓 运行docker_java_38

(4) 查看nacos

安卓系统安装docker环境 安卓 运行docker_安卓系统安装docker环境_39

(5) 访问接口

安卓系统安装docker环境 安卓 运行docker_docker_40

3.6.2 部署单个服务

(1) 修改Jenkinsfile

安卓系统安装docker环境 安卓 运行docker_安卓系统安装docker环境_41

(2) 修改老师接口

安卓系统安装docker环境 安卓 运行docker_docker_42

(3) 推送develop分支代码到gitlab(4) 查看流水线

安卓系统安装docker环境 安卓 运行docker_docker_43

(5) 再次访问老师接口

安卓系统安装docker环境 安卓 运行docker_java_44

作者:篮战丶