天天看点

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

文章导读

  • 本文仅代表作者的个人观点;
  • 本文的内容仅限于技术探讨,不能作为指导生产环境的素材;
  • 本文素材是红帽公司产品技术和手册;

一、实现Devops的金箍

容器在工具层面实现Devops。

这句话不是我说的,Gartner说的。

但说出这句话,和实现Devops全工具链落地之间的差距,与造出原子弹和E=MC2公式的差距,实不逞多让。

那么,从容器到Devops工具链,都需要啥呢?

之前我的一遍文章已经提到过,至少需要六大金刚。

Openshift:PaaS解决方案

Gogs: Go写的本地github

Jenkins/Jenkins Slave Pods

Nexus :工件管理器,能够解决本地缓存构建依赖项。

SonarQube:开源代码分析工具,它可以分析常见编程错误的源代码

Skopeo:镜像复制工具

理论上,七个葫芦一颗心,才能打败妖精。

同样,六大金刚协同工作,才能实现Devops。

那么,将这六大金刚协调起来,打通devops任督二脉的金箍圈是啥?

一个完整、全面的Jenkins Pipeline。

任何没有试验和代码的技术文章都是耍流氓,闲言少叙,看干货!

二、实验环境介绍

我的试验环境集成了六大金刚,五个工具分别在不同的Openshift项目中(Skopeo被做到了Jenkins Slave pod image中):

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

试验最最终实现效果:

  • 构建了一个pipeline,将openshift-tasks应用程序交付到生产环境中。
  • 构建过程集成了Gogs、Nexus、SonarQube和S2I构建。
  • 最终部署到生产中使用蓝绿色部署。
  • 将新版本的应用程序推送到Gogs时,可以配置要触发的pipeline。
  • 将pipeline与OpenShift Web控制台集成。

最终Pipeline的全流程:

  • 设置OpenShift开发(包括测试)和生产项目
  • 在Jenkins建立一个pipeline
  • 查看Gogs的源代码
  • 使用Nexus作为Maven代理从源代码构建应用程序
  • 将标记x.x-Buildnumber添加到构建的image
  • 运行单元测试
  • 运行代码覆盖测试
  • 将x.x标记添加到image
  • 将容器image保存到Nexus Docker注册表
  • 使用蓝绿部署将应用程序部署到生产环境
  • 停止pileline,等待批准
  • 批准后,将路由切换到新部署

展示效果:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

应用在向生产环境部署之前,询问是否批准:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

如果同意切换到生产:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

则应用部署到生产:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

而最终部署的应用的web展示:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

六大金刚协同工作图:

在比较简单的模式下:开发人员将代码push到git(gogs)中,Jenkins触发Tasks-Dev中的dc,触发构建,构建成功后,将构建好image推送到docker registry中。然后,镜像在Tasks-Dev中通过dc进行部署,然后给新的镜像打label,最后将镜像部署到Tasks-Prod中:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

在本实验中,开发人员将代码推送到git中,Jenkins Pipeline启动Jenkins Slave Pod,进行构建(构建成war包),然后war包被推到SonarQube中进行代码分析,分析通过以后,war包被推送到Nexus中:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

三、环境准备:创建dev和prod两个项目

我们在OpenShift中,针对一个应用tasks,创建dev和prod两个项目,模拟开发和生产。

创建xyz-tasks-dev80 OpenShift项目来保存openshift-tasks应用程序的开发版本:

  • 设置Jenkins的权限,以便能够操作xyz-tasks-dev项目中的对象。
  • 使用jboss-eap70-openshift:1.6 image stream创建二进制构建。
  • 创建指向任务的新部署配置:0.0-0。
  • 关闭自动构建和部署。
  • 将部署配置公开为服务(在端口8080上),为service 配置route。
  • 将ConfigMap附加到dc。

下面是操作命令截图,不再一 一解释:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

创建生产项目,命令行如下,具体截图不再展示:

oc new-project xyz-tasks-prod80 --display-name "Tasks Production80"

oc policy add-role-to-group system:image-puller system:serviceaccounts:xyz-tasks-prod80 -n xyz-tasks-dev80

oc policy add-role-to-user edit system:serviceaccount:xyz-jenkins:jenkins -n xyz-tasks-prod80

常见的两个项目如下:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

四、环境准备:创建蓝绿应用

创建Blue应用:

oc new-app xyz-tasks-dev80/tasks:0.0 --name=tasks-blue --allow-missing-imagestream-tags=true -n xyz-tasks-prod80

oc set triggers dc/tasks-blue --remove-all -n xyz-tasks-prod80

oc expose dc tasks-blue --port 8080 -n xyz-tasks-prod80

oc create configmap tasks-blue-config --from-literal="application-users.properties=Placeholder" --from-literal="application-roles.properties=Placeholder" -n xyz-tasks-prod80

oc set volume dc/tasks-blue --add --name=jboss-config --mount-path=/opt/eap/standalone/configuration/application-users.properties --sub-path=application-users.properties --configmap-name=tasks-blue-config -n xyz-tasks-prod80

oc set volume dc/tasks-blue --add --name=jboss-config1 --mount-path=/opt/eap/standalone/configuration/application-roles.properties --sub-path=application-roles.properties --configmap-name=tasks-blue-config -n xyz-tasks-prod80

创建Green应用:

oc new-app xyz-tasks-dev80/tasks:0.0 --name=tasks-green --allow-missing-imagestream-tags=true -n xyz-tasks-prod80

oc set triggers dc/tasks-green --remove-all -n xyz-tasks-prod80

oc expose dc tasks-green --port 8080 -n xyz-tasks-prod

oc create configmap tasks-green-config --from-literal="application-users.properties=Placeholder" --from-literal="application-roles.properties=Placeholder" -n xyz-tasks-prod80

oc set volume dc/tasks-green --add --name=jboss-config --mount-path=/opt/eap/standalone/configuration/application-users.properties --sub-path=application-users.properties --configmap-name=tasks-green-config -n xyz-tasks-prod80

oc set volume dc/tasks-green --add --name=jboss-config1 --mount-path=/opt/eap/standalone/configuration/application-roles.properties --sub-path=application-roles.properties --configmap-name=tasks-green-config -n xyz-tasks-prod80

创建路由,并将路由指向到蓝应用:

oc expose svc/tasks-blue --name tasks -n xyz-tasks-prod80

(在Pipeline第一次跑通以后,发布的应用指向了Green应用。为何?因为在Pipeline中,第十步会进行蓝绿切换,这点其实也好理解:生产上通常不会部署最新版本的应用,dev环境开发新版本,prod部署上一个版本)

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

四、Pileline的十二个阶段

在正式书写Pileline之前,我们先将框架写出来。

这个Pipeline包含以下十二个步骤

步骤1 :代码迁出

// Checkout Source Code

stage('Checkout Source') {

// TBD

}

设置代码版本号:

// Set the tag for the development image: version + build number

def devTag = "0.0-0"

// Set the tag for the production image: version

def prodTag = "0.0"

步骤2:构建war包

stage('Build war') {

echo "Building version ${version}"

// TBD

}

步骤3:单元测试

// Using Maven run the unit tests

stage('Unit Tests') {

echo "Running Unit Tests"

// TBD

}

步骤4 :代码分析

// Using Maven call SonarQube for Code Analysis

stage('Code Analysis') {

echo "Running Code Analysis"

// TBD

}

步骤5:将war推送到Nexus

// Publish the built war file to Nexus

stage('Publish to Nexus') {

echo "Publish to Nexus"

// TBD

}

步骤6:Openshift中构建docker image

// Build the OpenShift Image in OpenShift and tag it.

stage('Build and Tag OpenShift Image') {

echo "Building OpenShift container image tasks:${devTag}"

// TBD

}

步骤7:在dev项目中部署镜像

// Deploy the built image to the Development Environment.

stage('Deploy to Dev') {

echo "Deploying container image to Development Project"

// TBD

}

步骤8:进行集成测试

// Run Integration Tests in the Development Environment.

stage('Integration Tests') {

echo "Running Integration Tests"

// TBD

}

步骤9:将镜像拷贝到Nexus Docker Registry

// Copy Image to Nexus Docker Registry

stage('Copy Image to Nexus Docker Registry') {

echo "Copy image to Nexus Docker Registry"

// TBD

}

步骤10:在prod项目中进行蓝绿部署

// Blue/Green Deployment into Production

// -------------------------------------

// Do not activate the new version yet.

def destApp = "tasks-green"

def activeApp = ""

stage('Blue/Green Production Deployment') {

// TBD

}

步骤11 :切换应用版本到生产

stage('Switch over to new Version') {

// TBD

echo "Switching Production application to ${destApp}."

// TBD

}

}

步骤12 :代码迁出

// Checkout Source Code

stage('Checkout Source Code') {

checkout scm

}

}

五、Pileline的第一个阶段:获取源代码

Pilpeline的第一步是从Gogs中的openshift-tasks-private存储库获取源代码。

  • 我们需要考虑的点有:
  • 源代码库的URL是什么?
  • 如何访问Gogs吗?
  • 如何指定Jenkins的身份验证凭据,以访问Gogs?

首先,我们在Jenkins上生成一个credentialsId(就是相当于在Jenkins上对Gogs的用户名和密码做加密处理,避免写Pileline的时候出现明文)

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

需要注意的是,下面输入的用户名和密码是gogs的,创建成功以后,会随机创建一个 credentialsId.

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

然后,使用获取到的 credentialsId,书写Pipeline的第一个阶段,从gogs的私有仓库中获取源代码。

在下面的内容中,node后面的内容,表示构建的时候,使用的maven slave pod的镜像,寻找的时候,是通过maven-appdev 这个label来匹配的:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

#!groovy

// Run this pipeline on the custom Maven Slave ('maven-appdev')

// Maven Slaves have JDK and Maven already installed

// 'maven-appdev' has skopeo installed as well.

node('maven-appdev') {

// Define Maven Command. Make sure it points to the correct

// settings for our Nexus installation (use the service to

// bypass the router). The file nexus_openshift_settings.xml

// needs to be in the Source Code repository.

def mvnCmd = "mvn -s ./nexus_openshift_settings.xml"

stage('David Checkout Source') {

git credentialsId: '5e38511b-5ded-41b7-a385-36fd9bab279f', url: 'http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git'

}

源代码Checkout后,pipeline可以检查pom.xml文件(该文件位于gogs的私有仓库中),以确定要构建的应用程序的版本。 最佳做法是将开发标记设置为版本号,加上Jenkins的实际内部版本号的组合。 这样,每次版本号不同时,我们可以多次运行Pileline。 当构建通过所有检查并将image标记为准备生产时,标记只是版本号。

在pipeline中,在以下部分中设置正确的tag:

def devTag = "${version}-${BUILD_NUMBER}"

def prodTag = "${version}"

六、Pileline的第二个阶段:构建war

pipeline中的第二步是从源代码构建WAR文件,我们需要考虑:

  • pipeline将环境变量mvnCmd定义为mvn -s ./nexus_openshift_settings.xml。
  • nexus_openshift_settings.xml位于Gogs存储库中,需要指向正确的Nexus服务。

本步骤中,使用-DskipTests绕过单元测试(下一个阶段运行)

首先修改源码库中的nexus_openshift_settings.xml和nexus_openshift_settings.xml配置:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

然后,书写Pileline:

// Using Maven build the war file

// Do not run tests in this step

stage('David Build war') {

echo "Building version ${devTag}"

sh "${mvnCmd} clean package -DskipTests"

}

七、Pileline的第三个阶段:运行单元测试

构建WAR文件后,运行单元测试。运行Pileline并验证单元测试是否成功完成。

// Using Maven run the unit tests

stage('David Unit Tests') {

echo "Running Unit Tests"

sh "${mvnCmd} test"

}

八、Pileline的第四个阶段:运行代码分析

在本阶段中,使用SonarQube运行代码覆盖率测试

我们需要考虑以下内容:

  • 运行SonarQube分析的Maven命令
  • SonarQube服务的URL
  • SonarQube的项目名称

stage('David Code Analysis') {

echo "David Running Code Analysis"

sh "${mvnCmd} sonar:sonar -Dsonar.host.url=http://sonarqube-xyz-sonarqube80.apps.0845.openshift.opentlc.com/ -Dsonar.projectName=${JOB_BASE_NAME}-${devTag}"

}

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

九、Pileline的第五个阶段:将代码测试通过的WAR文件存储在Nexus

一旦代码覆盖率测试成功,我们将war push到Nexus中:

stage('David Publish war to Nexus') {

echo "Publish to Nexus"

sh "${mvnCmd} deploy -DskipTests=true -DaltDeploymentRepository=nexus::default::http://nexus3.xyz-nexus80.svc.cluster.local:8081/repository/releases"

}

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

十、Pileline的第六个阶段:在OpenShift中构建docker image

归档WAR文件后,接下来,在OpenShift中构建容器映像。 在这个过程中,我们使用B2I。

下面做的操作,是将Jenkis workspace目录中的./target/openshift-tasks.war文件,宝贝到tasks:1.1-10中。而builder image的定义,卸载了tasks的bc中:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

// Build the OpenShift Image in OpenShift and tag it.

stage('David Build and Tag OpenShift Image') {

echo "Building OpenShift container image tasks:${devTag}"

sh "oc start-build tasks --follow --from-file=./target/openshift-tasks.war -n xyz-tasks-dev80"

openshiftTag alias: 'false', destStream: 'tasks', destTag: devTag, destinationNamespace: 'xyz-tasks-dev80', namespace: 'xyz-tasks-dev80', srcStream: 'tasks', srcTag: 'latest', verbose: 'false'

}

十一、Pileline的第七个阶段:将构建的映像部署到开发项目中

接下来是部署刚刚构建的容器映像。 xyz-tasks-dev80项目中已经有任务部署配置。它指向如下版本task应用:0.0-0 image。

该项目还包含一个tasks-config ConfigMap,它应该包含两个JBoss EAP映像的配置文件。在常规S2I构建中,源代码存储库中配置目录中的所有内容都会自动复制到构建映像中的JBoss EAP配置中。但是,因为我们使用二进制构建来构建映像,所以不会发生这种情况。因此,需要使用ConfigMap将配置文件添加到部署配置中。

我们需要删除当前的ConfigMap并使用两个文件./configuration/application-users.properties和./configuration/application-roles.properties创建一个新文件。

创建ConfigMap后,使用更新的映像和ConfigMap部署应用程序,然后验证部署是否成功。

// Deploy the built image to the Development Environment.

stage('David Deploy app to Dev') {

echo "Deploying container image to Development Project"

sh "oc set image dc/tasks tasks=docker-registry.default.svc:5000/xyz-tasks-dev80/tasks:${devTag} -n xyz-tasks-dev80"

sh "oc delete configmap tasks-config -n xyz-tasks-dev80 --ignore-not-found=true"

sh "oc create configmap tasks-config --from-file=./configuration/application-users.properties --from-file=./configuration/application-roles.properties -n xyz-tasks-dev80"

openshiftDeploy depCfg: 'tasks', namespace: 'xyz-tasks-dev80', verbose: 'false', waitTime: '', waitUnit: 'sec'

openshiftVerifyDeployment depCfg: 'tasks', namespace: 'xyz-tasks-dev', replicaCount: '1', verbose: 'false', verifyReplicaCount: 'false', waitTime: '', waitUnit: 'sec'

openshiftVerifyService namespace: 'xyz-tasks-dev80', svcName: 'tasks', verbose: 'false'

}

十二、Pileline的第八个阶段:运行集成测试

本阶段运行集成测试。

openshift-tasks应用程序是一个简单的任务管理应用程序,具有用于创建,检索和删除任务的REST接口。 应用程序的README文件包含有关用户ID和操作任务的可能命令的信息。

在此pileline中,我们创建一个任务、通过http方法检测API,然后删除该任务。

// Run Integration Tests in the Development Environment.

stage('David Run Integration Tests') {

echo "Running Integration Tests"

sleep 15

// Create a new task called "integration_test_1"

echo "Creating task"

sh "curl -i -u 'tasks:redhat1' -H 'Content-Length: 0' -X POST http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/integration_test_1"

// Retrieve task with id "1"

echo "Retrieving tasks"

sh "curl -i -u 'tasks:redhat1' -H 'Content-Length: 0' -X GET http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/1"

// Delete task with id "1"

echo "Deleting tasks"

sh "curl -i -u 'tasks:redhat1' -H 'Content-Length: 0' -X DELETE http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/1"

十三、Pileline的第九个阶段:将docker image复制到Nexus Container Registry

在大多数客户的环境中,非生产和生产需要做物理隔离。因此pipeline需要将测试的容器映像移动到另一个容器注册表、或另一个OpenShift集群。

在我的韩静中,Nexus配置为充当Docker registry。 使用skopeo将test image从集成的OpenShift Container Registry复制到Nexus的Container Registry。 将image复制到Nexus后,需要将image标记为已准备推动到生产环境。

// Copy Image to Nexus Docker Registry

stage('David Copy Image to Nexus Docker Registry') {

echo "Copy image to Nexus Docker Registry"

sh "skopeo copy --src-tls-verify=false --dest-tls-verify=false --src-creds openshift:\$(oc whoami -t) --dest-creds admin:admin123 docker://docker-registry.default.svc.cluster.local:5000/xyz-tasks-dev80/tasks:${devTag} docker://nexus-registry.xyz-nexus80.svc.cluster.local:5000/tasks:${devTag}"

// Tag the built image with the production tag.

// Replace xyz-tasks-dev with the name of your dev project

openshiftTag alias: 'false', destStream: 'tasks', destTag: prodTag, destinationNamespace: 'xyz-tasks-dev80', namespace: 'xyz-tasks-dev80', srcStream: 'tasks', srcTag: devTag, verbose: 'false'

}

}

十四、Pileline的第十个阶段:使用蓝绿部署部署将应用发布到生产

将容器映像安全地存储在Nexus Container registry中后,即可将映像部署到生产环境中。

由于image位于OpenShift外部的Container registry中,因此我们可以将image部署到完全不同的集群中进行生产。在这种情况下,需要启用群集以从此外部注册表中提取 - 或者再次使用skopeo将映像复制到生产群集中的容器注册表。

使用蓝绿色部署方法来执行部署。这意味着:

  • 需要确定当前活动的应用程序版本(蓝色或绿色)。
  • 需要使用JBoss EAP服务器配置更新正确的ConfigMap。
  • 将新应用程序部署到当前不活动的应用程序。

在此pipeline中,在切换路由之前,需要在部署新版本的应用程序时停止批准。

// Blue/Green Deployment into Production

// -------------------------------------

// Do not activate the new version yet.

def destApp = "tasks-green"

def activeApp = ""

stage('Blue/Green Production Deployment') {

activeApp = sh(returnStdout: true, script: "oc get route tasks -n xyz-tasks-prod80 -o jsonpath='{ .spec.to.name }'").trim()

if (activeApp == "tasks-green") {

destApp = "tasks-blue"

}

echo "Active Application: " + activeApp

echo "Destination Application: " + destApp

// Update the Image on the Production Deployment Config

sh "oc set image dc/${destApp} ${destApp}=docker-registry.default.svc:5000/xyz-tasks-dev8080/tasks:${prodTag} -n xyz-tasks-prod80"

// Update the Config Map which contains the users for the Tasks application

sh "oc delete configmap ${destApp}-config -n xyz-tasks-prod80 --ignore-not-found=true"

sh "oc create configmap ${destApp}-config --from-file=./configuration/application-users.properties --from-file=./configuration/application-roles.properties -n xyz-tasks-prod80"

// Deploy the inactive application.

// Replace xyz-tasks-prod with the name of your production project

openshiftDeploy depCfg: destApp, namespace: 'xyz-tasks-prod80', verbose: 'false', waitTime: '', waitUnit: 'sec'

openshiftVerifyDeployment depCfg: destApp, namespace: 'xyz-tasks-prod80', replicaCount: '1', verbose: 'false', verifyReplicaCount: 'true', waitTime: '', waitUnit: 'sec'

openshiftVerifyService namespace: 'xyz-tasks-prod80', svcName: destApp, verbose: 'false'

}

十四、Pileline的第十一个阶段:到生产蓝绿切换

本阶段,应用程序现在可以进行切换。 应用程序已完全运行并准备接收流量。 如果需要,可以在切换流量之前使用生产环境(群集)中的实时应用程序运行另一个测试。 在我的实验中,增加了审批流程, 一旦批准,pipeline就会将路径从旧应用程序切换到新应用程序。

stage('David do Switch over to new Version') {

input "Switch Production?"

echo "Switching Production application to ${destApp}."

sh 'oc patch route tasks -n xyz-tasks-prod80 -p \'{"spec":{"to":{"name":"' + destApp + '"}}}\''

}

十五、Pileline的第十二个阶段:代码checkout

// Checkout Source Code

stage('David Checkout Source') {

checkout scm

}

接下来,截至到目前,主的Jenkins file已经写完。我们将这个Jenkins file上传到Gogs的代码仓库中,和源码放在一起:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

十六、设置web hook

我们要实现:开发人员将新代码推送到openshift-tasks-private1存储库时,自动触发构建,需要Gogs中设置Git挂钩。

在Jenkins中找到授权令牌,打开浏览器并登录Jenkins,在右上角,单击用户名旁边的向下箭头,然后选择配置。

单击“显示API令牌”并记下显示的用户ID和API令牌。

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

接下来,在Gogs中创建Web挂钩:

打开浏览器,导航到Gogs服务器,登录,然后转到CICDLabs / openshift-tasks-private1存储库,单击“设置”,然后单击“Git Hooks”。

配置Git钩子:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

将此脚本复制并粘贴到Hook Content字段中,将<userid>和<apiToken>替换为Jenkins用户ID和API令牌,将<jenkinsService>替换为Jenkins服务的名称,将<jenkinsProject>替换为OpenShift项目的名称您的Jenkins服务位于:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

十七、触发构建测试

提交新版本的应用程序源代码,会触发新的构建。 每次更改应用程序时,最好增加版本号。 我们可以手动或自动递增版本号。

我们进行测试:

export VERSION=1.1

mvn versions:set -f pom.xml -s nexus_settings.xml -DgenerateBackupPoms=false -DnewVersion=${VERSION}

git add pom.xml src/main/webapp/index.jsp

git commit -m "Increased version to ${VERSION}"

git push private master

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

验证此推送是否触发了Jenkins中的新构建。

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

确保pipeline各个阶段都能成功:

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

十八:使用pipeline构建配置

通过上面的步骤,我们写好了一个Jenkins File,可以在Jenkins触发构建。

但为了方便统一管理,我们可以使用Pipeline构建策略创建OpenShift构建配置,而不是在Jenkins中定义pileline。说简单点,就是在Openshift中写一个Pipeline/BC,触发上面写的Jenkins File( 此bc必须与Jenkins pod位于同一项目中除非将master-config.yaml配置为指向另一个Jenkins实例)。

创建tasks-pipeline.yaml文件:

echo "apiVersion: v1

items:

- kind: "BuildConfig"

apiVersion: "v1"

metadata:

name: "tasks-pipeline"

spec:

source:

type: "Git"

git:

uri: "http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1"

strategy:

type: "JenkinsPipeline"

jenkinsPipelineStrategy:

jenkinsfilePath: Jenkinsfile

kind: List

metadata: []" | oc create -f - -n xyz-jenkins80

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

创建secret并与bc相关联:

oc secrets new-basicauth gogs-secret --username=david --password=david -n xyz-jenkins80

oc set build-secret --source bc/tasks-pipeline gogs-secret -n xyz-jenkins80

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

在OpenShift Web控制台中,切换到Jenkins项目并导航到Builds→Pipelines。

单击“Start Pipeline”以触发Pipeline:

单击“查看日志”以查看pipeline进度并在Jenkins中进行操作。

怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变
怎样一个金箍圈(Pipeline),让至尊宝(Openshift)完成了到孙悟空(DevOps)的蜕变

最后,我将整个Pipeline的日志的重要部分提出来,以便参考(注解是我加上的,并非在原始的log中):

OpenShift Build xyz-jenkins80/tasks-pipeline-10 from http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1

//从Gogs获取Jenkins file,然后开始执行Jenkins File:Checking out git http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 into /var/lib/jenkins/jobs/xyz-jenkins80/jobs/xyz-jenkins80-tasks-pipeline/workspace@script to read Jenkinsfile
 > git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > git config remote.origin.url http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 # timeout=10
Fetching upstream changes from http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1
 > git --version # timeout=10
using GIT_ASKPASS to set credentials xyz-jenkins80-gogs-secret
 > git fetch --tags --progress http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 +refs/heads/*:refs/remotes/origin/*
 > git rev-parse origin/master^{commit} # timeout=10
Checking out Revision 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 (origin/master)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f 6b3cdd2e486420320b09ba84ab6c51e41d1a0642
Commit message: "更新 'Jenkinsfile'"
 > git rev-list --no-walk 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 # timeout=10
[Pipeline] node
Still waiting to schedule task
maven-appdev-wt2zs is offline

 
//此时启动Jenkins Slave Pod:
 Running on maven-appdev-wt2zs in /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline
[Pipeline] {
[Pipeline] stage

//此时开始迁出源代码[Pipeline] { (David Checkout Source)[Pipeline] git
Cloning the remote Git repository
Cloning repository http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git
 > git init /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline # timeout=10
Fetching upstream changes from http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git
 > git --version # timeout=10
using GIT_ASKPASS to set credentials gogsname
 > git fetch --tags --progress http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git +refs/heads/*:refs/remotes/origin/*
 > git config remote.origin.url http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git # timeout=10
 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
 > git config remote.origin.url http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git # timeout=10
Fetching upstream changes from http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git
using GIT_ASKPASS to set credentials gogsname
 > git fetch --tags --progress http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git +refs/heads/*:refs/remotes/origin/*
 > git rev-parse refs/remotes/origin/master^{commit} # timeout=10
 > git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10
Checking out Revision 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 (refs/remotes/origin/master)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f 6b3cdd2e486420320b09ba84ab6c51e41d1a0642
 > git branch -a -v --no-abbrev # timeout=10
 > git checkout -b master 6b3cdd2e486420320b09ba84ab6c51e41d1a0642
Commit message: "更新 'Jenkinsfile'"
 > git rev-list --no-walk 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 # timeout=10
[Pipeline] }
[Pipeline] // stage
[Pipeline] readFile
[Pipeline] readFile
[Pipeline] readFile

//此时开始构建war包[Pipeline] stage[Pipeline] { (David Build war)[Pipeline] echo
Building version 1.1-10
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script+ mvn -s ./nexus_openshift_settings.xml clean package -DskipTestsPicked up JAVA_TOOL_OPTIONS: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Dsun.zip.disableMemoryMapping=true
[INFO] Scanning for projects...
Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/jboss/bom/eap/jboss-javaee-6.0-with-tools/6.4.0.GA/jboss-javaee-6.0-with-tools-6.4.0.GA.pom
4/8 KB   
8/8 KB              

复制

Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/jboss/jboss-parent/9/jboss-parent-9.pom (28 KB at 299.8 KB/sec)
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building JBoss EAP - Tasks App 1.1
[INFO] ------------------------------------------------------------------------
Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/jacoco/jacoco-maven-plugin/0.7.9/jacoco-maven-plugin-0.7.9.pom
4/5 KB     
5/5 KB   
         
Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public           

复制

68/168 KB   38/38 KB   
                        
Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/shared/maven-shared-utils/0.9/maven-shared-utils-0.9.jar (168 KB at 1552.3 KB/sec)
                        
Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/surefire/surefire-grouper/2.19.1/surefire-grouper-2.19.1.jar (38 KB at 302.2 KB/sec)

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Picked up JAVA_TOOL_OPTIONS: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Dsun.zip.disableMemoryMapping=true
Running org.jboss.as.quickstarts.tasksrs.service.TaskResourceTest
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.51 sec - in org.jboss.as.quickstarts.tasksrs.service.TaskResourceTest
Running org.jboss.as.quickstarts.tasksrs.service.UserResourceTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 0.001 sec - in org.jboss.as.quickstarts.tasksrs.service.UserResourceTest

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 1


//war包构建成功[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 44.914 s
[INFO] Finished at: 2018-08-31T06:36:00+00:00
[INFO] Final Memory: 16M/178M
[INFO] ------------------------------------------------------------------------
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage

//开始做代码分析[Pipeline] { (David Code Analysis)
[Pipeline] echo
David Running Code Analysis
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ mvn -s ./nexus_openshift_settings.xml sonar:sonar -Dsonar.host.url=http://sonarqube-xyz-sonarqube80.apps.0845.openshift.opentlc.com/ -Dsonar.projectName=xyz-jenkins80-tasks-pipeline-1.1-10
Picked up JAVA_TOOL_OPTIONS: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Dsun.zip.disableMemoryMapping=true
[INFO] Scanning for projects...
Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/jboss/as/plugins/jboss-as-maven-plugin/7.4.Final/jboss-as-maven-plugin-7.4.Final.pom
4/13 KB   
8/13 KB   
12/13 KB              

复制

Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/sonarsource/scanner/maven/sonar-maven-plugin/3.3.0.603/sonar-maven-plugin-3.3.0.603.jar (54 KB at 266.7 KB/sec)
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building JBoss EAP - Tasks App 1.1
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- sonar-maven-plugin:3.3.0.603:sonar (default-cli) @ tasks ---
Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/shared/maven-dependency-tree/2.2/maven-dependency-tree-2.2.pom
4/8 KB     
8/8 KB   
         
Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/shared/maven-dependency-tree/2.2/maven-dependency-tree-2.2.pom (8 KB at 35.5 KB/sec)
Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/shared/maven-shared-components/20/maven-shared-components-20.pom
4/5 KB   
5/5 KB   
         
Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/shared/maven-shared-components/20/maven-shared-components-20.pom (5 KB at 25.6 KB/sec)
Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/eclipse/aether/aether-util/0.9.0.M2/aether-util-0.9.0.M2.pom
2/2 KB   
         
Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/eclipse/aether/aether-util/0.9.0.M2/aether-util-0.9.0.M2.pom (2 KB at 18.9 KB/sec)
Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/eclipse/aether/aether/0.9.0.M2/aether-0.9.0.M2.pom
4/28 KB   
8/28 KB   
12/28 KB   
16/28 KB   
20/28 KB   
24/28 KB              

复制

Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/commons-lang/commons-lang/2.6/commons-lang-2.6.jar (278 KB at 447.7 KB/sec)
                                     
Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/sonarsource/scanner/api/sonar-scanner-api/2.9.0.887/sonar-scanner-api-2.9.0.887.jar (520 KB at 744.4 KB/sec)
[INFO] User cache: /home/jenkins/.sonar/cache
[INFO] Publish mode
[INFO] Load global settings
[INFO] Load global settings (done) | time=223ms
[INFO] Server id: AWV_FuWdgycr44kTc7kD
[INFO] User cache: /home/jenkins/.sonar/cache
[INFO] Load plugins index
[INFO] Load plugins index (done) | time=55ms
[INFO] Download sonar-flex-plugin-2.3.jar
[INFO] Download sonar-csharp-plugin-6.5.0.3766.jar
[INFO] Download sonar-javascript-plugin-3.2.0.5506.jar
[INFO] Download sonar-java-plugin-4.15.0.12310.jar
[INFO] Download sonar-php-plugin-2.11.0.2485.jar
[INFO] Download sonar-python-plugin-1.8.0.1496.jar
[INFO] Download sonar-scm-git-plugin-1.3.0.869.jar
[INFO] Download sonar-scm-svn-plugin-1.6.0.860.jar
[INFO] Download sonar-typescript-plugin-1.1.0.1079.jar
[INFO] Download sonar-xml-plugin-1.4.3.1027.jar
[INFO] SonarQube version: 6.7.4
[INFO] Default locale: "en_US", source code encoding: "UTF-8"
[INFO] Process project properties
[INFO] Load project repositories
[INFO] Load project repositories (done) | time=207ms
[INFO] Load quality profiles
[INFO] Load quality profiles (done) | time=92ms
[INFO] Load active rules
[INFO] Load active rules (done) | time=704ms
[INFO] Load metrics repository
[INFO] Load metrics repository (done) | time=96ms
[INFO] Project key: org.jboss.quickstarts.eap:tasks[INFO] -------------  Scan xyz-jenkins80-tasks-pipeline-1.1-10[INFO] Load server rules
[INFO] Load server rules (done) | time=74ms
[INFO] Base dir: /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline
[INFO] Working dir: /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline/target/sonar
[INFO] Source paths: src/main/webapp, pom.xml, src/main/java
[INFO] Test paths: src/test/java
[INFO] Source encoding: UTF-8, default locale: en_US
[INFO] Index files
[INFO] 123 files indexed
[INFO] Quality profile for java: Sonar way
[INFO] Quality profile for js: Sonar way
[INFO] Quality profile for xml: Sonar way
[INFO] Sensor JavaSquidSensor [java]
[INFO] Configured Java source version (sonar.java.source): 8
[INFO] JavaClasspath initialization
[INFO] JavaClasspath initialization (done) | time=89ms
[INFO] JavaTestClasspath initialization
[INFO] JavaTestClasspath initialization (done) | time=1ms
[INFO] Java Main Files AST scan
[INFO] 11 source files to be analyzed
[INFO] 6/11 files analyzed, current file: /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline/src/main/java/org/jboss/as/quickstarts/tasksrs/model/User.java
[INFO] Java Main Files AST scan (done) | time=16992ms
[INFO] 11/11 source files have been analyzed
[INFO] Java Test Files AST scan
[INFO] 7 source files to be analyzed
[INFO] Java Test Files AST scan (done) | time=6396ms
[INFO] Sensor JavaSquidSensor [java] (done) | time=28197ms
[INFO] Sensor SurefireSensor [java]
[INFO] Property 'sonar.junit.reportsPath' is deprecated. Use property 'sonar.junit.reportPaths' instead.
[INFO] parsing [/tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline/target/surefire-reports]
[INFO] 7/7 source files have been analyzed
[INFO] Sensor SurefireSensor [java] (done) | time=1901ms
[INFO] Sensor JaCoCoSensor [java]
[INFO] Analysing /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline/target/jacoco.exec
[INFO] No information about coverage per test.
[INFO] Sensor JaCoCoSensor [java] (done) | time=1002ms
[INFO] Sensor SonarJavaXmlFileSensor [java]
[INFO] 4 source files to be analyzed
[INFO] Sensor SonarJavaXmlFileSensor [java] (done) | time=4601ms
[INFO] 4/4 source files have been analyzed
[INFO] Sensor XML Sensor [xml]
[INFO] Sensor XML Sensor [xml] (done) | time=999ms
[INFO] Sensor Analyzer for "php.ini" files [php]
[INFO] Sensor Analyzer for "php.ini" files [php] (done) | time=3ms
[INFO] Sensor JavaScript Squid Sensor [javascript]
[INFO] 3 source files to be analyzed
[INFO] Unit Test Coverage Sensor is started
[INFO] 3/3 source files have been analyzed
[INFO] Integration Test Coverage Sensor is started
[INFO] Overall Coverage Sensor is started
[INFO] Sensor JavaScript Squid Sensor [javascript] (done) | time=6896ms
[INFO] Sensor Zero Coverage Sensor
[INFO] Sensor Zero Coverage Sensor (done) | time=409ms
[INFO] Sensor CPD Block Indexer
[INFO] Sensor CPD Block Indexer (done) | time=294ms
[INFO] 3 files had no CPD blocks
[INFO] Calculating CPD for 10 files
[INFO] CPD calculation finished
[INFO] Analysis report generated in 896ms, dir size=255 KB
[INFO] Analysis reports compressed in 202ms, zip size=111 KB
[INFO] Analysis report uploaded in 103ms
[INFO] ANALYSIS SUCCESSFUL, you can browse http://sonarqube-xyz-sonarqube80.apps.0845.openshift.opentlc.com/dashboard/index/org.jboss.quickstarts.eap:tasks
[INFO] Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
[INFO] More about the report processing at http://sonarqube-xyz-sonarqube80.apps.0845.openshift.opentlc.com/api/ce/task?id=AWWOs4548YCjCIcdKfvG
[INFO] Task total time: 56.835 s

//代码分析通过[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:26 min
[INFO] Finished at: 2018-08-31T06:37:36+00:00
[INFO] Final Memory: 18M/250M
[INFO] ------------------------------------------------------------------------
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (David Publish war to Nexus)
[Pipeline] echo
David Publish app to Nexus
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ mvn -s ./nexus_openshift_settings.xml deploy -DskipTests=true -DaltDeployment           

复制

337/337 B   
            
Uploaded: http://nexus3.xyz-nexus80.svc.cluster.local:8081/repository/releases/org/jboss/quickstarts/eap/tasks/maven-metadata.xml (337 B at 11.8 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 32.726 s
[INFO] Finished at: 2018-08-31T06:38:19+00:00
[INFO] Final Memory: 22M/173M
[INFO] ------------------------------------------------------------------------
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage

//在Openshift构建docker image,通过B2I 将生成的war包拷贝到builder image中:
[Pipeline] { (David Build and Tag OpenShift Image)
[Pipeline] echo
David Building OpenShift container image tasks:1.1-10
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ oc start-build tasks --follow --from-file=./target/openshift-tasks.war -n xyz-tasks-dev80
Uploading file "target/openshift-tasks.war" as binary input for the build ...
build "tasks-3" started
Receiving source from STDIN as file openshift-tasks.warCopying all war artifacts from /tmp/src directory into /opt/eap/standalone/deployments for later deployment...
'/tmp/src/openshift-tasks.war' -> '/opt/eap/standalone/deployments/openshift-tasks.war'
Copying all ear artifacts from /tmp/src directory into /opt/eap/standalone/deployments for later deployment...
Copying all rar artifacts from /tmp/src directory into /opt/eap/standalone/deployments for later deployment...
Copying all jar artifacts from /tmp/src directory into /opt/eap/standalone/deployments for later deployment...
Copying all war artifacts from /tmp/src/deployments directory into /opt/eap/standalone/deployments for later deployment...
Copying all ear artifacts from /tmp/src/deployments directory into /opt/eap/standalone/deployments for later deployment...
Copying all rar artifacts from /tmp/src/deployments directory into /opt/eap/standalone/deployments for later deployment...
Copying all jar artifacts from /tmp/src/deployments directory into /opt/eap/standalone/deployments for later deployment...

Pushing image docker-registry.default.svc:5000/xyz-tasks-dev80/tasks:latest ...
Pushed 6/7 layers, 97% complete
Pushed 7/7 layers, 100% complete
Push successful
[Pipeline] openshiftTag           

复制

Starting "Tag OpenShift Image" with the source [image stream:tag] "tasks:latest" from the project "xyz-tasks-dev80" and destination stream(s) "tasks" with tag(s) "1.1-10" from the project "xyz-tasks-dev80".


Exiting "Tag OpenShift Image" successfully.
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage

//将docker image部署到dev环境,先修改dc指向上一步生成的image,然后触发dc进行部署:[Pipeline] { (David Deploy app to Dev)
[Pipeline] echo
David Deploying container image to Development Project
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script+ oc set image dc/tasks tasks=docker-registry.default.svc:5000/xyz-tasks-dev80/tasks:1.1-10 -n xyz-tasks-dev80deploymentconfig "tasks" image updated
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ oc delete configmap tasks-config -n xyz-tasks-dev80 --ignore-not-found=true
configmap "tasks-config" deleted
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ oc create configmap tasks-config --from-file=./configuration/application-users.properties --from-file=./configuration/application-roles.properties -n xyz-tasks-dev80
configmap "tasks-config" created
[Pipeline] openshiftDeployStarting "Trigger OpenShift Deployment" with deployment config "tasks" from the project "xyz-tasks-dev80".Operation will timeout after 600000 milliseconds


Exiting "Trigger OpenShift Deployment" successfully; deployment "tasks-3" has completed with status:  [Complete].
[Pipeline] openshiftVerifyDeployment


Starting "Verify OpenShift Deployment" with deployment config "tasks" from the project "xyz-tasks-dev80".
  Waiting on the latest deployment for "tasks" to complete ...
Operation will timeout after 180000 milliseconds


Exiting "Verify OpenShift Deployment" successfully; deployment "tasks-3" has completed with status:  [Complete].
[Pipeline] openshiftVerifyService


Starting "Verify OpenShift Service" for the service "tasks" from the project "xyz-tasks-dev80".
  Attempting to connect to "172.30.194.191:8080" ...


Exiting "Verify OpenShift Service" successfully; a connection to "172.30.194.191:8080" was made.
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
//进行集成测试,通过curl实现:[Pipeline] { (David Run Integration Tests)
[Pipeline] echo
David Running Integration Tests
[Pipeline] sleep
Sleeping for 15 sec
[Pipeline] echo
Creating task
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ curl -i -u tasks:redhat1 -H 'Content-Length: 0' -X POST http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/integration_test_1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
100    74  100    74    0     0     54      0  0:00:01  0:00:01 --:--:--    54
HTTP/1.1 404 Not Found
Connection: keep-alive
X-Powered-By: Undertow/1
Server: JBoss-EAP/7
Content-Length: 74
Content-Type: text/html
Date: Fri, 31 Aug 2018 06:39:23 GMT

<html><head><title>Error</title></head><body>404 - Not Found</body></html>[Pipeline] echo
Retrieving tasks
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ curl -i -u tasks:redhat1 -H 'Content-Length: 0' -X GET http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100    74  100    74    0     0   2575      0 --:--:-- --:--:-- --:--:--  2642
HTTP/1.1 404 Not Found
Connection: keep-alive
X-Powered-By: Undertow/1
Server: JBoss-EAP/7
Content-Length: 74
Content-Type: text/html
Date: Fri, 31 Aug 2018 06:39:23 GMT

<html><head><title>Error</title></head><body>404 - Not Found</body></html>[Pipeline] echo
Deleting tasks
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ curl -i -u tasks:redhat1 -H 'Content-Length: 0' -X DELETE http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100    83  100    83    0     0   5903      0 --:--:-- --:--:-- --:--:--  6384
HTTP/1.1 405 Method Not Allowed
Connection: keep-alive
X-Powered-By: Undertow/1
Server: JBoss-EAP/7
Content-Length: 83
Content-Type: text/html
Date: Fri, 31 Aug 2018 06:39:23 GMT

<html><head><title>Error</title></head><body>405 - Method Not Allowed</body></html>[Pipeline] stage

//拷贝deocker image到Nexus Docker Registry中,通过skopeo实现:[Pipeline] { (David Copy Image to Nexus Docker Registry)
[Pipeline] echo
David Copy image to Nexus Docker Registry
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
++ oc whoami -t
+ skopeo copy --src-tls-verify=false --dest-tls-verify=false --src-creds openshift:eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJ4eXotamVua2luczgwIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImplbmtpbnMtdG9rZW4tcHZjMngiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiamVua2lucyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjVkNTNiZDUzLWFhOWYtMTFlOC1iNWVlLTBhY2Q3NjhhYmEzMCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDp4eXotamVua2luczgwOmplbmtpbnMifQ.LwTOxjvWbARVAyh750wU69CefvDgL8w-v9gTkHQ6BeXh4ATkfBYWug4GKJ-XWQxnZIe0oNLUuHg4hJPmzs6OohIcwXk-DUhks_6UMzOXZg0fP68OwpEZTh9nn6ImMmIETO4lm4SZBUcCBYOsEzJPwSuTXV59qqYcGQgVLQ_zya_ucR5zPmxwb-cWI4TAmTCHcH6dOAAZixGQb8ncHjzEFqxRE4HARUZYj5JcICjMABb9wDybXWTwol3gq4W0akkbd56466IYOlhJzCp6OFxGMf6Ze1xwSt5Pwrl4Xn9i1B_-2ZTp7UBNY_SNsBOIb7v0_IQRmucOJfu0ZU6v3W1y-g --dest-creds admin:admin123 docker://docker-registry.default.svc.cluster.local:5000/xyz-tasks-dev80/tasks:1.1-10 docker://nexus-registry.xyz-nexus80.svc.cluster.local:5000/tasks:1.1-10
Getting image source signatures
Skipping fetch of repeat blob sha256:243dc7b9e786e952d1a31abe13850c78dbda894bae5f952f1bc83eb7625ced4e
Skipping fetch of repeat blob sha256:550516fb1c76cce4ed1e5197ab774186feb529bcc6362b3fe11cb7ab6f331206
Skipping fetch of repeat blob sha256:bd2f45881d4be8c18df36799d455bb6ec52669058c8a35eb65a198608434c195
Skipping fetch of repeat blob sha256:51268d1752f657f09e5c7ab7b564a9254dd3f566fcdcbc92db0d9de8378bb18b
Skipping fetch of repeat blob sha256:310ef6e6c91ce656668a4db4719fb0135f4b63a64fd98c423fda98e7a82d4f1d
Skipping fetch of repeat blob sha256:7b582c56c1ab9b1a9cb67caa730dcf932c6eb4aeee26b1cfbf8b982bcad446d9
Copying blob sha256:d0af4999de1d5f0bcb977f4b8e73b0246c72850508b5716be9f1093d083c289c

 0 B / 3.98 MB 
 3.98 MB / 3.98 MB 
 3.98 MB / 3.98 MB  0s
Copying config sha256:ddc1196b8d7a08399be99152ab63ac9d7b8760e0d1bd55ae6b765fe97216582e

 0 B / 6.71 KB 
 6.71 KB / 6.71 KB  0s
Writing manifest to image destination
Storing signatures
[Pipeline] openshiftTag


Starting "Tag OpenShift Image" with the source [image stream:tag] "tasks:1.1-10" from the project "xyz-tasks-dev80" and destination stream(s) "tasks" with tag(s) "1.1" from the project "xyz-tasks-dev80".


Exiting "Tag OpenShift Image" successfully.
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage

//进行蓝绿发布[Pipeline] { (David do Blue/Green Production Deployment)
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ oc get route tasks -n xyz-tasks-prod80 -o 'jsonpath={ .spec.to.name }'
[Pipeline] echo
Active Application:      tasks-blue
[Pipeline] echo
Destination Application: tasks-green
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ oc set image dc/tasks-green tasks-green=docker-registry.default.svc:5000/xyz-tasks-dev80/tasks:1.1 -n xyz-tasks-prod80
deploymentconfig "tasks-green" image updated
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ oc delete configmap tasks-green-config -n xyz-tasks-prod80 --ignore-not-found=true
configmap "tasks-green-config" deleted
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ oc create configmap tasks-green-config --from-file=./configuration/application-users.properties --from-file=./configuration/application-roles.properties -n xyz-tasks-prod80
configmap "tasks-green-config" created
[Pipeline] openshiftDeploy


Starting "Trigger OpenShift Deployment" with deployment config "tasks-green" from the project "xyz-tasks-prod80".
Operation will timeout after 600000 milliseconds


Exiting "Trigger OpenShift Deployment" successfully; deployment "tasks-green-1" has completed with status:  [Complete].
[Pipeline] openshiftVerifyDeployment


Starting "Verify OpenShift Deployment" with deployment config "tasks-green" from the project "xyz-tasks-prod80".
  Waiting on the latest deployment for "tasks-green" to complete and scale to "1" replica(s) ...
Operation will timeout after 180000 milliseconds


Exiting "Verify OpenShift Deployment" successfully; deployment "tasks-green-1" has completed with status:  [Complete].  The deployment reached "1" replica(s).
[Pipeline] openshiftVerifyService


Starting "Verify OpenShift Service" for the service "tasks-green" from the project "xyz-tasks-prod80".
  Attempting to connect to "172.30.156.93:8080" ...


Exiting "Verify OpenShift Service" successfully; a connection to "172.30.156.93:8080" was made.
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage

//提示是否向生产切换[Pipeline] { (David do Switch over to new Version)
[Pipeline] input
Switch Production?
Proceed or Abort
Approved by user80
[Pipeline] echo
Switching Production application to tasks-green.
[Pipeline] sh
[xyz-jenkins80-tasks-pipeline] Running shell script
+ oc patch route tasks -n xyz-tasks-prod80 -p '{"spec":{"to":{"name":"tasks-green"}}}'
route "tasks" patched
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage

//迁出源[Pipeline] { (David Checkout Source)
[Pipeline] checkout
 > git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > git config remote.origin.url http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 # timeout=10
Fetching upstream changes from http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1
 > git --version # timeout=10
using GIT_ASKPASS to set credentials xyz-jenkins80-gogs-secret
 > git fetch --tags --progress http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 +refs/heads/*:refs/remotes/origin/*
 > git rev-parse origin/master^{commit} # timeout=10
Checking out Revision 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 (origin/master)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f 6b3cdd2e486420320b09ba84ab6c51e41d1a0642
Commit message: "更新 'Jenkinsfile'"
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS           

复制