一、问题引入:云原生团队用Tekton时遇到的“慢”难题
很多做云原生开发的团队,都会选Tekton来做流水线——毕竟它是专门为Kubernetes设计的流水线工具,适配性强、扩展性也够。但不少团队落地后发现:流水线跑起来特别慢,比如一个普通的Java项目构建,本来在本地用Maven几分钟就能搞定,放到Tekton上可能要十几分钟甚至更久,严重拖慢了开发迭代的速度。 我们团队之前也遇到过这个问题,经过大半个月的排查和优化,把一个核心项目的流水线耗时从18分钟降到了4分钟以内。接下来就把我们踩过的坑、总结的优化路径拆解清楚,让不同基础的开发者都能跟着操作。
二、先搞懂Tekton流水线的“慢”到底慢在哪
要优化,得先找到问题根源。我们把流水线的执行流程拆成三个阶段:拉取代码、依赖准备、构建打包,慢的原因基本就出在这三个阶段里。
2.1 拉取代码慢:网络和存储的双重坑
拉取代码的慢,分两种情况:一种是网络问题,比如代码仓库在境外,集群节点的网络出口带宽小;另一种是存储问题,Tekton默认用的是临时存储(EmptyDir),拉取的代码在Pod销毁后就没了,每次都要重新拉,哪怕代码只改了一行,也要全量拉取。
2.2 依赖准备慢:每次都重新下载的“无效重复”
这是最常见的慢的原因。比如Java项目的Maven依赖、Node.js的npm依赖,每次构建都会在Pod里重新下载一遍,少则几十MB,多则上GB,既费时间又占带宽。
2.3 构建打包慢:资源不足或镜像臃肿
构建阶段的慢,要么是分配给Pod的CPU、内存不够,导致构建工具(比如Maven、Gradle)跑不起来;要么是构建出来的镜像太大,推送时间长。
三、具体优化路径:从易到难一步步改
我们的优化是按“成本低、见效快”的顺序来的,先改配置,再改代码,最后调架构。
3.1 第一步:解决拉取代码的慢——用PVC做持久化存储
之前我们的Tekton任务用的是EmptyDir,每次拉代码都是从头来。后来我们给任务加了PVC(持久化卷声明),把拉取的代码存到PVC里,下次构建的时候,只有代码有变化才会增量拉取,没变化就直接复用。
示例:带PVC的Tekton任务配置
技术栈:Tekton + Kubernetes
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-java-task
spec:
resources:
inputs:
- name: source-code
type: git
# 配置代码仓库地址、分支
params:
- name: url
value: "https://github.com/your-org/your-java-project.git"
- name: revision
value: "main"
# 新增PVC配置,用于持久化代码
volumes:
- name: code-pvc
persistentVolumeClaim:
claimName: code-pvc # 提前创建好的PVC,这里用ReadWriteMany模式,方便多个Pod同时访问
steps:
- name: pull-code
image: alpine/git # 用轻量的git镜像,比官方git镜像小很多
workingDir: /workspace/source-code
volumeMounts:
- name: code-pvc
mountPath: /workspace/source-code
script: |
# 先检查PVC里有没有代码,有的话就拉取增量更新,没有的话全量拉取
if [ -d ".git" ]; then
git pull origin main
else
git clone https://github.com/your-org/your-java-project.git .
fi
这里的PVC需要提前创建,用ReadWriteMany模式,因为可能有多个任务同时访问同一个代码目录。另外,我们用了alpine/git镜像,比官方的git镜像小了一半多,拉取镜像的时间也能省下来。
3.2 第二步:解决依赖下载慢——用PVC缓存依赖
依赖下载慢的核心是“重复下载”,所以我们用PVC把依赖缓存起来,下次构建的时候直接用缓存里的依赖,不用再重新下载。
示例:带依赖缓存的Maven构建任务
技术栈:Tekton + Kubernetes + Maven
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-java-task
spec:
resources:
inputs:
- name: source-code
type: git
params:
- name: url
value: "https://github.com/your-org/your-java-project.git"
- name: revision
value: "main"
volumes:
# 代码PVC
- name: code-pvc
persistentVolumeClaim:
claimName: code-pvc
# 新增Maven依赖缓存PVC
- name: maven-cache-pvc
persistentVolumeClaim:
claimName: maven-cache-pvc # 提前创建的PVC,模式ReadWriteMany
steps:
- name: pull-code
image: alpine/git
workingDir: /workspace/source-code
volumeMounts:
- name: code-pvc
mountPath: /workspace/source-code
script: |
if [ -d ".git" ]; then
git pull origin main
else
git clone https://github.com/your-org/your-java-project.git .
fi
- name: build-java
image: maven:3.8.6-openjdk-11-slim # 用slim版本的Maven镜像,比标准版小很多
workingDir: /workspace/source-code
volumeMounts:
- name: code-pvc
mountPath: /workspace/source-code
- name: maven-cache-pvc
mountPath: /root/.m2 # Maven的依赖缓存默认存在/root/.m2目录
script: |
# 执行Maven构建,跳过测试(如果需要测试可以去掉-DskipTests)
mvn clean package -DskipTests
这里的关键是把Maven的缓存目录/root/.m2挂载到PVC上,每次构建的时候,Maven会先检查PVC里有没有需要的依赖,有就直接用,没有才会下载。我们团队之前用这个方法,把Maven依赖的准备时间从12分钟降到了1分钟以内。
3.3 第三步:解决构建慢——优化资源和镜像
如果前两步改完还是慢,就要看构建阶段的问题了。
3.3.1 优化资源分配
很多团队给Tekton任务分配的资源太少,比如只给1核CPU、1G内存,导致构建工具跑不起来。我们可以给任务加资源限制,比如给Maven任务分配2核CPU、4G内存:
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-java-task
spec:
steps:
- name: build-java
image: maven:3.8.6-openjdk-11-slim
# 新增资源配置
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
cpu: "2"
memory: "4Gi"
# 其他配置...
注意,requests是请求的资源,limits是最大可用的资源,两者保持一致可以让调度更稳定。
3.3.2 优化镜像大小
构建出来的镜像太大,推送时间就长。我们可以用多阶段构建来缩小镜像大小。比如Java项目,第一阶段用Maven镜像构建Jar包,第二阶段用更小的JRE镜像来运行Jar包:
示例:多阶段构建的Dockerfile
技术栈:Docker
# 第一阶段:构建Jar包,用Maven镜像
FROM maven:3.8.6-openjdk-11-slim AS build
WORKDIR /app
COPY pom.xml .
# 先复制pom.xml,利用Docker缓存,下次构建时如果pom.xml没变化,就不会重新下载依赖
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests
# 第二阶段:运行Jar包,用轻量的JRE镜像(只有构建出来的镜像的1/3大小)
FROM openjdk:11-jre-slim
WORKDIR /app
# 从第一阶段复制构建好的Jar包
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
我们团队之前用这个方法,把镜像大小从1.2GB降到了300MB以内,推送时间从3分钟降到了30秒以内。
3.4 第四步:进阶优化——用Tekton的缓存和镜像加速
如果以上优化都做了,还想进一步提速,可以试试Tekton官方的缓存功能和镜像加速。
3.4.1 Tekton官方缓存
Tekton 0.29版本以后,官方提供了缓存功能,专门用来缓存依赖,比自己用PVC缓存更方便。它可以自动识别依赖的变化,决定是否使用缓存。
3.4.2 镜像加速
如果集群拉取官方镜像(比如Docker Hub、Maven官方镜像)慢,可以配置镜像加速。比如给Kubernetes的容器运行时(比如Docker、containerd)配置国内的镜像源,比如阿里云的镜像源:
# 给containerd配置镜像加速
mkdir -p /etc/containerd/certs.d/docker.io
cat > /etc/containerd/certs.d/docker.io/hosts.toml << EOF
server = "https://docker.io"
[host."https://xxxxxx.mirror.aliyuncs.com"]
capabilities = ["pull", "resolve"]
EOF
systemctl restart containerd
配置完镜像加速后,拉取官方镜像的时间会快很多。
四、优化效果对比
我们团队优化前后的流水线耗时对比: | 优化阶段 | 流水线总耗时 | 拉取代码耗时 | 依赖准备耗时 | 构建打包耗时 | | -------- | ------------ | ------------ | ------------ | ------------ | | 优化前 | 18分钟 | 2分钟 | 12分钟 | 4分钟 | | 优化后 | 3分40秒 | 10秒 | 1分钟 | 2分30秒 | 可以看到,优化效果非常明显,尤其是依赖准备阶段的耗时减少了90%以上。
五、应用场景、优缺点和注意事项
5.1 应用场景
这些优化方法适用于所有用Tekton做流水线的云原生团队,尤其是以下场景:
- 代码仓库在境外,拉取代码慢的团队;
- 依赖多、依赖下载慢的项目(比如Java、Node.js、Python项目);
- 流水线耗时过长,影响开发迭代的团队;
- 资源有限,需要优化资源利用率的团队。
5.2 技术优缺点
优点
- 成本低:大部分优化只需要修改配置,不需要额外购买资源;
- 见效快:优化后流水线耗时可以减少50%以上;
- 通用性强:适用于各种类型的项目和技术栈;
- 可扩展性强:可以根据团队的需求,进一步优化(比如加分布式缓存、分布式构建)。
缺点
- 依赖PVC:如果集群的存储性能不好,可能会影响优化效果;
- 多阶段构建增加了Dockerfile的复杂度;
- 官方缓存功能需要升级Tekton版本,可能会有兼容性问题。
5.3 注意事项
- PVC的模式要选对:代码和依赖缓存的PVC需要用ReadWriteMany模式,因为可能有多个任务同时访问;
- 镜像版本要稳定:尽量用slim版本的镜像,并且固定版本,避免因为镜像更新导致构建失败;
- 缓存清理:如果依赖变化频繁,需要定期清理缓存,避免缓存占用过多的存储;
- 资源分配要合理:不要过度分配资源,避免浪费集群资源。
六、总结
Tekton流水线执行效率低下的问题,本质上是“重复工作”和“资源不足”的问题。优化的核心思路是:减少重复工作(比如缓存代码、缓存依赖)、优化资源利用(比如用轻量镜像、合理分配资源)、提升网络速度(比如镜像加速)。 我们团队的优化经验告诉我们,大部分团队的流水线慢,都可以通过以上方法解决,不需要花大价钱升级集群,只需要调整配置和代码,就能得到明显的效果。希望这篇文章能帮到遇到同样问题的团队,让流水线跑起来更快,让开发迭代更顺畅。
评论
围绕“云原生团队落地Tekton时流水线执行效率低下的性能优化路径解析”参与讨论