之前一直用gitlab
来CI/CD
,去年换了个坑,新厂这边如今是用jenkins
来CI/CD
,之前听过jenkins
,但一直没有用过,虽然建议过用gitlab
的CI/CD
,但因为各类历史包袱,你们仍是坚持用jenkins
,既然用这个,我固然不能对这玩意彻底不了解啊,开始各类搜罗资料,了解jenkins
相关的知识。前端
公司的流水线主要用的是这种,这个流水线有几个问题:node
1. 对构建机有必定的依赖,好比你要执行`npm install`或者`go mod vendor`,构建机必需要安装了`node`和`go`环境,若是对版本有要求就更尴尬了
2. 若是同一个项目,我想指定分支来构建,这里不太好处理
复制代码
这个流水线挺好的,能够动态设置pipeline script
内容,用来作DevOps
开发CI/CD
挺好的,根据用户设置,用接口动态修改pipeline script
的内容,不过也有一些小问题:git
1. 若是同一个项目,我想指定分支来构建,这里不太好处理
复制代码
多分支流水线这个如今是我如今主要用的,若是你的项目有多个分支,每一个分支下都有jenkinsfile
,构建的时候会根据你选的分支来构建,这样用来构建、发布不一样的分支就很方便golang
流水线的问题解决了,如今的问题是怎么构建的问题了,基于之前用.gitlab-ci.yml
的经验,这里我仍是打算用docker
来构建,有几处好处:docker
1. 对构建机的依赖比较小,只要有docker就能够了
2. 不用担忧构建环境被破坏问题,添加新构建机也很方便
复制代码
这里要先安装jenkins
插件docker pipeline
,而且在构建机安装docker
,jenkins
的pipeline script
的方法,能够看官方文档,里面写的很清楚了,如下是目前的jenkinsfile
npm
jenkinsfile
pipeline {
environment {
// 改这几个就能够了
PROJECT = 'example-front'
DEPLOYMENT_NAME = 'example-front-deployment'
// 改这几个就能够了
DOCKERHUB = 'xxxx.com'
BUILD_TIME = sh(script:"date '+%Y%m%d%H%M'", returnStdout: true).trim()
// LABEL = 'nodelabel' // 若是要指定构建机,请设置构建机 label
IMAGE_TAG = "${DOCKERHUB}/${PROJECT}:${BRANCH_NAME}-${BUILD_TIME}-${BUILD_ID}"
// 我这用了apollo 配置服务,配置服务地址写到 jenkins的凭据里了
APOLLO_QA = credentials('APOLLO_QA')
APOLLO_PROD = credentials('APOLLO_PROD')
}
agent any
options {
retry(3)
}
stages {
stage('init') {
steps {
script {
// 初始化环境变量,这样后面就不用写 when 指令了
if (env.BRANCH_NAME == 'test') {
env.APOLLO = APOLLO_QA
env.NAMESPACE = 'qa-ns'
env.K8SCONFIG = '/root/.kube/qa-ns.kubeconfig'
}else if (env.BRANCH_NAME == 'master') {
env.APOLLO = APOLLO_PROD
env.NAMESPACE = 'prod-ns'
env.K8SCONFIG = '/root/.kube/prod-ns.kubeconfig'
}
}
}
}
stage('build-dist') {
agent {
docker {
image 'node:14.17.0'
// label "${LABEL}" // 若是要指定构建机,请设置构建机 label
}
}
steps {
sh 'npm install --registry=https://registry.npm.taobao.org/ && npm run build'
// 把构建的制品存起来,把 fingerprint 设置为 true,后期若是有问题,
// 能够经过 Check File Fingerprint 快速定位到构建制品的流水线
archiveArtifacts artifacts: 'dist/', fingerprint: true
}
}
stage('build-image') {
agent {
docker {
image 'docker:19.03.12'
args '-v /var/run/docker.sock:/var/run/docker.sock -v /root/.docker:/root/.docker'
// label "${LABEL}" // 若是要指定构建机,请设置构建机 label
}
}
steps {
sh "docker build ."
// registry已经在构建机登陆了,经过 -v /root/.docker:/root/.docker 把登陆信息共享过来了,
// 这里没有办法,我没有 registry 的帐号信息,
// 建议你们把 registry 的信息写到 jenkins 的凭据里面,经过 credentials 来读取,
// 而后用 docker login 登陆
sh "docker push ${IMAGE_TAG}"
}
}
stage('deploy') {
agent {
docker {
image 'roffe/kubectl:v1.13.2'
// 这里是共享k8s信息,缘由同上,没有帐号,建议同上,用凭据来管理
args '-v /root/.kube:/root/.kube'
// label "${LABEL}" // 若是要指定构建机,请设置构建机 label
}
}
steps {
sh "kubectl --kubeconfig ${K8SCONFIG} -n ${NAMESPACE} set image deployment/${DEPLOYMENT_NAME} ${PROJECT}=${IMAGE_TAG}"
}
}
}
}
复制代码
jenkinsfile
pipeline {
environment {
PROJECT = 'example-front'
DEPLOYMENT_NAME = 'example-front-deployment'
DOCKERHUB = 'xxxx.com'
BUILD_TIME = sh(script:"date '+%Y%m%d%H%M'", returnStdout: true).trim()
IMAGE_TAG = "${DOCKERHUB}/${PROJECT}:${BRANCH_NAME}-${BUILD_TIME}-${BUILD_ID}"
APOLLO_QA = credentials('APOLLO_QA')
APOLLO_PROD = credentials('APOLLO_PROD')
}
agent any
options {
retry(3)
}
stages {
stage('init') {
steps {
script {
if (env.BRANCH_NAME == 'test') {
env.APOLLO = APOLLO_QA
env.NAMESPACE = 'qa-ns'
env.K8SCONFIG = '/root/.kube/qa-ns.kubeconfig'
}else if (env.BRANCH_NAME == 'master') {
env.APOLLO = APOLLO_PROD
env.NAMESPACE = 'prod-ns'
env.K8SCONFIG = '/root/.kube/prod-ns.kubeconfig'
}
}
}
}
stage('build-main') {
agent {
docker {
image 'golang:1.14-alpine'
}
}
steps {
sh 'go mod vendor'
sh 'go build -o main main.go'
archiveArtifacts artifacts: 'main', fingerprint: true
}
}
stage('build-image') {
agent {
docker {
image 'docker:19.03.12'
args '-v /var/run/docker.sock:/var/run/docker.sock -v /root/.docker:/root/.docker'
}
}
steps {
sh "docker build ."
sh "docker push ${IMAGE_TAG}"
}
}
stage('deploy') {
agent {
docker {
image 'roffe/kubectl:v1.13.2'
}
}
steps {
sh "kubectl --kubeconfig ${K8SCONFIG} -n ${NAMESPACE} set image deployment/${DEPLOYMENT_NAME} ${PROJECT}=${IMAGE_TAG}"
}
}
}
}
复制代码
如今咱们点一下构建,就会依次执行这些job
,最终更新k8s
的容器后端
有些构建任务,若是想并行执行的话,能够了解下 parallel
指令markdown