1、動態生成Slave
1.一、簡介
以前咱們都是在物理機或者虛擬機上部署jenkins,可是這種部署方式會有一些難點,以下:node
- 主 Master 發生單點故障時,整個流程都不可用了
- 每一個 Slave 的配置環境不同,來完成不一樣語言的編譯打包等操做,可是這些差別化的配置致使管理起來很是不方便,維護起來也是比較費勁
- 資源分配不均衡,有的 Slave 要運行的 job 出現排隊等待,而有的 Slave 處於空閒狀態
- 資源有浪費,每臺 Slave 多是物理機或者虛擬機,當 Slave 處於空閒狀態時,也不會徹底釋放掉資源。
正由於上面的這些種種痛點,咱們渴望一種更高效更可靠的方式來完成這個 CI/CD 流程,而 Docker 虛擬化容器技術能很好的解決這個痛點,又特別是在 Kubernetes 集羣環境下面可以更好來解決上面的問題,下圖是基於 Kubernetes 搭建 Jenkins 集羣的簡單示意圖:
從圖上能夠看到 Jenkins Master 和 Jenkins Slave 以 Pod 形式運行在 Kubernetes 集羣的 Node 上,Master 運行在其中一個節點,而且將其配置數據存儲到一個 Volume 上去,Slave 運行在各個節點上,而且它不是一直處於運行狀態,它會按照需求動態的建立並自動刪除。
這種方式的工做流程大體爲:當 Jenkins Master 接受到 Build 請求時,會根據配置的 Label 動態建立一個運行在 Pod 中的 Jenkins Slave 並註冊到 Master 上,當運行完 Job 後,這個 Slave 會被註銷而且這個 Pod 也會自動刪除,恢復到最初狀態。
這種方式部署給咱們帶來以下好處:
python
- 服務高可用,當 Jenkins Master 出現故障時,Kubernetes 會自動建立一個新的 Jenkins Master 容器,而且將 Volume 分配給新建立的容器,保證數據不丟失,從而達到集羣服務高可用。
- 動態伸縮,合理使用資源,每次運行 Job 時,會自動建立一個 Jenkins Slave,Job 完成後,Slave 自動註銷並刪除容器,資源自動釋放,並且 Kubernetes 會根據每一個資源的使用狀況,動態分配 Slave 到空閒的節點上建立,下降出現因某節點資源利用率高,還排隊等待在該節點的狀況。
- 擴展性好,當 Kubernetes 集羣的資源嚴重不足而致使 Job 排隊等待時,能夠很容易的添加一個 Kubernetes Node 到集羣中,從而實現擴展。
1.二、部署
一、建立PV、PVC,爲Jenkins提供數據持久化:git
--- apiVersion: v1 kind: PersistentVolume metadata: name: jenkins-pv spec: capacity: storage: 5Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Delete nfs: server: 172.16.1.128 path: /data/k8s/jenkins --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jenkins-pvc namespace: devops spec: accessModes: - ReadWriteMany resources: requests: storage: 5Gi
二、建立角色受權
github
apiVersion: v1 kind: ServiceAccount metadata: name: jenkins-sa namespace: devops --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: jenkins-cr rules: - apiGroups: ["extensions", "apps"] resources: ["deployments"] verbs: ["create", "delete", "get", "list", "watch", "patch", "update"] - apiGroups: [""] resources: ["services"] verbs: ["create", "delete", "get", "list", "watch", "patch", "update"] - apiGroups: [""] resources: ["pods"] verbs: ["create","delete","get","list","patch","update","watch"] - apiGroups: [""] resources: ["pods/exec"] verbs: ["create","delete","get","list","patch","update","watch"] - apiGroups: [""] resources: ["pods/log"] verbs: ["get","list","watch"] - apiGroups: [""] resources: ["secrets"] verbs: ["get"] --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: jenkins-crd roleRef: kind: ClusterRole name: jenkins-cr apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: jenkins-sa namespace: devops
一、在Kubernetes中部署Jenkins,新建Deployment,jenkins-deploy.yaml
web
--- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: jenkins namespace: devops spec: template: metadata: labels: app: jenkins spec: terminationGracePeriodSeconds: 10 serviceAccount: jenkins-sa containers: - name: jenkins image: jenkins/jenkins:lts imagePullPolicy: IfNotPresent env: - name:JAVA_OPTS value: -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85 -Duser.timezone=Asia/Shanghai ports: - containerPort: 8080 name: web protocol: TCP - containerPort: 50000 name: agent protocol: TCP resources: limits: cpu: 1000m memory: 1Gi requests: cpu: 500m memory: 512Mi livenessProbe: httpGet: path: /login port: 8080 initialDelaySeconds: 60 timeoutSeconds: 5 failureThreshold: 12 readinessProbe: httpGet: path: /login port: 8080 initialDelaySeconds: 60 timeoutSeconds: 5 failureThreshold: 12 volumeMounts: - name: jenkinshome mountPath: /var/jenkins_home securityContext: fsGroup: 1000 volumes: - name: jenkinshome persistentVolumeClaim: claimName: jenkins-pvc --- apiVersion: v1 kind: Service metadata: name: jenkins namespace: devops labels: app: jenkins spec: selector: app: jenkins type: NodePort ports: - name: web port: 8080 targetPort: web nodePort: 30002 - name: agent port: 50000 targetPort: agent
五、建立上面的資源清單
docker
# kubectl apply -f jenkins-rbac.yaml # kubectl apply -f jenkins-pvc.yaml # kubectl apply -f jenkins-deploy.yaml
啓動若是報以下錯誤(由於咱們容器裏是以jenkins用戶啓動,而咱們NFS服務器上是root啓動,因此沒有權限):
shell
[root@master manifests]# kubectl logs jenkins-688c6cd5fd-lj6zg -n devops touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
而後給咱們NFS服務器上的目錄受權便可:
api
# chown -R 1000 /data/k8s/jenkins/jenkins
而後登陸網站,由於咱們Service是採用NodePort類型,其端口爲30002,咱們直接在瀏覽器用這個端口訪問:
密碼能夠經過以下命令得到:
瀏覽器
# cat /data/k8s/jenkins/secrets/initialAdminPassword 12b503a274354e09a465b4f76664db70
而後安裝插件到安裝完成。
安全
1.三、配置
一、安裝插件kubernetes
二、填寫Kubernetes和Jenkins的配置信息
配置管理->系統配置->新增cloud。
按照圖中紅色框中填寫,其中Kubernetes命名空間填寫咱們Jenkins所在的命名空間。
備註:
若是鏈接測試失敗,極可能是權限問題,咱們就須要把ServiceAccount的憑證jenkins-sa添加進來。
三、配置Pod模板
另外須要掛載兩個主機目錄:
- /var/run/docker.sock:該文件是用於 Pod 中的容器可以共享宿主機的 Docker;
- /root/.kube:這個目錄掛載到容器的/root/.kube目錄下面這是爲了讓咱們可以在 Pod 的容器中可以使用 kubectl 工具來訪問咱們的 Kubernetes 集羣,方便咱們後面在 Slave Pod 部署 Kubernetes 應用;
避免一些權限不足,須要配置ServiceAccount
1.四、測試
一、建立一個項目
二、在標籤位置填寫咱們前面模板中定義的Label
三、直接在構建處執行shell進行測試
而後點擊構建,在終端能夠看到整個過程:
[root@master manifests]# kubectl get pod -n devops -w NAME READY STATUS RESTARTS AGE jenkins-6595ddd5d-m5fvd 1/1 Running 0 144m jenkins-slave-kkc2b 0/1 Pending 0 0s jenkins-slave-kkc2b 0/1 Pending 0 0s jenkins-slave-kkc2b 0/1 ContainerCreating 0 0s jenkins-slave-kkc2b 1/1 Running 0 3s jenkins-slave-kkc2b 1/1 Terminating 0 31s jenkins-slave-kkc2b 1/1 Terminating 0 31s
也能夠在jenkins裏看日誌以下:
2、Pipeline
2.一、簡介
Pipeline,簡單來講,就是一套運行在 Jenkins 上的工做流框架,將原來獨立運行於單個或者多個節點的任務鏈接起來,實現單個任務難以完成的複雜流程編排和可視化的工做。
Jenkins Pipeline 有幾個核心概念:
- Node:節點,一個 Node 就是一個 Jenkins 節點,Master 或者 Agent,是執行 Step 的具體運行環境,好比咱們以前動態運行的 Jenkins Slave 就是一個 Node 節點
- Stage:階段,一個 Pipeline 能夠劃分爲若干個 Stage,每一個 Stage 表明一組操做,好比:Build、Test、Deploy,Stage 是一個邏輯分組的概念,能夠跨多個 Node
- Step:步驟,Step 是最基本的操做單元,能夠是打印一句話,也能夠是構建一個 Docker 鏡像,由各種 Jenkins 插件提供,好比命令:sh 'make',就至關於咱們平時 shell 終端中執行 make 命令同樣。
Pipeline的使用:
- Pipeline 腳本是由 Groovy 語言實現的
- Pipeline 支持兩種語法:Declarative(聲明式)和 Scripted Pipeline(腳本式)語法
- Pipeline 也有兩種建立方法:能夠直接在 Jenkins 的 Web UI 界面中輸入腳本;也能夠經過建立一個 Jenkinsfile 腳本文件放入項目源碼庫中
- 通常咱們都推薦在 Jenkins 中直接從源代碼控制(SCMD)中直接載入 Jenkinsfile Pipeline 這種方法
2.二、建立
2.2.一、簡單的Pipeline
直接 在Jenkins的WEB UI上輸入腳本。
腳本內容:
node { stage('Clone') { echo "1.Clone Stage" } stage('Test') { echo "2.Test Stage" } stage('Build') { echo "3.Build Stage" } stage('Deploy') { echo "4. Deploy Stage" } }
而後保存--> 點擊構建--> 觀察日誌
輸出符合咱們腳本內容。
2.2.二、在slave中運行Pipeline
上面對Jenkins的Pipeline作了簡單的測試,可是其並未在咱們的Slave中運行,若是要在Slave中運行,其就要使用咱們前面添加的Label,以下:
node('joker-jnlp') { stage('Clone') { echo "1.Clone Stage" } stage('Test') { echo "2.Test Stage" } stage('Build') { echo "3.Build Stage" } stage('Deploy') { echo "4. Deploy Stage" } }
而後咱們保存並點擊構建,觀察Pod的變化:
[root@master ~]# kubectl get pod -n devops -w NAME READY STATUS RESTARTS AGE jenkins-6595ddd5d-m5fvd 1/1 Running 0 2d23h jenkins-slave-vq8wf 0/1 Pending 0 0s jenkins-slave-vq8wf 0/1 Pending 0 0s jenkins-slave-vq8wf 0/1 ContainerCreating 0 0s jenkins-slave-vq8wf 1/1 Running 0 2s jenkins-slave-vq8wf 1/1 Terminating 0 27s jenkins-slave-vq8wf 1/1 Terminating 0 27s
咱們能夠看到其依據咱們定義的模板動態生成了jenkins-slave的Pod,咱們在Jenkins的日誌中查看:
能夠看到兩個的名字是同樣的。
2.2.三、部署完整應用
部署應用的流程以下:
- 編寫代碼
- 測試
- 編寫 Dockerfile
- 構建打包 Docker 鏡像
- 推送 Docker 鏡像到倉庫
- 編寫 Kubernetes YAML 文件
- 更改 YAML 文件中 Docker 鏡像 TAG
- 利用 kubectl 工具部署應用
因此基本的Pipeline腳本框架應該以下:
node('joker-jnlp') { stage('Clone') { echo "1.Clone Stage" } stage('Test') { echo "2.Test Stage" } stage('Build') { echo "3.Build Docker Image Stage" } stage('Push') { echo "4.Push Docker Image Stage" } stage('YAML') { echo "5. Change YAML File Stage" } stage('Deploy') { echo "6. Deploy Stage" } }
第一步:克隆代碼
stage('Clone') { echo "1.Clone Stage" git url: "https://github.com/baidjay/jenkins-demo.git" script { build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() } echo "${build_tag}" }
咱們這裏採用和git commit的記錄爲鏡像的 tag,這裏有一個好處就是鏡像的 tag 能夠和 git 提交記錄對應起來,也方便往後對應查看。可是因爲這個 tag 不僅是咱們這一個 stage 須要使用,下一個推送鏡像是否是也須要,因此這裏咱們把這個 tag 編寫成一個公共的參數,把它放在 Clone 這個 stage 中。
第二步:測試
stage('Test') { echo "2.Test Stage" }
測試能夠是單測,也能夠是工具,咱們這裏就簡單存在這個步驟。
第三步:構建鏡像
stage('Build') { echo "3.Build Docker Image Stage" sh "docker build -t registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag} ." }
這一步咱們就使用到上面定義的build_tag變量。
第四步:推送鏡像
stage('Push') { echo "4.Push Docker Image Stage" sh "docker login --username=www.565361785@qq.com registry.cn-hangzhou.aliyuncs.com -p xxxxx" sh "docker push registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag}" }
配置Jenkins,隱藏用戶名密碼信息:
其中ID:AliRegistry 是咱們後面要用的值。
這樣咱們上面的腳本就能夠定義以下:
stage('Push') { echo "4.Push Docker Image Stage" withCredentials([usernamePassword(credentialsId: 'AliRegistry', passwordVariable: 'AliRegistryPassword', usernameVariable: 'AliRegistryUser')]) { sh "docker login -u ${AliRegistryUser} registry.cn-hangzhou.aliyuncs.com -p ${AliRegistryPassword}" sh "docker push registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag}" } }
注意咱們這裏在 stage 中使用了一個新的函數withCredentials,其中有一個 credentialsId 值就是咱們剛剛建立的 ID 值,而對應的用戶名變量就是 ID 值加上 User,密碼變量就是 ID 值加上 Password,而後咱們就能夠在腳本中直接使用這裏兩個變量值來直接替換掉以前的登陸 docker hub 的用戶名和密碼,如今是否是就很安全了,我只是傳遞進去了兩個變量而已,別人並不知道個人真正用戶名和密碼,只有咱們本身的 Jenkins 平臺上添加的才知道。
第五步:更改YAML文件
stage('YAML') { echo "5. Change YAML File Stage" sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml" sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s.yaml" }
其YAML文件爲(YAML文件放在項目根目錄):
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: jenkins-demo spec: template: metadata: labels: app: jenkins-demo spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:<BUILD_TAG> imagePullPolicy: IfNotPresent name: jenkins-demo env: - name: branch value: <BRANCH_NAME>
第六步:部署
部署階段咱們增長人工干預,可能須要將該版本先發布到測試環境、QA 環境、或者預覽環境之類的,總之直接就發佈到線上環境去仍是挺少見的,因此咱們須要增長人工確認的環節,通常都是在 CD 的環節才須要人工干預,好比咱們這裏的最後兩步,咱們就能夠在前面加上確認,好比:
咱們將YAML這一步改成:
stage('YAML') { echo "5. Change YAML File Stage" def userInput = input( id: 'userInput', message: 'Choose a deploy environment', parameters: [ [ $class: 'ChoiceParameterDefinition', choices: "Dev\nQA\nProd", name: 'Env' ] ] ) echo "This is a deploy step to ${userInput.Env}" sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml" sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s.yaml" sh "sed -i 's#cnych/jenkins-demo#registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo#' k8s.yaml" }
而後再部署階段:
stage('Deploy') { echo "6. Deploy Stage" if (userInput.Env == "Dev") { // deploy dev stuff } else if (userInput.Env == "QA"){ // deploy qa stuff } else { // deploy prod stuff } sh "kubectl apply -f k8s.yaml" }
因爲這一步也屬於部署的範疇,因此咱們能夠將最後兩步都合併成一步,咱們最終的Pipeline腳本以下:
node('joker-jnlp') { stage('Clone') { echo "1.Clone Stage" git url: "https://github.com/baidjay/jenkins-demo.git" script { build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() } echo "${build_tag}" } stage('Test') { echo "2.Test Stage" } stage('Build') { echo "3.Build Docker Image Stage" sh "docker build -t registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag} ." } stage('Push') { echo "4.Push Docker Image Stage" withCredentials([usernamePassword(credentialsId: 'AliRegistry', passwordVariable: 'AliRegistryPassword', usernameVariable: 'AliRegistryUser')]) { sh "docker login -u ${AliRegistryUser} registry.cn-hangzhou.aliyuncs.com -p ${AliRegistryPassword}" sh "docker push registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag}" } } stage('Deploy') { echo "5. Change YAML File Stage" def userInput = input( id: 'userInput', message: 'Choose a deploy environment', parameters: [ [ $class: 'ChoiceParameterDefinition', choices: "Dev\nQA\nProd", name: 'Env' ] ] ) echo "This is a deploy step to ${userInput}" sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml" sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s.yaml" echo "6. Deploy Stage" if (userInput == "Dev") { // deploy dev stuff } else if (userInput == "QA"){ // deploy qa stuff } else { // deploy prod stuff } sh "kubectl apply -f k8s.yaml -n default" } }
而後構建面板以下:
而後查看Pod日誌以下:
[root@master jenkins]# kubectl logs jenkins-demo-789fdc6878-5pzbx Hello, Kubernetes!I'm from Jenkins CI!
2.2.四、Jenkinsfile
萬里長征,貌似咱們的任務完成了,其實否則,咱們這裏只是完成了一次手動的添加任務的構建過程,在實際的工做實踐中,咱們更多的是將 Pipeline 腳本寫入到 Jenkinsfile 文件中,而後和代碼一塊兒提交到代碼倉庫中進行版本管理。如今咱們將上面的 Pipeline 腳本拷貝到一個 Jenkinsfile 中,將該文件放入上面的 git 倉庫中,可是要注意的是,如今既然咱們已經在 git 倉庫中了,是否是就不須要 git clone 這一步驟了,因此咱們須要將第一步 Clone 操做中的 git clone 這一步去掉。
以下:
node('joker-jnlp') { stage('Prepare') { echo "1.Prepare Stage" script { build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() } echo "${build_tag}" } stage('Test') { echo "2.Test Stage" } stage('Build') { echo "3.Build Docker Image Stage" sh "docker build -t registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag} ." } stage('Push') { echo "4.Push Docker Image Stage" withCredentials([usernamePassword(credentialsId: 'AliRegistry', passwordVariable: 'AliRegistryPassword', usernameVariable: 'AliRegistryUser')]) { sh "docker login -u ${AliRegistryUser} registry.cn-hangzhou.aliyuncs.com -p ${AliRegistryPassword}" sh "docker push registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag}" } } stage('Deploy') { echo "5. Change YAML File Stage" def userInput = input( id: 'userInput', message: 'Choose a deploy environment', parameters: [ [ $class: 'ChoiceParameterDefinition', choices: "Dev\nQA\nProd", name: 'Env' ] ] ) echo "This is a deploy step to ${userInput}" sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml" sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s.yaml" echo "6. Deploy Stage" if (userInput == "Dev") { // deploy dev stuff } else if (userInput == "QA"){ // deploy qa stuff } else { // deploy prod stuff } sh "kubectl apply -f k8s.yaml -n default" } }
而後咱們更改上面的 jenkins-demo 這個任務,點擊 Configure -> 最下方的 Pipeline 區域 -> 將以前的 Pipeline Script 更改爲 Pipeline Script from SCM,而後根據咱們的實際狀況填寫上對應的倉庫配置,要注意 Jenkinsfile 腳本路徑。
在實際的項目中,每每一個代碼倉庫都會有不少分支的,好比開發、測試、線上這些分支都是分開的,通常狀況下開發或者測試的分支咱們但願提交代碼後就直接進行 CI/CD 操做,而線上的話最好增長一我的工干預的步驟,這就須要 Jenkins 對代碼倉庫有多分支的支持,固然這個特性是被 Jenkins 支持的。
而後新建一個 Jenkinsfile 文件,配置以下:
node('joker-jnlp') { stage('Prepare') { echo "1.Prepare Stage" checkout scm script { build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() if (env.BRANCH_NAME != 'master') { build_tag = "${env.BRANCH_NAME}-${build_tag}" } } } stage('Test') { echo "2.Test Stage" } stage('Build') { echo "3.Build Docker Image Stage" sh "docker build -t registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag} ." } stage('Push') { echo "4.Push Docker Image Stage" withCredentials([usernamePassword(credentialsId: 'AliRegistry', passwordVariable: 'AliRegistryPassword', usernameVariable: 'AliRegistryUser')]) { sh "docker login -u ${AliRegistryUser} registry.cn-hangzhou.aliyuncs.com -p ${AliRegistryPassword}" sh "docker push registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag}" } } stage('Deploy') { echo "5. Deploy Stage" if (env.BRANCH_NAME == 'master') { input "確認要部署線上環境嗎?" } sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml" sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s.yaml" sh "kubectl apply -f k8s.yaml --record" } }
在第一步中咱們增長了checkout scm命令,用來檢出代碼倉庫中當前分支的代碼,爲了不各個環境的鏡像 tag 產生衝突,咱們爲非 master 分支的代碼構建的鏡像增長了一個分支的前綴,在第五步中若是是 master 分支的話咱們才增長一個確認部署的流程,其餘分支都自動部署,而且還須要替換 k8s.yaml 文件中的環境變量的值。
3、BlueOcean
咱們這裏使用 BlueOcean 這種方式來完成此處 CI/CD 的工做,BlueOcean 是 Jenkins 團隊從用戶體驗角度出發,專爲 Jenkins Pipeline 從新設計的一套 UI 界面,仍然兼容之前的 fressstyle 類型的 job,BlueOcean 具備如下的一些特性:
- 連續交付(CD)Pipeline 的複雜可視化,容許快速直觀的瞭解 Pipeline 的狀態
- 能夠經過 Pipeline 編輯器直觀的建立 Pipeline
- 須要干預或者出現問題時快速定位,BlueOcean 顯示了 Pipeline 須要注意的地方,便於異常處理和提升生產力
- 用於分支和拉取請求的本地集成能夠在 GitHub 或者 Bitbucket 中與其餘人進行代碼協做時最大限度提升開發人員的生產力。
BlueOcean 能夠安裝在現有的 Jenkins 環境中,也可使用 Docker 鏡像的方式直接運行,咱們這裏直接在現有的 Jenkins 環境中安裝 BlueOcean 插件:登陸 Jenkins Web UI -> 點擊左側的 Manage Jenkins -> Manage Plugins -> Available -> 搜索查找 BlueOcean -> 點擊下載安裝並重啓
3.一、建立Pipeline
點擊建立:
獲取Token的步驟:
而後獲取Token:
建立完成以下所示: