Kubernetes API 服务器如何在节点上启动新调度的 pod?
How does the Kubernetes API server start a newly scheduled pod on a node?
我正在尝试更好地了解 'under the hood' Kubernetes Pod 调度和创建过程的工作原理,以及 kubelet
和 kube-apiserver
之间的交互。
我了解 Kubernetes 调度程序选择一个节点来分配新的 pod,并将此通知 API 服务器。但是,我不清楚 API 服务器如何通知相关节点上的 kubelet
启动 pod。 kubelet
中是否有查询 API 服务器更改的轮询进程?或者有没有事件监听/回调类型的交互?
如果有人知道答案或可以指出一些文档的方向,将不胜感激!
没有 link 源代码的回答,但我确定 kubelet
是这样工作的:
- 列表podshttps://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#list-pod-v1-core
- 将
watch
放入列表
- grep pods 在
PodScheduled
状态
- grep pods 其中
spec.nodeName==$hostname
- 在每个观看事件上重复
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 的主机名。
我正在尝试更好地了解 'under the hood' Kubernetes Pod 调度和创建过程的工作原理,以及 kubelet
和 kube-apiserver
之间的交互。
我了解 Kubernetes 调度程序选择一个节点来分配新的 pod,并将此通知 API 服务器。但是,我不清楚 API 服务器如何通知相关节点上的 kubelet
启动 pod。 kubelet
中是否有查询 API 服务器更改的轮询进程?或者有没有事件监听/回调类型的交互?
如果有人知道答案或可以指出一些文档的方向,将不胜感激!
没有 link 源代码的回答,但我确定 kubelet
是这样工作的:
- 列表podshttps://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#list-pod-v1-core
- 将
watch
放入列表 - grep pods 在
PodScheduled
状态 - grep pods 其中
spec.nodeName==$hostname
- 在每个观看事件上重复
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 的主机名。