前面介紹採用 Jenkinsfile + KubernetesPod.yaml 方式進行部署項目(Rancher 構建 CI/CD 自動化流程 - 動態配置 Jenkins-slave(一)),maven、kubectl 等容器工具須要在 KubernetesPod.yaml 中定義,一同存放在代碼倉庫中託管,比較繁瑣。html
這裏採用 Jenkinsfile + docker in docker 方式進行部署,把 maven 等工具都運行在 docker 容器中,這樣減小了 yaml 文件,相對更加簡潔方便。linux
Rancher 2.2.7 (部署Rancher參考以前文章:離線安裝 Rancher2.2.4 HA 集羣)git
Jenkins 2.176.2 github
在 rancher 中部署 jenkins 服務docker
工做負載 -> PVCjson
jenkins程序家目錄PVC:pvc-jenkins-home
maven緩存PVC:pvc-jenkins-maven
資源 -> 配置映射緩存
名稱:jenkins-master 鍵:JAVA_OPTS 值: -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85 -Duser.timezone=Asia/Shanghai
做爲環境變量傳進jenkins,前三個值定義的是slaves生成等待時間(https://github.com/jenkinsci/kubernetes-plugin/blob/master/README_zh.md),最後一個值是jenkins的時區。負載均衡
工做負載 -> 部署服務curl
名稱:jenkins-master Docker鏡像:jenkinsci/blueocean:latest 命名空間:jenkinsci
環境變量:類型:Config Map,源:jenkins-master,值:All 數據卷掛載:pvc(pvc-jenkins-home) -> 容器路徑 /var/jenkins_home -> 子路徑 aliyun-jenkins(pvc中的目錄)
說明:由於我是把原來 jenkins 遷移到了pvc中,因此有子路徑,新部署的話不用子路徑。maven
名稱:jenkins-master 主機名:jenkins.wmq.com 服務:jenkins-master 容器端口:8080
jenkins.wmq.com 解析到 ingress lb 的 ip 地址
系統管理 -> 插件管理
Kubernetes
Kubernetes Cli
執行者數量:0 新增一個雲:Kubernetes
名稱:kubernetes Kubernetes 地址:https://kubernetes.default Kubernetes 命名空間:jenkinsci 憑據:cicd集羣帳號 Jenkins 地址:http://jenkins-master:8080 Pod Labels:鍵:jenkins,值:slave Pod Retention:Never Seconds to wait for pod to be running:600 默認提供的模板名稱:jenkins-slave
憑聽說明:類型:Secret text,Secret:rancher的cicd集羣中的配置文件中的token,ID:cicd,描述:cicd集羣帳號
名稱:jenkins-slave 標籤列表:jenkins-slave 用法:儘量的使用這個節點
1)jnlp
名稱:jnlp //不能更名 Docker 鏡像:reg.nexus.wmq.com/rancher/jenkins-jnlp-slave-docker-kubectl:v1.14.5 工做目錄:/home/jenkins/agent 運行的命令:空 命令參數:${computer.jnlpmac} ${computer.name} EnvVars:Environment Variable (鍵:JENKINS_URL,值:http://jenkins-master.jenkinsci.svc.cluster.local:8080)
2)docker
名稱:docker Docker 鏡像:reg.nexus.wmq.com/tools/docker-dind-daemon 工做目錄:/home/jenkins/agent 運行的命令:空 命令參數:空 高級選項:勾選以最高權限運行 //docker in docker 必定要最高權限
1)掛載空目錄,讓jnlp和docker兩個容器共享/var/run目錄,這樣jnlp容器可使用docker.sock文件操做docker容器
類型:Empty Dir Volume 掛載路徑:/var/run
2)掛載pvc,提供maven容器的緩存(maven容器在Jenkinsfile中指定)
類型:Persistent Volume Claim 申明值:pvc-jenkins-maven 掛載路徑:/opt/data/aliyun-jenkins-maven
Pod Retention:Never 代理的空閒存活時間(分):10080 //一週 鏈接 Jenkins 的超時時間(秒):100 Show raw yaml in console:不勾選
說明:代理存活時間爲一週,由於每次agent啓動須要花費必定時間等待,爲了減小等待時間,增長agent存活時間,不會立馬自動銷燬。
上面配置Container Template用到了jnlp、docker鏡像都是含有定製的工具。
給jnlp鏡像添加docker、kubectl兩個命令,Dockerfile內容以下:
FROM jenkins/jnlp-slave ENV KUBECTL_VERSION=v1.14.5 USER root RUN echo "deb http://mirrors.163.com/debian/ stretch main" > /etc/apt/sources.list && \ echo "deb http://mirrors.163.com/debian/ stretch-updates main non-free contrib" >> /etc/apt/sources.list && \ echo "deb http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib" >> /etc/apt/sources.list RUN apt-get update && \ apt-get -y install apt-transport-https ca-certificates curl software-properties-common && \ curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/debian/gpg | apt-key add - && \ add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/debian $(lsb_release -cs) stable" && \ apt-get -y update && \ apt-get -y install docker-ce RUN curl -L https://www.cnrancher.com/download/kubernetes/linux-amd64-${KUBECTL_VERSION}-kubectl -o /usr/local/bin/kubectl \ && chmod +x /usr/local/bin/kubectl
說明:jnlp-slave 是基於 debian 系統,先更換安裝源,而後安裝 docker。kubectl 是用 rancher 提供的下載連接。
上傳鏡像到私有倉庫:
docker build -t jnlp-:v1.14.5 . docker tag jnlp-:v1.14.5 reg.nexus.wmq.com/rancher/jenkins-jnlp-slave-docker-kubectl:v1.14.5 docker push reg.nexus.wmq.com/rancher/jenkins-jnlp-slave-docker-kubectl:v1.14.5
因採用 docker in docker 鏡像,須要更換默認的鏡像倉庫,換成私有倉庫,構建會把鏡像緩存到私有倉庫,要否則每次構建都重新下載鏡像會很慢;後續 jenkinsfile 中定義的容器都運行該 docker 中,Dockerfile 內容以下:
FROM docker:dind USER root RUN mkdir /etc/docker ADD daemon.json /etc/docker/daemon.json
掛載的daemon.json內容以下:
{ "registry-mirrors": ["https://mirror.nexus.wmq.com"], "max-concurrent-downloads": 5, "max-concurrent-uploads": 5, "storage-driver": "overlay2", "storage-opts": ["overlay2.override_kernel_check=true"], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" } }
上傳鏡像到倉庫:
docker build -t docker:v1 . docker tag docker:v1 reg.nexus.wmq.com/tools/docker-dind-daemon docker push reg.nexus.wmq.com/tools/docker-dind-daemon
Jenkinsfile模板以下:
pipeline { agent none stages { stage('setting env') { agent any options { skipDefaultCheckout(true) } steps { script { env.NAMESPACE = "jenkins-test" env.PROJECT_NAME = "jenkins-test" env.IMAGE_NAME = "reg.nexus.wmqhealth.com/$NAMESPACE/$PROJECT_NAME/$BRANCH_NAME:build-$BUILD_NUMBER" } } } stage('package') { agent { docker { alwaysPull false image 'maven:3.6-alpine' args '-v /opt/data/aliyun-jenkins-maven:/root/.m2' } } steps { sh 'mvn package' stash(name: 'copy jar', includes: 'target/*.jar') } } stage('docker build') { agent any steps { unstash 'copy jar' script { def image = docker.build("$IMAGE_NAME", ".") withDockerRegistry([credentialsId:'docker-registry', url:"https://reg.wmq.com"]){ image.push() } } } } stage('deploy') { parallel { stage('prod') { agent any options { skipDefaultCheckout(true) } when { branch 'master' } steps { withKubeConfig(clusterName: 'production', contextName: 'production', credentialsId: 'kube-prod', namespace: '$NAMESPACE', serverUrl: 'https://rancher.wmq.com/k8s/clusters/c-x497w') { sh 'kubectl set image deployment/$PROJECT_NAME $PROJECT_NAME=$IMAGE_NAME --namespace $NAMESPACE' } } } stage('dev') { agent any options { skipDefaultCheckout(true) } when { not { branch 'master' } } steps { withKubeConfig(clusterName: 'develop', contextName: 'develop', credentialsId: 'kube-dev', namespace: '$NAMESPACE', serverUrl: 'https://rancher.wmq.com/k8s/clusters/c-xg99q') { sh 'kubectl set image deployment/$PROJECT_NAME $PROJECT_NAME=$IMAGE_NAME --namespace $NAMESPACE' } } } } } } options { buildDiscarder(logRotator(numToKeepStr: '5', artifactNumToKeepStr: '5')) } }
說明:
env.IMAGE_TAG:定義的是環境變量,全局可調用,需放置在前面
withKubeConfig:須要安裝 Kubernetes Cil 插件,能夠操做kubernetes
buildDiscarder:構建歷史保留次數