Woodpecker CI 核心概念科普
Woodpecker CI 是一个轻量级开源 CI/CD 引擎。这篇文章不讲具体配置——那是入门速查的事——而是解释背后的核心概念和设计思路。
CI/CD 解决了什么问题
在多人协作的软件项目里,每次代码变更(push、PR)都可能引入问题。CI/CD 的职责是:
- 自动检查——代码风格、单元测试、编译,确保变更不破坏已有功能
- 自动交付——通过检查的代码自动构建成制品,甚至直接部署到生产环境
传统做法是 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 后台执行
这种分离设计带来的能力:
- 弹性伸缩——加一个 Agent 就是加一条执行流水线。Server 不执行任何实际任务,瓶颈只在 Agent 数量
- 异构 Agent——一个 Server 可以对接不同架构的 Agent(
linux/amd64、linux/arm64、windows/amd64),Workflow 通过labels或platform匹配 - 离线执行——Agent 执行期间如果网络断开(有重试和 keepalive 机制),Workflow 不受影响
- 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,但它是思路最清晰的那个。