上一篇文章中已經安裝好 jenkins,此次咱們來實現動態 slave。node
當咱們使用動態 slave 時,每啓動一個 job 都會建立一個 pod,其中這個 pod 的主容器天然就是 jenkins slave。有主容器天然就有其餘容器,什麼狀況下會出現其餘容器呢?git
好比我得啓動一個 git 容器拉代碼,拉下來代碼以後須要使用 maven 進行構建,這時就須要啓動 maven 容器了。等你構建完了以後還得打成鏡像吧,還得上傳吧,因此還得須要 docker 容器。web
因此這樣一來一個 pod 中就有四個容器了,有意思的是,當你拉代碼以後,以後的容器都會將代碼目錄掛載進去,而且默認就在這個目錄下面工做。這樣一來就十分方便了,多個容器能夠如同一個容器般的操做。docker
可是你沒法掛載目錄進鏡像中,也就是說你打好的 war 包帶不出來,你只能打成鏡像或者上傳到 ftp 等。api
說了這麼多,相信你對其已經有了大體的瞭解,那讓咱們直接開整。tomcat
登陸 jenkins 以後,首先須要安裝 Kubernetes 這個插件,安裝完成以後,咱們點擊 Manage Jenkins -> Configure System -> Cloud -> add -> Kubernetes。markdown
開始新建一個雲:併發
Name
:kubernetes,這個名字隨意;Kubernetes URL
:https://kubernetes.default
;Disable https certificate check
:勾選;Credentials
:Add -> Jenkins
Domain
:Global credentials;Kind
:Kubernetes Service Account;Scope
:System;Jenkins URL
:若是你啓動的容器可以解析你的 jenkins 域名,那麼就寫域名(能夠是 http),不然就寫 service。我這裏使用 http://jenkins
,感受直接寫 service 更好;Jenkins tunnel
:和上面同樣的道理,我這裏使用 jenkins:50000
;Connection Timeout
:0;Read Timeout
:0;Concurrency Limit
:10,指定併發,應該是同時建立的 slave 的數量。只須要配置這些,其餘默認就好。dom
接着建立第一個 job,一個名爲 test 的 pipeline 任務。咱們直接來到 Pipeline 這裏,你這能夠直接將 pipeline 腳本貼在 Script 中,也可使用 Pipeline script from SCM
,將 jenkinsfile 放在 git/svn 上。socket
我這裏選擇將 jenkinsfile 放在 git 上,這樣的好處是每次你對 jenkinsfile 的修改都會記錄下來。
如下是 jenkinsfile 的內容:
def label = "test-${UUID.randomUUID().toString()}" podTemplate(label: label, yaml: """ apiVersion: v1 kind: Pod metadata: labels: jenkins: slave spec: imagePullSecrets: - name: nexus-pull containers: - name: jnlp image: registry.ntpstat.com:2222/jenkins/jnlp-slave:3.10-1-alpine args: - \$(JENKINS_SECRET) - \$(JENKINS_NAME) """ ) { node(label) { stage('test') { echo "test" } } } 複製代碼
說明:
因爲是從私有鏡像倉庫中拉鏡像,因此這裏我定義了一個 imagePullSecrets
,相信看了我前面文章的同窗都懂。動態 slave 狀況下,slave 節點必需要啓動,哪怕你以爲它啥也沒幹,因此這裏定義了 slave 這一個容器。
必須傳遞給 slave 容器兩個參數,由於 slave 容器在啓動以後必須鏈接 master,而這兩個參數是由 kubernetes 插件自動注入的。事實上,插件會傳遞多個參數,只不過其餘的咱們用不上而已。
由於只是測試,因此這裏就簡單的輸出 test,看看是否可以直接輸出。
保存以後回到主界面以後,直接點擊構建 test 任務,過會就可以看到在左側出現一個新的 slave,一開始是離線狀態。
等會它就消失了,由於構建結束。咱們能夠直接點擊進入任務中查看。
能夠看出編譯成功。
測試成功以後,咱們直接實戰。我會首先使用 git 鏡像拉取項目代碼,而後使用 maven 構建。因爲 maven 鏡像配置文件是默認的,因此我會使用 configMap 建立一個我線上實現的配置文件,掛載到 Maven 鏡像中覆蓋其配置文件。
maven 編譯過程當中會從 nexus 下載依賴包,雖然配置文件中指定了 nexus 的地址,可是若是每次構建下載的依賴包都放在容器中,那麼這次構建完畢以後這些下載的依賴包就會被清掉,沒法二次利用。因此咱們將 nfs 的一個目錄直接映射到 maven 鏡像的 /root/.m2
目錄下。
因爲此時用來進行構建實戰的項目有些複雜,它會生成五個包,所以這裏會有循環的操做。循環生成五個鏡像,併發布到私有倉庫。
在以後的發佈中,我會啓動 docker 鏡像,可是會將本地的 docker 域套接字映射進去,這樣 docker 鏡像倉庫的操做和宿主機就沒什麼區別了。
def label = "maven-${UUID.randomUUID().toString()}" def warDir = "warDir" def dirPrefix = "hehe_" def targetDir = "/target" podTemplate(label: label, yaml: """ apiVersion: v1 kind: Pod metadata: labels: jenkins: slave spec: imagePullSecrets: - name: nexus-pull containers: - name: jnlp image: registry.ntpstat.com:2222/jenkins/jnlp-slave:3.10-1-alpine args: - \$(JENKINS_SECRET) - \$(JENKINS_NAME) - name: git image: registry.ntpstat.com:2222/alpine/git command: - cat tty: true - name: maven image: registry.ntpstat.com:2222/maven:3-alpine command: - cat tty: true volumeMounts: - name: maven-xml mountPath: /usr/share/maven/conf/settings.xml readOnly: true subPath: settings.xml - name: maven-data mountPath: /root/.m2 - name: docker image: registry.ntpstat.com/library/docker:18.06 command: - cat tty: true volumeMounts: - name: docker-socket mountPath: /var/run/docker.sock readOnly: true volumes: - name: maven-xml configMap: name: maven-conf - name: maven-data nfs: server: registry.ntpstat.com path: /opt/kubernetes/maven-data - name: docker-socket hostPath: path: /var/run/docker.sock """ ) { wars = ['fuckGod-sync', 'fuckGod-job', 'fuckGod-mq', 'fuckGod-main', 'fuckGod-web'] node(label) { stage('拉代碼') { checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '19f20e6e-910e-42cd-b395-e4f82c76fd89', url: 'http://git.ntpstat.com/hehe/hehe.git']]]) container('git') { sh "cp Dockerfile /" version = sh(script: "git tag | tail -1", returnStdout: true).trim().split('-')[1] sh "git checkout version-${version}" sh "cp /Dockerfile ." } } stage('maven 編譯') { container('maven') { sh 'mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package -Dmaven.test.failure.ignore=true' wars.each { item -> dir(dirPrefix + item + targetDir) { sh "mkdir ${warDir}" sh "unzip *.war -d ${warDir}" } } } } stage('打鏡像') { container('docker') { withDockerRegistry(credentialsId: 'nexus-pull', url: 'https://registry.ntpstat.com') { wars.each { item -> dir(dirPrefix + item + targetDir) { imageName = "registry.ntpstat.com/tomcat/${item}:${version}" sh "cp ../../Dockerfile ." sh "docker build -t ${imageName} ." sh "docker push ${imageName}" } } } } } } } 複製代碼
從 gitlab/svn 上面拉代碼的語法可使用 Pipeline Syntax,選擇 checkout 自動生成。
爲了方便使用,我將 dockerfile 放在了項目的根目錄。
咱們這裏的 git 在上線前會打個 tag,所以我在拉代碼以後會切換到這個 tag 進行編譯。
其餘的也沒啥好說的了,相信你看看就能懂。