golang微服务项目通用流水线
工作中随着业务越来越大,微服务的项目也越来越多,最开始的时候是一个服务一个流水线,然后还分了三个环境,也就是一个服务三个流水线,后面就越来越不利于管理维护了,因此,进行了一个改造整合
golang这边的微服务基本分成三类,service、schedule、mq,所以将所有流水线整合为三条通用流水线,再通过参数传递的形式,去构建每个服务
一、dockerfile和jenkinsfile
这是service里面的dockerfile和jenkinsfile,schedule、mq大同小异
dockerfile
FROM ccr.ccs.tencentyun.com/chens/golang:1.17.13
ENV ZBE_PATH /biz-code
ARG SERVICENAME=message
COPY $SERVICENAME /biz-code/$SERVICENAME
WORKDIR /biz-code
RUN chmod 777 $(echo `ls -l` |awk -F ' ' '{print $NF}')
USER root
RUN ls -l
CMD ./$(echo `ls -l` |awk -F ' ' '{print $NF}')
jenkinsfile
pipeline {
agent {
kubernetes {cloud 'kubernetes'
cloud 'kubernetes-test'
slaveConnectTimeout 1200
workspaceVolume hostPathWorkspaceVolume(hostPath:"/opt/workspace", readOnly: false)
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- args: [\'$(JENKINS_SECRET)\', \'$(JENKINS_NAME)\']
image: 'jenkins/jnlp-slave:latest-jdk11'
name: jnlp
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: "/etc/localtime"
name: "localtime"
readOnly: false
- command:
- "cat"
env:
- name: "LANGUAGE"
value: "en_US:en"
- name: "LC_ALL"
value: "en_US.UTF-8"
- name: "LANG"
value: "en_US.UTF-8"
image: "ccr.ccs.tencentyun.com/chens/golang:1.17.13"
imagePullPolicy: "IfNotPresent"
name: "build"
tty: true
volumeMounts:
- mountPath: "/etc/localtime"
name: "localtime"
- mountPath: "/go/pkg/"
name: "cachedir"
readOnly: false
- command:
- "cat"
env:
- name: "LANGUAGE"
value: "en_US:en"
- name: "LC_ALL"
value: "en_US.UTF-8"
- name: "LANG"
value: "en_US.UTF-8"
image: "registry.cn-beijing.aliyuncs.com/citools/kubectl:self-1.17"
imagePullPolicy: "IfNotPresent"
name: "kubectl"
tty: true
volumeMounts:
- mountPath: "/etc/localtime"
name: "localtime"
readOnly: false
- command:
- "cat"
env:
- name: "LANGUAGE"
value: "en_US:en"
- name: "LC_ALL"
value: "en_US.UTF-8"
- name: "LANG"
value: "en_US.UTF-8"
image: "registry.cn-beijing.aliyuncs.com/citools/docker:19.03.9-git"
imagePullPolicy: "IfNotPresent"
name: "docker"
tty: true
volumeMounts:
- mountPath: "/etc/localtime"
name: "localtime"
readOnly: false
- mountPath: "/var/run/docker.sock"
name: "dockersock"
readOnly: false
restartPolicy: "Never"
imagePullSecrets:
- name: qcloudregistrykey
nodeSelector:
build: "true"
securityContext: {}
volumes:
- hostPath:
path: "/var/run/docker.sock"
name: "dockersock"
- hostPath:
path: "/usr/share/zoneinfo/Asia/Shanghai"
name: "localtime"
- name: "cachedir"
hostPath:
path: "/opt/gopkg"
- name: "phpdir"
hostPath:
path: "/opt/phppkg"
'''
}
}
stages {
stage('Pulling Code') {
parallel {
stage('Pulling Code by Jenkins') {
when {
expression {
env.giteeBranch == null
}
}
steps {
git(changelog: true, poll: true, url:'https://gitee.com/chens-go/kobe.git', branch:"${BRANCH}", credentialsId: 'gitee-mima')
script {
COMMIT_ID = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()
TAG = BUILD_TAG + '-' + COMMIT_ID
println "Current branch is ${BRANCH}, Commit ID is ${COMMIT_ID}, Image TAG is ${TAG}"
}
}
}
stage('Pulling Code by trigger') {
when {
expression {
env.giteeBranch != null
}
}
steps {
git(url: 'https://gitee.com/chens-go/kobe.git', branch: env.giteeBranch, changelog: true, poll: true, credentialsId: 'gitee-mima')
script {
COMMIT_ID = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()
TAG = BUILD_TAG + '-' + COMMIT_ID
println "Current branch is ${env.giteeBranch}, Commit ID is ${COMMIT_ID}, Image TAG is ${TAG}"
}
}
}
}
}
stage('Building') {
steps {
container(name: 'build') {
sh """
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io,direct
go env -w GOPRIVATE=gitee.com/chens-go/jordan
export GIT_TERMINAL_PROMPT=1
go build -o ${SERVICENAME} services/${SERVICENAME}/${SERVICENAME}-service/cmd/${SERVICENAME}/main.go
chmod +x ${SERVICENAME}
cp -p ${SERVICENAME} build-work/k8s2/service
"""
}
}
}
stage('Docker build for creating image') {
environment {
HARBOR_USER = credentials('registry-secret')
}
steps {
container(name: 'docker') {
sh """
cd build-work/k8s2/service
echo ${HARBOR_USER_USR} ${HARBOR_USER_PSW} ${TAG}
docker login -u ${HARBOR_USER_USR} -p ${HARBOR_USER_PSW} ${HARBOR_ADDRESS}
docker build -t ${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${TAG} --build-arg SERVICENAME=${SERVICENAME} .
docker push ${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${TAG}
"""
}
}
}
stage('Deploying to K8s') {
environment {
MY_KUBECONFIG = credentials('k8s-config')
}
steps {
container(name: 'kubectl'){
sh """
/usr/local/bin/kubectl --kubeconfig $MY_KUBECONFIG set image deploy -l app=${KOBE_NAME} ${KOBE_NAME}=${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${TAG} -n $NAMESPACE
"""
}
}
}
}
environment {
COMMIT_ID = ""
HARBOR_ADDRESS = "ccr.ccs.tencentyun.com"
REGISTRY_DIR = "chens"
IMAGE_NAME = "kobe"
NAMESPACE = "${ENV}"
TAG = ""
KOBE_NAME = "${SERVICENAME}"
}
parameters {
gitParameter(branch: '', branchFilter: 'origin/(.*)', defaultValue: "${BRANCH}", description: 'Branch for build and deploy', name:'BRANCH', quickFilterEnabled: false, selectedValue: 'NONE', sortMode: 'NONE', tagFilter: '*', type: 'PT_BRANCH')
}
}
二、参数传递
流水线里面需要传递三个参数
具体配置
最后的这个build-work/k8s2/service/Jenkinsfile
,是jenkinsfile在项目代码中的路径
所有参数名称和路径皆可根据自己项目来定义
三、写在最后
这里面有些语法看着很离谱,其实是我在做的过程中踩的一些坑,你们可以试试不那样写会发生什么,当然也有可能还有别的解决方法,可多尝试