KubeSphere-04-Dev-ops 流水线插件的使用
KubeSphere 基于 Jenkins 的 DevOps 系统是专为 Kubernetes 中的 CI/CD 工作流设计的,它提供了一站式的解决方案,帮助开发和运维团队用非常简单的方式构建、测试和发布应用到 Kubernetes。它还具有插件管理、Binary-to-Image (B2I)、Source-to-Image (S2I)、代码依赖缓存、代码质量分析、流水线日志等功能。
DevOps 系统为用户提供了一个自动化的环境,应用可以自动发布到同一个平台。它还兼容第三方私有镜像仓库(如 Harbor)和代码库(如 GitLab/GitHub/SVN/BitBucket)。它为用户提供了全面的、可视化的 CI/CD 流水线,打造了极佳的用户体验,而且这种兼容性强的流水线能力在离线环境中非常有用。
本文档旨在成为您的技术指南,逐步引导您开启 KubeSphere 的 DevOps 之旅。我们将深入探索如何开启 DevOps 插件,如何规划设计一个完整的 DevOps 流水线并编写 Jenkins 流水线配置文件。通过本文档的实战案例,您将能够掌握从理论到实践的全过程,为您的项目带来持续集成和持续部署的自动化体验。
您将学习如何在 KubeSphere 上开启 DevOps 插件。
通过实际案例,规划设计一个高效、自动化的 DevOps 流水线。
我们将一起编写 Jenkinsfile,定义代码拉取、测试、编译、构建和部署的流程。
最终,我们将完成一个实战项目,将理论知识转化为实际操作,让您对 KubeSphere DevOps 的应用有更深的理解。
随着本文图片的辅助,本文档将确保您在每一个步骤中都能获得清晰的指导和深刻的见解。无论您是 DevOps 的新手还是希望在 KubeSphere 上实现 DevOps 流程的老手,本文档都将为您提供宝贵的知识和实践技巧。
一、开启 DevOps 组件
1.1 前提说明
现在,新部署的 KubeSphere v3.4.1 开启 DevOps 插件会有问题,具体描述见 KubeSphere 镜像构建器(S2I)服务证书过期(x509)问题。
在开启之前我们先修复存在的问题。
清理开启失败的残留 release(适用于开启过 DevOps 且安装失败)
helm -n kubesphere-devops-system delete devops
执行下面命令,获取 ks-installer 镜像
$ kubectl -n kubesphere-system get deployments ks-installer --no-headers -o custom-columns=:.spec.template.spec.containers[0].image
kubesphere/ks-installer:v3.4.1
在获取的镜像最后加上 ‘-patch.0’ ,执行下面命令更新 ks-installer 镜像
$ kubectl -n kubesphere-system patch deployments ks-installer --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value": "kubesphere/ks-installer:v3.4.1-patch.0"}]'
更新镜像后 ks-installer 会自动重启并根据 ClusterConfiguration 里的配置安装各个开启的未安装的模块。
1.2 开启 DevOps 组件配置
以
admin用户登录 KubeSphere 控制台,点击左上角的「平台管理」,选择「集群管理」。点击 「定制资源定义」,在搜索栏中输入
clusterconfiguration,点击搜索结果查看其详细页面。定制资源定义(CRD)允许用户在不新增 API 服务器的情况下创建一种新的资源类型,用户可以像使用其他 Kubernetes 原生对象一样使用这些定制资源。

在自定义资源中,点击
ks-installer右侧的三个竖点 ,选择编辑 YAML。

在该 YAML 文件中,搜索
devops,将enabled的false改为true。完成后,点击右下角的确定,保存配置,保存之后 KubeSphere 会自动安装 devops 插件。
devops:
enabled: true
jenkinsCpuLim: 1
jenkinsCpuReq: 0.5
jenkinsMemoryLim: 4Gi
jenkinsMemoryReq: 4Gi
jenkinsVolumeSize: 16Gi注意:上面的参数配置是默认值,仅适用于测试环境,生产环境建议根据规模调大参数值。
1.3 验证
在 kubectl 中执行以下命令检查安装过程。
$ kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l 'app in (ks-install, ks-installer)' -o jsonpath='{.items[0].metadata.name}') -f正确执行后,输出结果如下 :
PLAY RECAP *********************************************************************
localhost : ok=26 changed=14 unreachable=0 failed=0 skipped=21 rescued=0 ignored=0
Start installing monitoring
Start installing multicluster
Start installing openpitrix
Start installing network
Start installing devops
**************************************************
Waiting for all tasks to be completed ...
task network status is successful (1/5)
task openpitrix status is successful (2/5)
task multicluster status is successful (3/5)
task monitoring status is successful (4/5)
task devops status is successful (5/5)
**************************************************
Collecting installation results ...
#####################################################
### Welcome to KubeSphere! ###
#####################################################
......
检查 Kubernetes 集群
kubesphere-devops-system命名空间的资源运行状态。
$ kubectl get all -n kubesphere-devops-system
NAME READY STATUS RESTARTS AGE
pod/devops-28717020-l769w 0/1 Completed 0 14m
pod/devops-apiserver-858fdcc978-hwxbf 1/1 Running 0 15m
pod/devops-controller-989995d9f-wc6hs 1/1 Running 0 15m
pod/devops-jenkins-df4d7cd4b-pkmhn 1/1 Running 0 15m
pod/s2ioperator-0 1/1 Running 0 14m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/devops-apiserver ClusterIP 10.233.42.51 <none> 9090/TCP 15m
service/devops-jenkins NodePort 10.233.48.8 <none> 80:30180/TCP 15m
service/devops-jenkins-agent ClusterIP 10.233.3.210 <none> 50000/TCP 15m
service/s2ioperator-metrics-service ClusterIP 10.233.60.160 <none> 8080/TCP 15m
service/s2ioperator-trigger-service ClusterIP 10.233.13.255 <none> 8081/TCP 15m
service/webhook-server-service ClusterIP 10.233.1.199 <none> 443/TCP 15m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/devops-apiserver 1/1 1 1 15m
deployment.apps/devops-controller 1/1 1 1 15m
deployment.apps/devops-jenkins 1/1 1 1 15m
NAME DESIRED CURRENT READY AGE
replicaset.apps/devops-apiserver-858fdcc978 1 1 1 15m
replicaset.apps/devops-controller-989995d9f 1 1 1 15m
replicaset.apps/devops-jenkins-df4d7cd4b 1 1 1 15m
NAME READY AGE
statefulset.apps/s2ioperator 1/1 45m
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/devops 0/30 * * * * False 0 14m 15m
NAME COMPLETIONS DURATION AGE
job.batch/devops-28717020 1/1 15s 14m注意:实际部署中会增加 Minio 、OpenLDAP,还有一组 Argo CD 的服务组件。
KubeSphere 管理控制台验证。
登录KubeSphere 管理控制台,依次点击「平台管理」->「集群管理」->「系统组件」,检查 DevOps 标签页中的所有组件是否都处于健康状态。如果是,组件安装成功。

二、创建和管理 DevOps 项目
本文仅演示,如何创建单管理员用户实现企业空间中创建项目和管理 DevOps 项目,更复杂、更贴近生产环境的多用户模式请参考官方文档 创建企业空间、项目、用户和平台角色
2.1 创建用户
安装 KubeSphere 之后,您需要向平台添加具有不同角色的用户,以便他们可以针对自己授权的资源在不同的层级进行工作。一开始,系统默认只有一个用户 admin,具有 platform-admin 角色。在本步骤中,我将创建一个示例用户 opsxlab。
以
admin身份使用默认帐户和密码 (admin/P@88w0rd) 登录 Web 控制台。点击左上角的平台管理,然后选择访问控制。

在用户中,点击创建。

在弹出的对话框中,填写所有必要信息(带有*标记)。在平台角色下拉列表,选择platform-self-provisioner。点击确定。新创建的用户将显示在用户页面。

在用户页面,查看创建的用户。

2.2 创建企业空间
企业空间是 KubeSphere 多租户系统的基础,是管理项目、DevOps 项目和组织成员的基本逻辑单元。
在左侧导航栏,选择企业空间。企业空间列表中已列出默认企业空间 system-workspace,该企业空间包含所有系统项目。其中运行着与系统相关的组件和服务,您无法删除该企业空间。

在企业空间列表页面,点击创建,输入企业空间的名称(例如 opsxlab),并将用户
opsxlab设置为企业空间管理员。完成后,点击创建。

点击「创建」返回。

登出控制台,然后以
opsxlab身份重新登录,验证是否能成功登录。

2.3 创建项目
在此步骤中,您需要使用在上一步骤中创建的帐户 opsxlab 来创建项目。KubeSphere 中的项目与 Kubernetes 中的命名空间相同,为资源提供了虚拟隔离。
以
opsxlab身份登录 KubeSphere Web 控制台,点击企业空间opsxlab,进入企业空间概览

在项目中,点击创建。

输入项目名称(例如
opsxlab),点击确定。您还可以为项目添加别名和描述。

完成创建

在项目中,点击刚创建的项目查看其详情页面。
在项目的概览页面,默认情况下未设置项目配额。您可以点击编辑配额并根据需要指定资源请求和限制(例如:CPU 和内存的限制分别设为 10 Core 和 50 Gi)。


2.4 创建 DevOps 项目
以
opsxlab身份登录 KubeSphere 控制台,转到 DevOps 项目,然后点击创建。

输入 DevOps 项目名称(例如
opsxlab-devops),然后点击确定,也可以为该项目添加别名和描述。

DevOps 项目创建后,会显示在下图所示的列表中。

点击刚创建的 DevOps 项目查看其详细页面。

三、DevOps 流水线规划设计
KubeSphere 官方提供的示例项目中的 Jenkinsfile-online 流水线设计更贴近生产环境,流程比较复杂,小白理解起来可能会有困难。为了让小白快速上手 KubeSphere DevOps 的功能,我设计了一个简化版的流程。
项目链接
本文我们基于 Jenkins 模拟生产环境应用发布的流程,实现如下的 DevOps 流水线任务:
阶段 1:Checkout SCM:从 Git 仓库检出源代码,本文使用 Gitlab 作为示例,GitHub 或是自建 Gitee 流程类似。
阶段 2:单元测试:待该测试通过后才会进行下一阶段。
阶段 3:编译 Java 源码:使用 Maven 构建 Jar 包。
阶段 4:构建并推送 tag 镜像:根据运行流水线时输入的分支来构建镜像,并将标签为
TAG_NAME的镜像推送至 Harbor 镜像仓库。阶段 5:推送最新镜像:将
TAG_NAME标签的镜像标记为特定的格式main-2025-10-21-10-57-9bf0946-59,并推送至 Harbor 镜像仓库。阶段 6:部署环境:将已发布的镜像部署到环境,流水线会根据分支的类型进行选择性部署,main、prod分支类型部署到生产环境,dev 分支部署到开发环境,pre 分支部署到预生产环境。
四、实现流水线的准备工作
设置 CI 专用节点用于运行流水线
准备 Gitlab 代码仓库(kubesphere 所在的集群要能访问 gitlab 仓库地址,如果是 https 类型则还需要特殊操作)
准备一个 Harbor 镜像仓库,并创建账户(用于存放构建的镜像,也可以使用 DockerHub 或是其他镜像仓库)
创建 kubeconfig 凭证
创建一个 DevOps 项目(使用上文创建的
opsxlab-devops)
4.1 为依赖项缓存设置 CI 专用节点
通常情况下,构建应用程序的过程中需要拉取不同的依赖项。这可能会导致某些问题,例如拉取时间长和网络不稳定,这会进一步导致构建失败。
我们可以配置一个节点或一组节点,专门用于持续集成 (CI)。这些 CI 节点可以通过使用缓存来加快构建过程。为我们流水线提供更可靠和稳定的环境。
执行下面的命令,标记节点 ksp-worker-1 作为 CI 节点:
kubectl label nodes ksp-worker-1 node-role.kubernetes.io/worker=ci --overwrite4.2 修改 maven 容器镜像
自定义修改 maven 容器镜像,为镜像内部添加信任证书的操作,因为我的 gitlab 代码仓库是本地部署的,https 证书是自签名的,所以需要容器信任,否则 git clone 的时候会提示证书安全问题,导致无法连接
[root@k8s-master1 builder-maven]# ls
ca.crt Dockerfile settings.xml *.tianxiang.love.cert *.tianxiang.love.crt
[root@k8s-master1 builder-maven]# cat Dockerfile
FROM harbor.tianxiang.love:30443/kubesphere/builder-maven:v3.2.0
# centos7
USER root
COPY *.tianxiang.love.crt /etc/pki/ca-trust/source/anchors/
COPY *.tianxiang.love.cert /etc/pki/ca-trust/source/anchors/
COPY ca.crt /etc/pki/ca-trust/source/anchors/
COPY settings.xml /opt/apache-maven-3.5.3/conf/settings.xml
RUN update-ca-trust
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && \
yum -y install jqsettings.xml 是 maven 的配置文件,这个里面我添加了阿里云仓库的私服,以便快速拉取依赖
[root@k8s-master1 builder-maven]# vim settings.xml
<!-- mirrors
| This is a list of mirrors to be used in downloading artifacts from remote repositories.
|
| It works like this: a POM may declare a repository to use in resolving certain artifacts.
| However, this repository may have problems with heavy traffic at times, so people have mirrored
| it to several places.
|
| That repository definition will have a unique id, so we can create a mirror reference for that
| repository, to be used as an alternate download site. The mirror site will be the preferred
| server for that repository.
|-->
### 146 行下面插入以下内容
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>central</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
###
</mirror>
<!-- mirror
| Specifies a repository mirror site to use instead of a given repository. The repository that
| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
|
<mirror>
<id>mirrorId</id>
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://my.repository.com/repo/path</url>
</mirror>
-->
</mirrors>构建镜像推送
[root@k8s-master1 builder-maven]# docker build . -t harbor.tianxiang.love:30443/kubesphere/builder-maven:v3.2.0
[root@k8s-master1 builder-maven]# docker push harbor.tianxiang.love:30443/kubesphere/builder-maven:v3.2.04.3 创建 Gitlab 仓库访问凭证
点击创建凭证

使用用户名密码方式添加 gitlab 登陆账号密码

4.4 创建 kubeconfig 凭证
接下来,我们创建 kubeconfig 凭证。
以
opsxlab身份登录 KubeSphere 控制台。进入您的 DevOps 项目,在左侧导航栏,选择DevOps 项目设置 > 凭证。
在右侧的凭证区域,点击创建。
在弹出的创建凭证对话框,设置以下参数:
名称:设置凭证名称,例如
opsxlab-kubeconfig类型:选择kubeconfig
内容:系统自动获取当前 Kubernetes 集群的 kubeconfig 文件内容,并自动填充该字段,您无须做任何更改。但是访问其他集群时,您可能需要更改 kubeconfig
因为我们要配置多环境部署部署,所以需要添加多个环境的 kubeconfig 文件
prod-kubeconfig


dev-kubeconfig

五、DevOps 流水线实战
5.1 创建流水线
创建流水线 java-demo-project

自定义名称和描述,选择流水线类别

使用参数化构建,选择选项


5.2 编辑流水线
这里使用项目中提供的 Jenkinsfile ,把代码复制粘贴进去
进入流水线

编辑流水线

流水线代码如下:
项目地址修改为你自己的:https://k8s-gitlab.tianxiang.love:30443/my-awesome-group/java-demo-project.git
pipeline {
agent {
node {
label 'maven'
}
}
stages {
stage('拉取代码') {
agent none
steps {
container('maven') {
echo "📥 正在拉取分支: ${params.BRANCH_NAME}"
git(url: 'https://k8s-gitlab.tianxiang.love:30443/my-awesome-group/java-demo-project.git', branch: "${params.BRANCH_NAME}", credentialsId: 'k8s-gitlab-login')
script {
env.GIT_COMMIT = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
echo "✅ 当前 GIT_COMMIT: ${env.GIT_COMMIT}"
}
}
}
}
stage('构建Jar包') {
agent none
steps {
container('maven') {
script {
def mvnProfile = (params.BRANCH_NAME == 'main' || params.BRANCH_NAME == 'prod') ? 'prod' : 'dev'
echo "🏗️ 使用 Maven Profile: ${mvnProfile}"
sh "mvn -B clean package -P ${mvnProfile} -Dmaven.test.skip=true"
}
sh 'ls -lh target/*.jar'
}
}
}
stage('生成TAG标签') {
agent none
steps {
container('maven') {
script {
def dateTag = sh(returnStdout: true, script: 'date +%Y-%m-%d-%H-%M').trim()
env.TAG_NAME = "${params.BRANCH_NAME}-${dateTag}-${env.GIT_COMMIT}-${BUILD_NUMBER}"
echo "✅ 生成的 TAG_NAME: ${env.TAG_NAME}"
}
}
}
}
stage('Docker Build & Push 镜像') {
agent none
steps {
container('maven') {
sh '''
echo "登录 Harbor 仓库"
echo "$HARBOR_PASSWD" | docker login $HARBOR_ADDRESS -u "$HARBOR_USER" --password-stdin
'''
sh '''
echo "查找 jar 包..."
JAR_NAME=$(find target -maxdepth 1 -name "*.jar" ! -name "*-sources.jar" ! -name "*-javadoc.jar" ! -name "original-*" | head -n 1)
echo "发现 JAR: $JAR_NAME"
'''
sh '''
echo "构建镜像: $HARBOR_ADDRESS/$HARBOR_PROJECT/$IMAGE_NAME:${TAG_NAME}"
docker build -t $HARBOR_ADDRESS/$HARBOR_PROJECT/$IMAGE_NAME:${TAG_NAME} --build-arg JAR_FILE=$JAR_NAME .
'''
sh '''
echo "推送镜像中..."
docker push $HARBOR_ADDRESS/$HARBOR_PROJECT/$IMAGE_NAME:${TAG_NAME}
echo "✅ 镜像推送成功: $HARBOR_ADDRESS/$HARBOR_PROJECT/$IMAGE_NAME:${TAG_NAME}"
'''
}
}
}
stage('确认 k8s 环境') {
agent none
steps {
container('maven') {
script {
switch(params.BRANCH_NAME) {
case 'dev':
env.DEPLOY_PROFILE = 'dev'; break
case 'pre':
env.DEPLOY_PROFILE = 'pre'; break
case 'main':
case 'prod':
env.DEPLOY_PROFILE = 'prod'; break
default:
error "未识别分支 ${params.BRANCH_NAME}"
}
switch(env.DEPLOY_PROFILE) {
case 'dev': env.KUBECONFIG_CREDENTIALS_ID = 'dev-kubeconfig'; break
case 'pre': env.KUBECONFIG_CREDENTIALS_ID = 'pre-kubeconfig'; break
case 'prod': env.KUBECONFIG_CREDENTIALS_ID = 'prod-kubeconfig'; break
}
env.DEPLOY_TEMPLATE = "k8s/deployment-${env.DEPLOY_PROFILE}.tml"
echo "🚀 开始部署到 ${env.DEPLOY_PROFILE} 环境"
echo "📦 使用模板: ${env.DEPLOY_TEMPLATE}"
echo "🔑 使用 KubeConfig 凭据: ${env.KUBECONFIG_CREDENTIALS_ID}"
}
}
}
}
stage('配置 K8s 环境') {
agent none
steps {
container('maven') {
withCredentials([kubeconfigContent(credentialsId: env.KUBECONFIG_CREDENTIALS_ID, variable: 'KUBECONFIG_CONTENT')]) {
sh '''echo "🔧 配置 K8s 环境..."
mkdir -p ~/.kube
echo "$KUBECONFIG_CONTENT" > ~/.kube/config
chmod 600 ~/.kube/config
echo '192.168.233.246 apiserver.cluster.local' | tee -a /etc/hosts
echo "✅ KubeConfig 配置完成"
if kubectl cluster-info > /dev/null 2>&1; then
echo "✅ K8s 集群连接正常"
kubectl cluster-info
else
echo "❌ K8s 集群连接失败"
exit 1
fi'''
}
}
}
}
stage('渲染部署文件') {
agent none
steps {
container('maven') {
sh '''
echo "🎨 渲染部署文件..."
sed -e "s/{{.IMAGE_NAME}}/${IMAGE_NAME}/g" \
-e "s/{{.PROJECT_NAME}}/${HARBOR_PROJECT}/g" \
-e "s/{{.TAG_NAME}}/${TAG_NAME}/g" \
-e "s/{{.HARBOR_ADDRESS}}/${HARBOR_ADDRESS}/g" \
-e "s/{{.PROFILE}}/${DEPLOY_PROFILE}/g" \
${DEPLOY_TEMPLATE} > k8s/deployment-"${DEPLOY_PROFILE}".yaml
echo "📄 生成的部署文件内容:"
cat k8s/deployment-"${DEPLOY_PROFILE}".yaml
echo "✅ 部署文件渲染完成"
'''
}
}
}
stage('应用部署') {
agent none
steps {
container('maven') {
sh '''
echo "🚀 开始应用部署..."
DEPLOY_START_TIME=$(date +%s)
echo "DEPLOY_START_TIME=$DEPLOY_START_TIME" > /tmp/deploy_time.env
kubectl apply -f k8s/deployment-"${DEPLOY_PROFILE}".yaml
echo "✅ 部署文件应用完成"
'''
}
}
}
stage('等待 Pod 就绪') {
agent none
steps {
container('maven') {
sh '''
chmod +x ./scripts/wait-pod-running.sh
bash ./scripts/wait-pod-running.sh "${HARBOR_PROJECT}" "${IMAGE_NAME}"
'''
}
}
}
}
environment {
HARBOR_ADDRESS = 'harbor.tianxiang.love:30443'
HARBOR_PROJECT = 'k8s-app'
IMAGE_NAME = 'java-demo-project'
HARBOR_USER = 'admin'
HARBOR_PASSWD = 'TianHarbor12345'
}
parameters {
choice(name: 'BRANCH_NAME', choices: ['dev', 'pre', 'main', 'prod'], description: '请选择要构建的 Git 分支')
}
}查看可视化流水线,刷新一下页面即可显示出来

5.3 运行流水线
开发环境部署









验证服务是否正常

生产环境部署


验证服务是否正常
