背景
在前文蓝盾「Docker公共构建机」缓存清理中我们通过分析源码,知道拉起的构建 Pod 通过 hostPath 挂载工作目录做缓存。我们接下来进一步分析创建 Pod 的流程。
部署配置
dispatch-k8s-manager/resources/config.yaml
1 | dispatch: |
通过 dispatch-k8s-manager
模块的配置文件,我们发现可以通过 nodeSelector
、 nodesAnnotation
、realResource
等配置来设置调度策略。
源码分析
亲和性和污点容忍
dispatch-k8s-manager/pkg/apiserver/service/builder_start.go
1 | func CreateBuilder(builder *Builder) (taskId string, err error) { |
dispatch-k8s-manager/pkg/kubeclient/deployment.go
1 | func CreateDeployment(dep *Deployment) error { |
在 CreateBuilder 里,调度相关的两个核心参数 tolers 和 nodeMatches 都是通过 buildDedicatedBuilder(builder) 返回的,这两个参数会一起传递给 kubeclient 层,在 kubeclient 的 CreateDeployment 方法中:
- NodeMatches 会被转换为 affinity.nodeAffinity,用于节点亲和调度。
- Tolerations 会直接下发到 Pod 的 spec.tolerations 字段,用于污点容忍。
历史节点调度
蓝盾源码里我们找到了有关亲和性以及污点容忍的实现,但是有关历史节点调度的实现只有通过 getBuilderAnnotations 给 Pod 设置注解。至于如何通过注解影响调度在蓝盾源码里并没有找到相关内容。
我们进一步分析发现,历史节点调度需要通过蓝盾基于K8S调度插件实现。
1 | apiVersion: v1 |
1 | package bkdevopsschedulerplugin |
- 在插件的 Score 阶段,会读取 Pod 的 bkci.dispatch.kubenetes/builder-history-nodes 注解内容,并将其反序列化为历史节点名称数组,即提供历史节点信息。
- 插件通过 calculateNodeHisScore 方法,根据当前调度节点是否在历史节点列表中,以及其在列表中的顺序,给予不同的分数(最近的历史节点分数最高)。
- 该分数会与资源分数(通过 bkci.dispatch.kubenetes/builder-real-resources 注解和节点资源情况计算得出)相加,作为最终调度优先级,影响调度器选择节点的排序。
总结
在蓝盾流水线中,通过以下方式实现了 Kubernetes 的调度优化:
- 历史节点调度:通过注解记录历史节点信息,调度插件优先选择这些节点,减少初始化时间。
- 亲和性(Affinity):根据配置文件中的 nodeSelector 和代码中的 NodeMatches 转换为 nodeAffinity,确保 Pod 调度到特定节点。
- 污点容忍(Tolerations):仅在配置文件中指定了专机(privateMachine)时,生成污点容忍配置,允许 Pod 调度到带特定污点的节点。
这些机制协同提升了调度效率和资源利用率。