天天看點

怎樣一個金箍圈(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           

複制