Woodpecker CI 核心概念科普

2026-05-22

Woodpecker CI 是一个轻量级开源 CI/CD 引擎。这篇文章不讲具体配置——那是入门速查的事——而是解释背后的核心概念和设计思路。


CI/CD 解决了什么问题

在多人协作的软件项目里,每次代码变更(push、PR)都可能引入问题。CI/CD 的职责是:

  1. 自动检查——代码风格、单元测试、编译,确保变更不破坏已有功能
  2. 自动交付——通过检查的代码自动构建成制品,甚至直接部署到生产环境

传统做法是 Jenkins 那样跑在固定服务器上的 Agent,每台机器装好环境和依赖。Woodpecker 的做法不同:每个步骤启动一个容器,环境隔离、用完即弃。

核心概念层级

Woodpecker 用三个层次组织流水线:

Pipeline(一次触发)
  └─ Workflow(一组串行/并行步骤)
       └─ Step(一个容器里执行的命令)

Pipeline(流水线)

由外部事件触发(push、pull_request、tag、cron、手动等)。一次 Pipeline 代表一次完整的构建任务,可以包含多个 Workflow。

Workflow(工作流)

定义在 .woodpecker/*.yaml 文件中。一个仓库可以有多个 Workflow 文件,它们默认并行执行,也可以通过 depends_on 建立依赖关系。

为什么需要多 Workflow?因为不同任务可能跑在不同架构上。例如一个 Workflow 在 linux/amd64 上编译,另一个在 linux/arm64 上编译,它们并行进行,互不干扰,各自匹配不同的 Agent。

Step(步骤)

最小的执行单元。每个 Step 在一个容器中运行,多个 Step 默认串行执行。串行的好处:前一个 Step 对文件系统的修改对后一个 Step 可见(同一 volume 挂载)。

如果需要并行,用 depends_on 声明依赖关系,框架自动构建 DAG:

steps:
  - name: lint
    image: golang
    commands: golangci-lint run
    depends_on: []       # 立即启动
  - name: test
    image: golang
    commands: go test ./...
    depends_on: []       # 与 lint 并行
  - name: build
    image: golang
    commands: go build
    depends_on: [lint, test]  # 等前两者完成

容器化执行模型

每个 Step = 一个容器。这是 Woodpecker 最根本的设计决策。这意味着:

优势

  • 环境完全隔离——不同 Step 可用不同镜像(编译用 golang,部署用 amazon/aws-cli
  • 不需要在 Agent 上预装任何依赖,只需要 Docker 或 Kubernetes
  • 插件也是容器——社区写的 S3 上传插件就是一个 Docker 镜像,通过 settings 传参

代价

  • 每个 Step 的启动有容器冷启动开销(但通常只有 1-2 秒)
  • 需要容器运行时环境(Docker / K8s / 本地)

Agent-Server 架构

Woodpecker 分为两个核心组件:

Server — 接收 Webhook、解析 YAML、管理队列、提供 UI 和 API

Agent — 真正的执行者,通过 gRPC 从 Server 拉取任务,用 Docker/K8s/Local 后台执行

这种分离设计带来的能力:

  1. 弹性伸缩——加一个 Agent 就是加一条执行流水线。Server 不执行任何实际任务,瓶颈只在 Agent 数量
  2. 异构 Agent——一个 Server 可以对接不同架构的 Agent(linux/amd64linux/arm64windows/amd64),Workflow 通过 labelsplatform 匹配
  3. 离线执行——Agent 执行期间如果网络断开(有重试和 keepalive 机制),Workflow 不受影响
  4. Autoscaler——根据队列深度自动创建/销毁云 VM 上的 Agent

插件系统

Woodpecker 的插件就是一个普通 Docker 镜像,在 Step 中通过 image 引用。与传统 CI 的插件框架不同:

  • 不限定语言——Python、Go、Shell 写的工具都能当插件,只要它是指令正确的 Docker 镜像
  • 参数传递——通过 settings 转换为容器环境变量
  • Secret 注入——敏感信息通过 UI 配置,在 Step 中用 from_secret 引用,不会暴露在 YAML 中
steps:
  - name: deploy
    image: woodpeckerci/plugin-s3
    settings:
      bucket: my-bucket
      source: ./dist/
      target: /app
      access_key:
        from_secret: aws_access_key

条件执行模型

Woodpecker 的 when 条件系统设计为:

  • 条件列表 = OR(任一条件满足即执行)
  • 单个条件内的子条件 = AND(全部满足才匹配)

这意味着可以表达复杂的规则:

when:
  - event: push
    branch: main
  - event: pull_request
    path:
      include: ['src/**']
      exclude: ['*.md']

复杂的场景还可以用 evaluate 写表达式:

when:
  - evaluate: 'CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == CI_REPO_DEFAULT_BRANCH && not (CI_COMMIT_MESSAGE contains "skip")'

安全模型

  • Trusted 仓库——某些 Step 需要 privileged 模式(比如 Docker-in-Docker),只有管理员在 UI 中标记为 trusted 的仓库才可用
  • Secrets——存储在 Server 数据库中,YAML 中只引用不存储值,运行时才注入容器
  • Agent Labels——Workflow 可以通过 labels 限定只能被特定 Agent 执行,防止敏感任务跑到不安全的 Agent 上
  • Agent 注册控制——管理员可以关闭用户自行注册 Agent 的功能(WOODPECKER_DISABLE_USER_AGENT_REGISTRATION=true),防止恶意读取全局 Secret

什么时候选 Woodpecker

适合的场景:

  • 想完全自托管 CI,不依赖 SaaS 服务
  • 项目主要在 GitHub/Gitea/GitLab 上,想用一个工具统一
  • 需要轻量、简单的 CI,不想学 Jenkins 的 DSL 或复杂的插件生态
  • 跑在树莓派或低配机器上(Server 最小资源占用不到 256MB)

不太适合的场景:

  • 需要丰富的托管 CI 市场(GitHub Actions 更适合)
  • 需要图形化流水线编辑器(Woodpecker 只有 YAML)
  • 大规模团队需要企业级权限管理(GitLab CI 更成熟)

总结

Woodpecker 的核心思想可以用三句话概括:

  • Step = 容器,环境隔离,用完即弃
  • Agent 与 Server 分离,弹性伸缩的基础
  • 插件 = Docker 镜像,不 reinvent the wheel

它不是功能最全的 CI,但它是思路最清晰的那个。

参考

https://blog.logfun.xyz/blog/feed.xml