Kubernetes 调度器扩展与自定义调度策略实践

好嘞!各位观众老爷,各位技术大咖,各位正在敲代码敲到头秃的程序猿/媛们,欢迎来到今天的“Kubernetes 调度器扩展与自定义调度策略实践”大型脱口秀现场!我是你们的老朋友,一个被 Bug 亲吻过的码农,今天就跟大家聊聊 Kubernetes 调度器这个神秘又有趣的话题。

别害怕,今天咱不搞枯燥乏味的理论,也不堆砌晦涩难懂的概念。咱用最接地气的方式,聊聊如何驯服 Kubernetes 调度器这匹野马,让它乖乖地听你的话,把你的应用放到最合适的地方。准备好了吗?咱们开始!

一、调度器:Kubernetes 的“红娘”?

首先,咱们得搞清楚 Kubernetes 调度器到底是干啥的。简单来说,它就像一个经验丰富的“红娘”,负责给你的 Pod(可以理解为 Kubernetes 里的“单身男女”)找到合适的 Node(可以理解为 Kubernetes 里的“房子”)。

它会综合考虑 Node 的资源情况(CPU、内存、硬盘等等),Pod 的资源需求,以及各种各样的约束条件(比如亲和性、反亲和性、污点等等),最终决定把 Pod 放到哪个 Node 上。

如果没有调度器,你的 Pod 就像无头苍蝇一样乱飞,可能跑到资源不足的 Node 上,导致应用性能下降甚至崩溃;也可能跑到不合适的 Node 上,导致安全风险或者功能异常。

所以,调度器是 Kubernetes 集群的核心组件之一,它的好坏直接关系到整个集群的稳定性和性能。

二、默认调度器:勤劳的“老黄牛”

Kubernetes 自带了一个默认调度器,它就像一头勤劳的“老黄牛”,默默地为你干着活。它会按照一套预定义的策略,尽力把你的 Pod 放到最合适的 Node 上。

这些策略包括:

  • Predicate(预选): 筛选出满足 Pod 要求的 Node。比如,Pod 需要 2 核 CPU 和 4GB 内存,那么只有拥有足够资源的 Node 才能通过预选。
  • Priority(优选): 对通过预选的 Node 进行打分,选择得分最高的 Node。比如,Node 的 CPU 利用率越低,得分越高;Node 上已经运行的 Pod 数量越少,得分越高。

默认调度器虽然好用,但是也有一些局限性:

  • 策略固定: 只能使用 Kubernetes 预定义的策略,无法根据你的业务需求进行定制。
  • 功能有限: 无法满足一些高级的调度需求,比如根据 Node 的地理位置、网络拓扑等等进行调度。

这时候,就需要我们自己动手,扩展或者定制调度器,让它更好地服务于我们的业务。

三、扩展调度器:给“红娘”配个“军师”

扩展调度器,就像给“红娘”配个“军师”,让它在做媒的时候,能够参考更多的信息,做出更明智的决策。

Kubernetes 提供了两种扩展调度器的方式:

  1. Scheduler Extender: 这是一个外部进程,可以拦截调度器的调度请求,并根据自定义的策略进行筛选和打分。
  2. Scheduling Framework: 这是 Kubernetes 1.19 引入的新特性,它提供了一套插件机制,允许你自定义调度器的各个阶段的行为。

咱们先来看看 Scheduler Extender。

3.1 Scheduler Extender:插上翅膀的调度器

Scheduler Extender 的工作流程大致如下:

  1. 调度器收到一个 Pod 的调度请求。
  2. 调度器调用 Extender 的 Filter 接口,让 Extender 筛选出满足自定义策略的 Node。
  3. 调度器调用 Extender 的 Prioritize 接口,让 Extender 对通过筛选的 Node 进行打分。
  4. 调度器综合考虑 Extender 的打分和自身策略的打分,选择得分最高的 Node。
  5. 调度器将 Pod 绑定到选定的 Node。

举个例子,假设你有一个 Extender,它可以根据 Node 的 GPU 数量进行筛选和打分。那么,你可以配置调度器,让它优先选择拥有更多 GPU 的 Node 来运行你的 AI 应用。

表格:Scheduler Extender 的配置示例

参数名 描述 示例值
urlPrefix Extender 的 URL 前缀。 "http://my-extender.default.svc.cluster.local"
filterVerb Extender 的 Filter 接口的路径。 "/filter"
prioritizeVerb Extender 的 Prioritize 接口的路径。 "/prioritize"
weight Extender 的权重。Extender 的打分会乘以这个权重,然后再与调度器自身的打分进行合并。 1
enableHTTPS 是否启用 HTTPS。 false
tlsConfig HTTPS 的配置。 {"certFile": "/path/to/cert.pem", "keyFile": "/path/to/key.pem"}
nodeCacheCapable 是否启用 Node 缓存。如果启用,Extender 会缓存 Node 的信息,减少对 Kubernetes API Server 的访问。 true
managedResources Extender 管理的资源。如果指定了,调度器会将这些资源的信息传递给 Extender。 [{"name": "gpu", "ignoredByScheduler": false}]
ignorable 如果 Extender 返回错误,是否忽略错误。如果设置为 true,调度器会忽略错误,继续调度;如果设置为 false,调度器会停止调度。 true

Scheduler Extender 的优点是简单易用,只需要编写一个 HTTP 服务,就可以实现自定义的调度策略。但是,它的缺点也很明显:

  • 性能瓶颈: 每次调度都需要调用 Extender,会增加调度延迟。
  • 维护成本: 需要维护一个额外的 HTTP 服务,增加了维护成本。
  • 功能限制: 只能在 Filter 和 Prioritize 阶段进行扩展,无法访问调度器的内部状态。

3.2 Scheduling Framework:给“红娘”换个“大脑”

Scheduling Framework 就像给“红娘”换个“大脑”,让它能够更加灵活地处理各种复杂的调度场景。

Scheduling Framework 提供了一套插件机制,允许你自定义调度器的各个阶段的行为。这些阶段包括:

  • QueueSort: 对调度队列中的 Pod 进行排序。
  • PreFilter: 在 Filter 之前执行,可以提前拒绝一些不满足条件的 Pod。
  • Filter: 筛选出满足 Pod 要求的 Node。
  • PostFilter: 在 Filter 之后执行,可以对 Filter 的结果进行处理。
  • PreScore: 在 Score 之前执行,可以提前计算一些 Score 需要的数据。
  • Score: 对通过 Filter 的 Node 进行打分。
  • Reserve: 预留 Node 的资源,防止其他 Pod 占用。
  • Permit: 允许或者拒绝 Pod 绑定到 Node。
  • PreBind: 在 Bind 之前执行,可以进行一些准备工作。
  • Bind: 将 Pod 绑定到 Node。
  • PostBind: 在 Bind 之后执行,可以进行一些清理工作。

你可以根据自己的需求,编写不同的插件,来实现各种各样的调度策略。

举个例子,你可以编写一个 Score 插件,根据 Node 的地理位置进行打分,让 Pod 优先调度到距离用户最近的 Node 上,从而提高应用的访问速度。

Scheduling Framework 的优点是功能强大,性能高效,可以访问调度器的内部状态。但是,它的缺点也很明显:

  • 学习曲线陡峭: 需要深入了解 Kubernetes 调度器的内部机制。
  • 开发难度高: 需要使用 Go 语言进行开发,并遵循 Kubernetes 的代码规范。
  • 维护成本高: 需要维护一套复杂的插件系统,增加了维护成本。

表格:Scheduling Framework 的插件配置示例

参数名 描述 示例值
apiVersion API 版本。 "kubescheduler.config.k8s.io/v1beta2"
kind 对象类型。 "KubeSchedulerConfiguration"
leaderElection Leader 选举的配置。 {"leaderElect": true, "resourceLock": "leases", "resourceNamespace": "kube-system", "resourceName": "kube-scheduler"}
profiles 调度策略的配置。 [{"schedulerName": "default-scheduler", "plugins": {"score": [{"name": "MyScorePlugin", "weight": 1}], "filter": [{"name": "MyFilterPlugin"}]}}]
pluginConfig 插件的配置。 [{"name": "MyScorePlugin", "args": {"factor": 0.5}}]

四、自定义调度策略:让“红娘”更懂你

不管是扩展调度器,还是使用 Scheduling Framework,最终的目的都是为了实现自定义的调度策略,让“红娘”更懂你,更好地服务于你的业务。

那么,有哪些常见的自定义调度策略呢?

  • 亲和性调度: 将相关的 Pod 调度到一起,比如将一个应用的多个 Pod 调度到同一个 Node 上,减少网络延迟。
  • 反亲和性调度: 将不相关的 Pod 调度到不同的 Node 上,比如将一个应用的多个 Pod 调度到不同的 Node 上,提高应用的可用性。
  • 污点和容忍度: 给 Node 打上污点,表示该 Node 不适合运行某些 Pod。Pod 可以设置容忍度,表示可以容忍某些污点。
  • 节点选择器: 根据 Node 的标签选择 Node,比如只允许 Pod 运行在拥有特定硬件的 Node 上。
  • 区域感知调度: 将 Pod 调度到距离用户最近的区域,提高应用的访问速度。
  • 成本优化调度: 将 Pod 调度到成本最低的 Node 上,降低应用的运行成本。

五、实践案例:驯服“野马”的正确姿势

说了这么多理论,咱们来点实际的,看看如何驯服 Kubernetes 调度器这匹“野马”。

案例:基于 GPU 资源的 AI 应用调度

假设你有一个 AI 应用,需要大量的 GPU 资源。你需要确保 AI 应用能够运行在拥有足够 GPU 的 Node 上,并且优先选择拥有更多 GPU 的 Node。

你可以使用 Scheduler Extender 或者 Scheduling Framework 来实现这个需求。这里我们以 Scheduling Framework 为例。

  1. 编写一个 Score 插件: 该插件会根据 Node 的 GPU 数量进行打分,拥有更多 GPU 的 Node 得分更高。
  2. 配置调度器: 将该插件添加到调度器的 Score 阶段。
  3. 部署 AI 应用: 在 Pod 的 YAML 文件中,添加 Node 选择器,选择拥有 GPU 的 Node。

这样,Kubernetes 调度器就会优先选择拥有更多 GPU 的 Node 来运行你的 AI 应用,从而提高应用的性能。

六、总结:让 Kubernetes 调度器成为你的得力助手

今天跟大家聊了 Kubernetes 调度器扩展与自定义调度策略,希望能够帮助大家更好地理解 Kubernetes 调度器的原理,并能够灵活地运用各种技术手段,让 Kubernetes 调度器成为你的得力助手。

记住,Kubernetes 调度器不是一个冷冰冰的机器,而是一个可以被你驯服的“野马”。只要你掌握了正确的方法,就能够让它乖乖地听你的话,把你的应用放到最合适的地方。

最后,祝大家在 Kubernetes 的世界里,玩得开心,码得快乐!🎉🎉🎉

Disclaimer: 本文仅供学习交流,请勿用于非法用途。如有侵权,请联系删除。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注