一、說明
1.1 說明
前面介紹采用 Jenkinsfile + KubernetesPod.yaml 方式進行部署項目(Rancher 構建 CI/CD 自動化流程 - 動態配置 Jenkins-slave(一)),maven、kubectl 等容器工具需要在 KubernetesPod.yaml 中定義,一同存放在代碼倉庫中托管,比較繁瑣。
這里采用 Jenkinsfile + docker in docker 方式進行部署,把 maven 等工具都運行在 docker 容器中,這樣減少了 yaml 文件,相對更加簡潔方便。
1.2 環境
Rancher 2.2.7 (部署Rancher參考之前文章:離線安裝 Rancher2.2.4 HA 集群)
Jenkins 2.176.2
二、部署 jenkins
在 rancher 中部署 jenkins 服務
2.1 創建 PVC
工作負載 -> PVC
jenkins程序家目錄PVC:pvc-jenkins-home
maven緩存PVC:pvc-jenkins-maven
2.2 配置映射
資源 -> 配置映射
名稱: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的時區。
2.3 工作負載
工作負載 -> 部署服務
名稱:jenkins-master Docker鏡像:jenkinsci/blueocean:latest 命名空間:jenkinsci
環境變量:類型:Config Map,源:jenkins-master,值:All 數據卷掛載:pvc(pvc-jenkins-home) -> 容器路徑 /var/jenkins_home -> 子路徑 aliyun-jenkins(pvc中的目錄)
說明:因為我是把原來 jenkins 遷移到了pvc中,所以有子路徑,新部署的話不用子路徑。
2.4 負載均衡
名稱:jenkins-master 主機名:jenkins.wmq.com 服務:jenkins-master 容器端口:8080
2.5 域名解析
jenkins.wmq.com 解析到 ingress lb 的 ip 地址
三、配置jenkins
3.1 安裝插件
系統管理 -> 插件管理
Kubernetes
Kubernetes Cli
3.2 系統設置
3.2.1 系統設置
執行者數量:0 新增一個雲:Kubernetes
3.2.2 配置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集群賬號
3.2.3 配置Kubernetes Pod Template
名稱:jenkins-slave 標簽列表:jenkins-slave 用法:盡可能的使用這個節點
3.2.4 配置Container Template
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 一定要最高權限
3.2.5 配置掛載卷
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
3.2.6 其他配置
Pod Retention:Never 代理的空閑存活時間(分):10080 //一周 連接 Jenkins 的超時時間(秒):100 Show raw yaml in console:不勾選
說明:代理存活時間為一周,因為每次agent啟動需要花費一定時間等待,為了減少等待時間,增加agent存活時間,不會立馬自動銷毀。
四、docker鏡像制作
上面配置Container Template用到了jnlp、docker鏡像都是含有定制的工具。
4.1 jnlp鏡像
給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
4.2 docker鏡像
因采用 docker in docker 鏡像,后續 jenkinsfile 中定義的容器都運行該 docker 中。
1)需要更換默認的鏡像倉庫,換成私有倉庫,構建會把鏡像緩存到私有倉庫,要不然每次構建都從新下載鏡像會很慢;
2)添加 crond 命令到啟動項,並每天定時任務清理鏡像垃圾。
Dockerfile 內容如下:
FROM docker:dind USER root RUN mkdir /etc/docker ADD daemon.json /etc/docker/daemon.json
RUN sed -i "2a crond" /usr/local/bin/dockerd-entrypoint.sh
RUN crontab -l > crontab_list
RUN echo '0 3 * * * docker image prune -a -f --filter "until=24h" > /var/log/crontab.log 2>&1' >> crontab_list
RUN crontab crontab_list
掛載的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 文件
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:構建歷史保留次數