前言
之前我们已经将jenkins agent环境搭建好(基于docker或k8s动态创建),并且已经通过流水线跑通了一个Demo示例,基于前面搭建的环境,实际项目中针对后端java项目如何通过agent进行发布呢? 其实主要思路还是跟以前一样的:
- 拉代码
- maven构建打包
- 构建镜像
- 上传至私有镜像仓库
- 部署服务
只不过现在这些事情由jenkins master全权交给agent来做, agent做完即销毁。
注意:k8s的方式中,jenkins agent是一个pod,而一个pod可以是一组容器,在这一个pod中这一组容器的数据是共享的,所以系统默认会有一个jnlp的容器用来agent与master连接这是一个必须有的容器,我们还可以在这个pod中加一个maven的容器来实现maven构建打包的阶段。当然了,也可以将这个jnlp容器重构,加入docker,maven等相关工具只用这个镜像去完成也可以,不过目前我还没这么做,只是聚集需要的容器在一个pod中作为一个整体agent去完成的。
思路
- 创建流水线任务
- jenkins管理节点中创建pod模板,并配置maven容器与docker容器
- pod配置-挂载卷 (主要为/root/.m2 以及 kubectl 和.kube下的配置)
- 配置 凭据(登录habor的凭据,git拉取代码的凭据)
- 流水线代码
- 测试调试发布
一.创建流水线任务
新建任务--流水线--填写名称(略)
二.创建Pod模板
1. 模板配置
系统管理-->节点管理-->Configure Clouds-->Pod Temlates-->填写pod模板名称-->detalis展开更详细配置
-->填写命名空间-->agent标签列表(后期通过这个标签名去调用相应的一组agent pod来完成任务)

2. 容器配置
maven打包构建需要maven容器,docker打包上传镜像需要docker容器


三. 挂载卷
有些目录或者数据需要挂载到pod中,这里我是有一台nfs服务器(搭建过程略),如果没有nfs存储服务器那么就需要k8s集群中每台机器都需要放一份相同数据了哦~
需要挂载:maven构建需要的/root/.m2; kubectl以及链接的config文件; 宿主机上的docker.sock;rancher工具(看需求);
注意:我们配置了docker容器,经过测试如果不将docker.sock进程挂载进去的话,是无法在docker中操作docker的。
这样挂出来也是比较省事的方法,也是用的比较多的方案,这种操作跟宿主机的docker是同步的。还有一种叫dind,有兴趣的可以自己了解一下。
- 查看nfs共享的目录里都有哪些东西?
# nfs共享目录
# showmount -e
Export list for k8s01.test.hw:
/opt/jenkins_agent_data *
/opt/jenkins_agent_data# ls -a
. .. _data .kube rancher-tools .ssh.bak
/opt/jenkins_agent_data/_data下放的是/root/.m2的数据,将其挂载出来避免每次启动maven agent都会拉一遍所有依赖
/opt/jenkins_agent_data/_data
root@k8s01.test.hw:/opt/jenkins_agent_data/_data# ls
copy_reference_file.log repository settings-docker.xml settings.xml settings.xml-bak-20211117 settings.xml-bak-20211118 settings.xml.bak_20220711
.kube包含了kubectl工具和k8s集群的config文件,用于在agent直接可发布项目至k8s集群
root@k8s01.test.hw:/opt/jenkins_agent_data/.kube# ls
cache config config.dev config.uat kubectl
rancher-tools中为rancher工具,跟kubectl一样,是用来发布项目至rancher集群中(如果你没有rancher集群项目请忽略)
root@k8s01.test.hw:/opt/jenkins_agent_data/rancher-tools# ls
rancher
- jenkins-pod模板--容器配置处,添加卷(注意类型)


四. 配置凭据
系统管理---安全---Manage Credentials
需要配2个凭据:
- 拉代码用到访问gitlab项目的凭据
- docker推镜像用到的Docker login凭据
以下为docker凭据配置,gitlab配置的方式同理


五. Pipeline编写
发布至k8s
agent.label这里要写之前配置的pod标签
pipeline {
agent {
label 'mavenpod'
}
options {
skipDefaultCheckout()
}
environment {
IMAGE_REPO = "harbor.hw.xxxx:5000/k8s-test"
PROJECT_NAME = "health-cloud-evaluation"
RUN_ENV = "k8s-dev"
}
stages {
stage('get code'){
steps{
git branch: 'tianye-cicd', credentialsId: '248e1fa0-6165-4a81-8297-4107e413207c', url: 'https://gitlab.xxxx.com/java-dev/health-cloud-biz/health-cloud-evaluation.git'
//git branch: 'dev', credentialsId: '248e1fa0-6165-4a81-8297-4107e4132017c', url: 'git@gitlab.xxxx.com:java-dev/health-cloud-biz/health-cloud-evaluation.git'
// get image-version
script {
env.GIT_COMMIT_MSG = sh (script: 'git rev-parse --short=8 HEAD', returnStdout: true).trim()
IMAGE_VERSION = "${GIT_COMMIT_MSG}-${RUN_ENV}"
IMAGE_NAME = "${IMAGE_REPO}/${PROJECT_NAME}:${IMAGE_VERSION}"
}
}
}
stage('maven build'){
steps{
container('maven-agent') {
sh 'mvn clean package -DskipTests -Pdev'
}
}
}
stage('build image'){
steps{
container('docker-agent') {
withCredentials([usernamePassword(credentialsId: 'ee78c0ce-d905-4c2c-bbf0-928f1a9f17d0', passwordVariable: 'docker_password', usernameVariable: 'docker_username')]) {
sh 'docker login -u ${docker_username} -p ${docker_password} ${IMAGE_REPO}'
sh "docker build -t ${PROJECT_NAME}:${IMAGE_VERSION} -f deploy/test/Dockerfile ."
sh "docker tag ${PROJECT_NAME}:${IMAGE_VERSION} ${IMAGE_REPO}/${PROJECT_NAME}:${IMAGE_VERSION}"
sh "docker push ${IMAGE_REPO}/${PROJECT_NAME}:${IMAGE_VERSION}"
sh 'echo build images success'
}
}
}
}
stage('deploy to k8s'){
steps{
sh "sed -i \"s#IMAGE_NAME#${IMAGE_NAME}#g\" deploy/test/k8sdeployment.yaml"
sh "/home/jenkins/.kube/kubectl apply -f deploy/test/k8sdeployment.yaml"
}
}
stage('health-check'){
steps{
sh '/home/jenkins/.kube/kubectl rollout status -n nacos deployment ${PROJECT_NAME}'
}
}
}
}
发布至Rancher
pipeline {
agent {
label 'mavenpod'
}
options {
skipDefaultCheckout()
}
environment {
IMAGE_REPO = "harbor.hw.xxx.com:5000/k8s-test"
PROJECT_NAME = "health-cloud-evaluation"
RUN_ENV = "dev"
OLD_IMAGE = "harbor.hw.xxxx.com:5000/health-cloud-server/health-cloud-evaluation:latest"
}
stages {
stage('get code'){
steps{
git branch: 'tianye-cicd', credentialsId: '248e1fa0-6165-4a81-8297-4107e4131207c', url: 'https://gitlab.xxxx.com/java-dev/health-cloud-biz/health-cloud-evaluation.git'
//git branch: 'dev', credentialsId: '248e1fa0-6165-4a81-8297-4107e4132017c', url: 'git@gitlab.xxx.com:java-dev/health-cloud-biz/health-cloud-evaluation.git'
// get image version
script {
env.GIT_COMMIT_MSG = sh (script: 'git rev-parse --short=8 HEAD', returnStdout: true).trim()
IMAGE_VERSION = "${GIT_COMMIT_MSG}-${RUN_ENV}"
IMAGE_NAME = "${IMAGE_REPO}/${PROJECT_NAME}:${IMAGE_VERSION}"
}
}
}
stage('maven build'){
steps{
container('maven-agent') {
sh "sed -i \"s#${OLD_IMAGE}#${IMAGE_NAME}#g\" deploy/test/docker-compose.yml"
sh 'mvn clean package -DskipTests -Pdev'
}
}
}
stage('build image'){
steps{
container('docker-agent') {
withCredentials([usernamePassword(credentialsId: 'ee78c0ce-d905-4c2c-bbf0-928f1a9f17d0', passwordVariable: 'docker_password', usernameVariable: 'docker_username')]) {
sh 'docker login -u ${docker_username} -p ${docker_password} ${IMAGE_REPO}'
sh "docker build -t ${PROJECT_NAME}:${IMAGE_VERSION} -f deploy/test/Dockerfile ."
sh "docker tag ${PROJECT_NAME}:${IMAGE_VERSION} ${IMAGE_REPO}/${PROJECT_NAME}:${IMAGE_VERSION}"
sh "docker push ${IMAGE_REPO}/${PROJECT_NAME}:${IMAGE_VERSION}"
sh 'echo build images success'
}
}
}
}
stage('deploy to rancher'){
steps{
sh '/home/jenkins/rancher-tools/rancher --url https://dev.hw.xxxxrancher.com/ --access-key 926407BB131AE8EE5010 --secret-key ksPBDn1fr97bjzAqYk5KaVU8aRfLQF6UHxFdtfwP2 --env 1a5 up -s health-cloud-server -d -f deploy/test/docker-compose.yml --rancher-file deploy/test/rancher-compose.yml --pull --upgrade --confirm-upgrade'
}
}
}
}
六. 测试发布

——————————————————————————————————————————————————
关于jenkins变量引用用单引还是双引的问题
jenkins 中和shell语法是一致的。
- 要引用的是普通字符,单双引号都可以。
- 引用的内容中有需要解释的符号,如提取变量的$需要用
双引号
- 但jenkins的流水线声明的env变量中,解析它的变量用单引号
如:
withCredentials([usernamePassword(credentialsId: 'ee78c0ce-d905-4c2c-bbf0-928f1a9f171d0', passwordVariable: 'docker_password', usernameVariable: 'docker_username')]) {
sh 'docker login -u ${docker_username} -p ${docker_password} ${IMAGE_REPO}'
这一段中,经过测试,双引号就解析不出来变量。
- 如果需要用双引号里面的命令还需要用双引号,那可以利用转义,如
sh "sed -i \"s#IMAGE_NAME#${IMAGE_NAME}#g\" deploy/test/k8sdeployment.yaml"
To Do List :
-
job的workspace挂载出来,省去每次都重新去拉代码(已更新)
-
通过git-commit号来作为镜像版本标识,更加有助于回滚 (已更新)
20230220更新:
agent构建的时候,持久化数据也是有必要的,不然首先麻烦的就每次都要重新拉取代码,尝试把agent工作目录挂载到宿主机:
1.将agent的工作目录挂载到nfs服务器上:
系统管理---节点管理---找到你的cloud--pod模板设置中

设置后,会自动将agent的工作路径/home/jenkins/agent下的workspace挂载到nfs服务器的/opt/jenkins_agent_workspace下
查看一下(workspace下job名,而下面就是各job下的数据):
root@k8s01.test.hw:/opt/jenkins_agent_workspace# ls workspace/
k8s-test_health-cloud-evaluation k8s-test_health-cloud-evaluation@tmp test-bottom-library_H5-node12.20.2 test-bottom-library_H5-node12.20.2@tmp
root@k8s01.test.hw:/opt/jenkins_agent_workspace# pwd
/opt/jenkins_agent_workspace
不用每次都重新拉代码了:

网友评论