背景
本文以蓝盾社区版7.1为例,结合实际源码和配置,详细梳理从前端点击「执行」到最终在 Kubernetes 集群拉起 Deployment 的全链路调用过程,
目录结构
1 2 3 4 5 6 7 8 9
| bk-ci/src ├── gateway # OpenResty 网关(Lua) ├── frontend # Vue 前端,模块级微前端 ├── backend # Kotlin + SpringCloud 微服务 │ ├── process # 流水线引擎 │ ├── dispatch # 构建调度(Docker & K8s) │ └── ... ├── agent # Go 语言 Agent └── pipeline-plugin # Java 插件 SDK
|
源码拆解
前端触发
页面地址:https://devops.bk.tencent.com/console/pipeline/{projectId}/{pipelineId}/preview
| 事件/方法 |
对应后端接口 |
作用 |
| requestStartupInfo |
GET /ms/process/api/user/builds/{p}/{pl}/manualStartupInfo |
获取流水线启动所需参数 |
| executePipeline |
POST /ms/process/api/user/builds/{p}/{pl} |
真正触发流水线执行 |
通过全局事件总线 bus 通信,以及具名视图(named views)机制实现页面拆分和组合。在 preview.vue 页面监听 executePipeline 事件,然后在 PreviewHeader.vue 中通过事件总线触发执行。
网关转发
/ms/process/api/user/builds/… 统一转发到 process 微服务。
1 2 3
| location /ms/process/ { proxy_pass http://process/; }
|
Process 服务:流水线启动主链路
主要方法调用链如下:
1 2 3 4 5 6 7 8 9
| UserBuildResource.manualStartup() // 接收启动流水线的请求 ↓ ServiceBuildResourceImpl.manualStartup() // 具体实现,做参数校验、权限校验等 ↓ PipelineBuildFacadeService.buildManualStartup() // 负责组装启动参数、调用核心服务 ↓ PipelineBuildService.startPipeline() // 启动流水线主流程,负责流水线状态流转、记录等 ↓ PipelineRuntimeService.startBuild() // 流水线引擎,解析模型,调度 Stage/Job/Container,准备构建任务
|
这一阶段主要负责接收前端的启动请求,经过参数校验、权限校验后,组装启动参数,最终进入流水线引擎。流水线引擎会解析流水线的模型(YAML/DSL),为后续的调度和任务准备做铺垫。
生成并下发构建任务
主要方法调用链如下:
1 2 3 4 5
| PipelineContainerService.prepareBuildContainerTasks() // 遍历流水线模型,为每个 Job/Container 生成任务,判断分发类型 ↓ VmOperateTaskGenerator.makeStartVMContainerTask() // 针对容器构建机,生成 VM 启动任务(taskAtom = "dispatchVMStartupTaskAtom") ↓ pipelineEventDispatcher.dispatch(PipelineBuildStartEvent()) // 下发流水线启动事件
|
此阶段会遍历流水线模型中的每个 Job/Container,根据其类型(如容器构建机)生成对应的任务。对于容器构建机,会生成 VM 启动任务,并通过事件分发器下发流水线启动事件,为后续的事件驱动调度做准备。
事件驱动:Stage/Container/Task 调度
主要方法调用链如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| PipelineBuildStartListener.run(event) // 消费 PipelineBuildStartEvent,驱动流水线调度 ↓ BuildStartControl.handle(event) ↓ PipelineBuildStartEvent.execute(watcher) ↓ buildModel() ↓ pipelineEventDispatcher.dispatch(PipelineBuildStageEvent()) // 下发 Stage 事件
PipelineStageBuildListener.run(event) // 消费 PipelineBuildStageEvent ↓ StageControl.handle(event) ↓ PipelineBuildStageEvent.execute(watcher) ↓ pipelineContainerService.listContainers(...) // 遍历当前 Stage 下所有 Container(Job) ↓ pipelineEventDispatcher.dispatch(PipelineBuildContainerEvent()) // 为每个 Job 下发事件
PipelineContainerBuildListener.run(event) // 消费 PipelineBuildContainerEvent ↓ ContainerControl.handle(event) ↓ ContainerCmdChain.doCommand(context) // 命令链执行,关键命令 StartActionTaskContainerCmd ↓ pipelineEventDispatcher.dispatch(PipelineBuildAtomTaskEvent()) // 下发插件任务事件
|
蓝盾采用事件驱动架构,每个阶段(Stage)、每个 Job(Container)、每个插件(Task)都通过事件进行调度。每个事件都有对应的 Listener 消费,逐步推进流水线的执行流程,保证了系统的高解耦和可扩展性。
插件任务调度与 VM 启动
主要方法调用链如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| PipelineAtomTaskBuildListener.run(event) // 消费 PipelineBuildAtomTaskEvent ↓ TaskControl.handle(event) ↓ taskAtomService.start(buildTask) ↓ SpringContextUtil.getBean(IAtomTask::class.java, task.taskAtom).execute(task, runVariables) ↓ DispatchVMStartupTaskAtom.execute() // 对于 VM 启动任务,加载并执行 ↓ dispatch() ↓ getDispatchType() // 返回 DockerDispatchType(社区版容器构建机默认) ↓ pipelineEventDispatcher.dispatch(PipelineAgentStartupEvent()) // 下发分发事件
|
每个插件任务(Atom)都会被动态加载并执行。对于 VM 启动任务,会加载 DispatchVMStartupTaskAtom 插件,判断分发类型(如 Docker),并下发 PipelineAgentStartupEvent,为后续的构建机分发做准备。
dispatch-docker 服务:分发到 k8s
主要方法调用链如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| DockerVMListener.onStartup(dispatchMessage) // 消费 PipelineAgentStartupEvent ↓ getDockerRoutingType(projectId) // 判断路由类型(如 configmap 配置为 "KUBERNETES") ↓ startKubernetesDocker(...) // 路由类型为 KUBERNETES 时,走 k8s 资源池 ↓ DispatchBuildService.startUp() ↓ createAndStartNewBuilder() ↓ containerServiceFactory.load(projectId).createAndStartBuilder() ↓ KubernetesContainerService.createAndStartBuilder() ↓ kubernetesBuilderClient.createBuilder() // HTTP POST /api/builders 调用 dispatch-k8s-manager
|
dispatch-docker 服务会根据项目的路由配置,决定是走本地 Docker 还是 k8s 资源池。若配置为 KUBERNETES,则会通过 HTTP 请求调用 dispatch-k8s-manager 服务,准备在 k8s 集群中拉起构建容器。
查看 bk-ci-bk-ci-dispatch-docker 这个 configmap,可以发现配置文件里的 defaultDockerRoutingType 是 “KUBERNETES”。
dispatch-k8s-manager 服务:拉起 k8s Deployment
主要方法调用链如下:
1 2 3 4 5 6 7 8 9
| POST /api/builders // 路由 ↓ createBuilder handler ↓ service.CreateBuilder ↓ task.DoCreateBuilder ↓ kubeclient.CreateDeployment(dep) // 通过 k8s API 创建 Deployment,拉起实际的构建容器
|
dispatch-k8s-manager 服务负责与 Kubernetes API 交互,接收来自 dispatch-docker 的 HTTP 请求后,组装 Deployment 对象并调用 k8s API,最终在集群中拉起实际的构建容器,完成流水线的环境准备。
总结时序图

总结
| 阶段 |
关键技术点 |
一句话描述 |
| 前端 |
Vue + Event Bus |
点击按钮 → 事件总线 → 请求发出 |
| 网关 |
OpenResty 前缀转发 |
统一入口,/ms/process/** 直接透传至 process 服务。 |
| 流程引擎 |
自研事件-命令链框架 |
PipelineBuildStart → Stage → Container → Task → AgentStartup,层层事件推进,高内聚低耦合。 |
| 插件 |
IAtomTask SPI 机制 |
运行时动态加载 DispatchVMStartupTaskAtom,扩展即插即用。 |
| 调度 |
dispatch-docker → dispatch-kubernetes |
根据 defaultDockerRoutingType=KUBERNETES 路由到对应资源池。 |
| K8s 交付 |
dispatch-k8s-manager 与 kube-apiserver 交互 |
一条 HTTP 请求即可在集群内拉起 Deployment,数秒完成环境就绪。 |
参考