Kubernetes API 服务器如何在节点上启动新调度的 pod?

How does the Kubernetes API server start a newly scheduled pod on a node?

我正在尝试更好地了解 'under the hood' Kubernetes Pod 调度和创建过程的工作原理,以及 kubeletkube-apiserver 之间的交互。

我了解 Kubernetes 调度程序选择一个节点来分配新的 pod,并将此通知 API 服务器。但是,我不清楚 API 服务器如何通知相关节点上的 kubelet 启动 pod。 kubelet 中是否有查询 API 服务器更改的轮询进程?或者有没有事件监听/回调类型的交互?

如果有人知道答案或可以指出一些文档的方向,将不胜感激!

没有 link 源代码的回答,但我确定 kubelet 是这样工作的:

Query Parameters
...
watch   Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

Watch 功能继承自 etcd(API 服务器背后的数据库):https://etcd.io/docs/v3.2.17/learning/api/。见 Watch streams:

Watches are long running requests and use gRPC streams to stream event data.

所以这是一种长轮询。

阿里巴巴有一个really insightful blog post on the inner workings of the scheduler。来自博客:


调度器基本上是这样工作的:

  • 调度器维护一个调度的 podQueue 并监听 APIServer。
  • 当我们创建Pod时,我们首先通过API服务器将Pod元数据写入etcd。
  • 调度器通过Informer监听Pod状态。当添加新的 Pod 时,Pod 被添加到 podQueue。
  • 主进程不断从podQueue中取出Pods并分配节点给Pods.
  • 调度过程包括两个步骤:筛选匹配节点并根据 Pod 配置(例如,通过资源使用和亲和力等指标)对这些节点进行优先级排序,对节点进行评分,select 得分最高的节点得分.
  • 节点分配成功后,调用apiServer的绑定pod接口,将pod.Spec.NodeName设置为分配的pod。
  • 节点上的kubelet也监听ApiServer。如果它发现一个新的 Pod 被调度到该节点,本地 dockerDaemon 被调用到 运行 容器。
  • 如果调度器调度Pod失败,如果开启了优先级和抢占,首先进行抢占尝试,删除节点上优先级低的Pods,调度Pods将被调度到节点。如果未开启抢占或者抢占尝试失败,则会在日志中记录相关信息,并Pods添加到podQueue的末尾。

关于 Kubelet 轮询:实际上,API 服务器支持“监视”模式,该模式使用 WebSocket 协议。通过这种方式,Kubelet 会收到有关 Pods 的任何更改的通知,主机名等于 Kubelet 的主机名。