kubernetes中部署Jenkins並簡單使用


一、動態生成Slave

1.1、簡介

之前我們都是在物理機或者虛擬機上部署jenkins,但是這種部署方式會有一些難點,如下:

  • 主 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 也會自動刪除,恢復到最初狀態。


這種方式部署給我們帶來如下好處:

  • 服務高可用,當 Jenkins Master 出現故障時,Kubernetes 會自動創建一個新的 Jenkins Master 容器,並且將 Volume 分配給新創建的容器,保證數據不丟失,從而達到集群服務高可用。
  • 動態伸縮,合理使用資源,每次運行 Job 時,會自動創建一個 Jenkins Slave,Job 完成后,Slave 自動注銷並刪除容器,資源自動釋放,而且 Kubernetes 會根據每個資源的使用情況,動態分配 Slave 到空閑的節點上創建,降低出現因某節點資源利用率高,還排隊等待在該節點的情況。
  • 擴展性好,當 Kubernetes 集群的資源嚴重不足而導致 Job 排隊等待時,可以很容易的添加一個 Kubernetes Node 到集群中,從而實現擴展。

1.2、部署

1、創建PV、PVC,為Jenkins提供數據持久化:

---
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


2、創建角色授權

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


1、在Kubernetes中部署Jenkins,新建Deployment,jenkins-deploy.yaml

---
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


5、創建上面的資源清單

# kubectl apply -f jenkins-rbac.yaml
# kubectl apply -f jenkins-pvc.yaml
# kubectl apply -f jenkins-deploy.yaml


啟動如果報如下錯誤(因為我們容器里是以jenkins用戶啟動,而我們NFS服務器上是root啟動,所以沒有權限):

[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服務器上的目錄授權即可:

# chown -R 1000 /data/k8s/jenkins/jenkins


然后登錄網站,因為我們Service是采用NodePort類型,其端口為30002,我們直接在瀏覽器用這個端口訪問:
image.png
密碼可以通過如下命令獲得:

# cat /data/k8s/jenkins/secrets/initialAdminPassword 
12b503a274354e09a465b4f76664db70


然后安裝插件到安裝完成。

1.3、配置

1、安裝插件kubernetes
image.png


2、填寫Kubernetes和Jenkins的配置信息
配置管理->系統配置->新增cloud。
image.png
image.png
image.png
按照圖中紅色框中填寫,其中Kubernetes命名空間填寫我們Jenkins所在的命名空間。
備注:
如果連接測試失敗,很可能是權限問題,我們就需要把ServiceAccount的憑證jenkins-sa添加進來。


3、配置Pod模板
image.png
另外需要掛載兩個主機目錄:

  1. /var/run/docker.sock:該文件是用於 Pod 中的容器能夠共享宿主機的 Docker;
  2. /root/.kube:這個目錄掛載到容器的/root/.kube目錄下面這是為了讓我們能夠在 Pod 的容器中能夠使用 kubectl 工具來訪問我們的 Kubernetes 集群,方便我們后面在 Slave Pod 部署 Kubernetes 應用;


image.png
避免一些權限不足,需要配置ServiceAccount
image.png

1.4、測試

1、創建一個項目
image.png


2、在標簽位置填寫我們前面模板中定義的Label
image.png


3、直接在構建處執行shell進行測試
image.png


然后點擊構建,在終端可以看到整個過程:

[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里看日志如下:
image.png

二、Pipeline

2.1、簡介

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.2.1、簡單的Pipeline

直接 在Jenkins的WEB UI上輸入腳本。
image.png
image.png
腳本內容:

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"
  }
}


然后保存--> 點擊構建--> 觀察日志
image.png
輸出符合我們腳本內容。

2.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的日志中查看:
image.png
可以看到兩個的名字是一樣的。

2.2.3、部署完整應用

部署應用的流程如下:

  • 編寫代碼
  • 測試
  • 編寫 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,隱藏用戶名密碼信息:
image.png
其中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"
    }
}


然后構建面板如下:
image.png


然后查看Pod日志如下:

[root@master jenkins]# kubectl logs jenkins-demo-789fdc6878-5pzbx
Hello, Kubernetes!I'm from Jenkins CI!

2.2.4、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 腳本路徑。
image.png


在實際的項目中,往往一個代碼倉庫都會有很多分支的,比如開發、測試、線上這些分支都是分開的,一般情況下開發或者測試的分支我們希望提交代碼后就直接進行 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 文件中的環境變量的值。

三、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.1、創建Pipeline

點擊創建:
image.png
image.png


獲取Token的步驟:
image.png
image.png
image.png


然后獲取Token:
image.png


創建完成如下所示:
image.png


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM