一、问题引入:云原生团队用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流水线执行效率低下的问题,本质上是“重复工作”和“资源不足”的问题。优化的核心思路是:减少重复工作(比如缓存代码、缓存依赖)、优化资源利用(比如用轻量镜像、合理分配资源)、提升网络速度(比如镜像加速)。 我们团队的优化经验告诉我们,大部分团队的流水线慢,都可以通过以上方法解决,不需要花大价钱升级集群,只需要调整配置和代码,就能得到明显的效果。希望这篇文章能帮到遇到同样问题的团队,让流水线跑起来更快,让开发迭代更顺畅。