diff --git a/content/zh/docs/concepts/scheduling-eviction/_index.md b/content/zh/docs/concepts/scheduling-eviction/_index.md new file mode 100644 index 0000000000..742a054e40 --- /dev/null +++ b/content/zh/docs/concepts/scheduling-eviction/_index.md @@ -0,0 +1,4 @@ +--- +title: "调度和驱逐(Scheduling and Eviction)" +weight: 90 +--- diff --git a/content/zh/docs/concepts/scheduling-eviction/kube-scheduler.md b/content/zh/docs/concepts/scheduling-eviction/kube-scheduler.md new file mode 100644 index 0000000000..cc1bbda060 --- /dev/null +++ b/content/zh/docs/concepts/scheduling-eviction/kube-scheduler.md @@ -0,0 +1,169 @@ +--- +title: Kubernetes 调度器 +content_template: templates/concept +weight: 50 +--- + + +{{% capture overview %}} + + +在 Kubernetes 中,_调度_ 是指将 {{< glossary_tooltip text="Pod" term_id="pod" >}} 放置到合适的 +{{< glossary_tooltip text="Node" term_id="node" >}} 上,然后对应 Node 上的 {{< glossary_tooltip term_id="kubelet" >}} 才能够运行这些 pod。 + +{{% /capture %}} + +{{% capture body %}} + +## 调度概览 {#scheduling} + + +调度器通过 kubernetes 的 watch 机制来发现集群中新创建且尚未被调度到 Node 上的 Pod。调度器会将发现的每一个未调度的 Pod 调度到一个合适的 Node 上来运行。调度器会依据下文的调度原则来做出调度选择。 + + +如果你想要理解 Pod 为什么会被调度到特定的 Node 上,或者你想要尝试实现一个自定义的调度器,这篇文章将帮助你了解调度。 + + +## kube-scheduler + + +[kube-scheduler](/zh/docs/reference/command-line-tools-reference/kube-scheduler/) 是 Kubernetes 集群的默认调度器,并且是集群 {{< glossary_tooltip text="控制面" term_id="control-plane" >}} 的一部分。如果你真的希望或者有这方面的需求,kube-scheduler 在设计上是允许你自己写一个调度组件并替换原有的 kube-scheduler。 + + +对每一个新创建的 Pod 或者是未被调度的 Pod,kube-scheduler 会选择一个最优的 Node 去运行这个 Pod。然而,Pod 内的每一个容器对资源都有不同的需求,而且 Pod 本身也有不同的资源需求。因此,Pod 在被调度到 Node 上之前,根据这些特定的资源调度需求,需要对集群中的 Node 进行一次过滤。 + + +在一个集群中,满足一个 Pod 调度请求的所有 Node 称之为 _可调度节点_。如果没有任何一个 Node 能满足 Pod 的资源请求,那么这个 Pod 将一直停留在未调度状态直到调度器能够找到合适的 Node。 + + +调度器先在集群中找到一个 Pod 的所有可调度节点,然后根据一系列函数对这些可调度节点打分,然后选出其中得分最高的 Node 来运行 Pod。之后,调度器将这个调度决定通知给 kube-apiserver,这个过程叫做 _绑定_。 + + +在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、亲和以及反亲和要求、数据局域性、负载间的干扰等等。 + + +## kube-scheduler 调度流程 {#kube-scheduler-implementation} + + +kube-scheduler 给一个 pod 做调度选择包含两个步骤: + +1. 过滤 +2. 打分 + + +过滤阶段会将所有满足 Pod 调度需求的 Node 选出来。例如,PodFitsResources 过滤函数会检查候选 Node 的可用资源能否满足 Pod 的资源请求。在过滤之后,得出一个 Node 列表,里面包含了所有可调度节点;通常情况下,这个 Node 列表包含不止一个 Node。如果这个列表是空的,代表这个 Pod 不可调度。 + + +在打分阶段,调度器会为 Pod 从所有可调度节点中选取一个最合适的 Node。根据当前启用的打分规则,调度器会给每一个可调度节点进行打分。 + + +最后,kube-scheduler 会将 Pod 调度到得分最高的 Node 上。如果存在多个得分最高的 Node,kube-scheduler 会从中随机选取一个。 + + +支持以下两种方式配置调度器的过滤和打分行为: + + +1. [调度策略](/docs/reference/scheduling/policies) 允许你配置过滤的 _谓词(Predicates)_ 和打分的 _优先级(Priorities)_ 。 +2. [调度配置](/docs/reference/scheduling/profiles) 允许你配置实现不同调度阶段的插件,包括:`QueueSort`, `Filter`, `Score`, `Bind`, `Reserve`, `Permit` 等等。你也可以配置 kube-scheduler 运行不同的配置文件。 + +{{% /capture %}} +{{% capture whatsnext %}} + + + +* 阅读关于 [调度器性能调优](/zh/docs/concepts/scheduling-eviction/scheduler-perf-tuning/) +* 阅读关于 [Pod 拓扑分布约束](/zh/docs/concepts/workloads/pods/pod-topology-spread-constraints/) +* 阅读关于 kube-scheduler 的 [参考文档](/zh/docs/reference/command-line-tools-reference/kube-scheduler/) +* 了解关于 [配置多个调度器](/zh/docs/tasks/administer-cluster/configure-multiple-schedulers/) 的方式 +* 了解关于 [拓扑结构管理策略](/zh/docs/tasks/administer-cluster/topology-manager/) +* 了解关于 [Pod 额外开销](/zh/docs/concepts/configuration/pod-overhead/) +{{% /capture %}} diff --git a/content/zh/docs/concepts/scheduling-eviction/scheduler-perf-tuning.md b/content/zh/docs/concepts/scheduling-eviction/scheduler-perf-tuning.md new file mode 100644 index 0000000000..ee0b285712 --- /dev/null +++ b/content/zh/docs/concepts/scheduling-eviction/scheduler-perf-tuning.md @@ -0,0 +1,276 @@ +--- +title: 调度器性能调优 +content_template: templates/concept +weight: 70 +--- + + +{{% capture overview %}} + +{{< feature-state for_k8s_version="1.14" state="beta" >}} + + +作为 kubernetes 集群的默认调度器,[kube-scheduler](/docs/concepts/scheduling-eviction/kube-scheduler/#kube-scheduler) 主要负责将 Pod 调度到集群的 Node 上。 + + +在一个集群中,满足一个 Pod 调度请求的所有 Node 称之为 _可调度_ Node。调度器先在集群中找到一个 Pod 的可调度 Node,然后根据一系列函数对这些可调度 Node打分,之后选出其中得分最高的 Node 来运行 Pod。最后,调度器将这个调度决定告知 kube-apiserver,这个过程叫做 _绑定_。 + + +这篇文章将会介绍一些在大规模 Kubernetes 集群下调度器性能优化的方式。 + +{{% /capture %}} + +{{% capture body %}} + + +在大规模集群中,你可以调节调度器的表现来平衡调度的延迟(新 Pod 快速就位)和精度(调度器很少做出糟糕的放置决策)。 + +你可以通过设置 kube-scheduler 的 `percentageOfNodesToScore` 来配置这个调优设置。这个 KubeSchedulerConfiguration 设置决定了调度集群中节点的阈值。 + + +### 设置阈值 + + +`percentageOfNodesToScore` 选项接受从 0 到 100 之间的整数值。0 值比较特殊,表示 kube-scheduler 应该使用其编译后的默认值。 +如果你设置 `percentageOfNodesToScore` 的值超过了 100,kube-scheduler 的表现等价于设置值为 100。 + + +要修改这个值,编辑 kube-scheduler 的配置文件(通常是 `/etc/kubernetes/config/kube-scheduler.yaml`),然后重启调度器。 + + +修改完成后,你可以执行 +```bash +kubectl get componentstatuses +``` + + +来检查该 kube-scheduler 组件是否健康。输出类似如下: +``` +NAME STATUS MESSAGE ERROR +controller-manager Healthy ok +scheduler Healthy ok +... +``` + + +## 节点打分阈值 {#percentage-of-nodes-to-score} + + +要提升调度性能,kube-scheduler 可以在找到足够的可调度节点之后停止查找。在大规模集群中,比起考虑每个节点的简单方法相比可以节省时间。 + + +你可以使用整个集群节点总数的百分比作为阈值来指定需要多少节点就足够。 kube-scheduler 会将它转换为节点数的整数值。在调度期间,如果 +kube-scheduler 已确认的可调度节点数足以超过了配置的百分比数量,kube-scheduler 将停止继续查找可调度节点并继续进行 [打分阶段](/docs/concepts/scheduling-eviction/kube-scheduler/#kube-scheduler-implementation)。 + + +[调度器如何遍历节点](#how-the-scheduler-iterates-over-nodes) 详细介绍了这个过程。 + + +### 默认阈值 + + +如果你不指定阈值,Kubernetes 使用线性公式计算出一个比例,在 100-node 集群下取 50%,在 5000-node 的集群下取 10%。 +这个自动设置的参数的最低值是 5%。 + + +这意味着,调度器至少会对集群中 5% 的节点进行打分,除非用户将该参数设置的低于 5。 + + +如果你想让调度器对集群内所有节点进行打分,则将 `percentageOfNodesToScore` 设置为 100。 + + +## 示例 + + +下面就是一个将 `percentageOfNodesToScore` 参数设置为 50% 的例子。 + +```yaml +apiVersion: kubescheduler.config.k8s.io/v1alpha1 +kind: KubeSchedulerConfiguration +algorithmSource: + provider: DefaultProvider + +... + +percentageOfNodesToScore: 50 +``` + + +### 调节 percentageOfNodesToScore 参数 + + +`percentageOfNodesToScore` 的值必须在 1 到 100 之间,而且其默认值是通过集群的规模计算得来的。 +另外,还有一个 50 个 Node 的最小值是硬编码在程序中。 + + +{{< note >}} +当集群中的可调度节点少于 50 个时,调度器仍然会去检查所有的 Node,因为可调度节点太少,不足以停止调度器最初的过滤选择。 + +同理,在小规模集群中,如果你将 `percentageOfNodesToScore` 设置为一个较低的值,则没有或者只有很小的效果。 + +如果集群只有几百个节点或者更少,请保持这个配置的默认值。改变基本不会对调度器的性能有明显的提升。 + +{{< /note >}} + + +值得注意的是,该参数设置后可能会导致只有集群中少数节点被选为可调度节点,很多 node 都没有进入到打分阶段。这样就会造成一种后果,一个本来可以在打分阶段得分很高的 Node 甚至都不能进入打分阶段。 + +由于这个原因,这个参数不应该被设置成一个很低的值。通常的做法是不会将这个参数的值设置的低于 10。很低的参数值一般在调度器的吞吐量很高且对 node 的打分不重要的情况下才使用。换句话说,只有当你更倾向于在可调度节点中任意选择一个 Node 来运行这个 Pod 时,才使用很低的参数设置。 + + +### 调度器做调度选择的时候如何覆盖所有的 Node + + +如果你想要理解这一个特性的内部细节,那么请仔细阅读这一章节。 + + +在将 Pod 调度到 Node 上时,为了让集群中所有 Node 都有公平的机会去运行这些 Pod,调度器将会以轮询的方式覆盖全部的 Node。你可以将 Node 列表想象成一个数组。调度器从数组的头部开始筛选可调度节点,依次向后直到可调度节点的数量达到 `percentageOfNodesToScore` 参数的要求。在对下一个 Pod 进行调度的时候,前一个 Pod 调度筛选停止的 Node 列表的位置,将会来作为这次调度筛选 Node 开始的位置。 + + +如果集群中的 Node 在多个区域,那么调度器将从不同的区域中轮询 Node,来确保不同区域的 Node 接受可调度性检查。如下例,考虑两个区域中的六个节点: + +``` +Zone 1: Node 1, Node 2, Node 3, Node 4 +Zone 2: Node 5, Node 6 +``` + + +调度器将会按照如下的顺序去评估 Node 的可调度性: + +``` +Node 1, Node 5, Node 2, Node 6, Node 3, Node 4 +``` + + +在评估完所有 Node 后,将会返回到 Node 1,从头开始。 + +{{% /capture %}} diff --git a/content/zh/docs/concepts/configuration/scheduling-framework.md b/content/zh/docs/concepts/scheduling-eviction/scheduling-framework.md similarity index 50% rename from content/zh/docs/concepts/configuration/scheduling-framework.md rename to content/zh/docs/concepts/scheduling-eviction/scheduling-framework.md index 40ad637ed4..bebea8d02e 100644 --- a/content/zh/docs/concepts/configuration/scheduling-framework.md +++ b/content/zh/docs/concepts/scheduling-eviction/scheduling-framework.md @@ -3,7 +3,7 @@ reviewers: - ahg-g title: 调度框架 content_template: templates/concept -weight: 70 +weight: 60 --- @@ -21,7 +21,7 @@ weight: 70 {{< feature-state for_k8s_version="1.15" state="alpha" >}} -调度框架是 Kubernetes Scheduler 的一种新的可插入架构,可以简化调度器的自定义。它向现有的调度器增加了一组新的“插件” API。插件被编译到调度器程序中。这些 API 允许大多数调度功能以插件的形式实现,同时使调度“核心”保持简单且可维护。请参考[调度框架的设计提案][kep]获取框架设计的更多技术信息。 +调度框架是 Kubernetes Scheduler 的一种可插入架构,可以简化调度器的自定义。它向现有的调度器增加了一组新的“插件” API。插件被编译到调度器程序中。这些 API 允许大多数调度功能以插件的形式实现,同时使调度“核心”保持简单且可维护。请参考[调度框架的设计提案][kep]获取框架设计的更多技术信息。 [kep]: https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/20180409-scheduling-framework.md @@ -57,7 +57,7 @@ Each attempt to schedule one Pod is split into two phases, the **scheduling cycle** and the **binding cycle**. --> -每次调度一个 pod 的尝试都分为两个阶段,即**调度周期**和**绑定周期**。 +每次调度一个 Pod 的尝试都分为两个阶段,即 **调度周期** 和 **绑定周期**。 -调度周期为 pod 选择一个节点,绑定周期将该决策应用于集群。调度周期和绑定周期一起被称为“调度上下文”。 +调度周期为 Pod 选择一个节点,绑定周期将该决策应用于集群。调度周期和绑定周期一起被称为“调度上下文”。 -如果确定 pod 不可调度或者存在内部错误,则可以终止调度周期或绑定周期。Pod 将返回队列并重试。 +如果确定 Pod 不可调度或者存在内部错误,则可以终止调度周期或绑定周期。Pod 将返回队列并重试。 -下图显示了一个 pod 的调度上下文以及调度框架公开的扩展点。在此图片中,“过滤器”等同于“断言”,“评分”相当于“优先级函数”。 +下图显示了一个 Pod 的调度上下文以及调度框架公开的扩展点。在此图片中,“过滤器”等同于“断言”,“评分”相当于“优先级函数”。 - {{< figure src="/images/docs/scheduling-framework-extensions.png" title="调度框架扩展点" >}} - -### 队列排序 + +### 队列排序 {#queue-sort} -队列排序插件用于对调度队列中的 pod 进行排序。队列排序插件本质上将提供 "less(Pod1, Pod2)" 函数。一次只能启动一个队列插件。 +队列排序插件用于对调度队列中的 Pod 进行排序。队列排序插件本质上提供 "less(Pod1, Pod2)" 函数。一次只能启动一个队列插件。 -### 前置过滤 +### 前置过滤 {#pre-filter} -前置过滤插件用于预处理 pod 的相关信息,或者检查集群或 pod 必须满足的某些条件。如果前置过滤插件返回错误,则调度周期将终止。 +前置过滤插件用于预处理 Pod 的相关信息,或者检查集群或 Pod 必须满足的某些条件。如果 PreFilter 插件返回错误,则调度周期将终止。 -过滤插件用于过滤出不能运行该 pod 的节点。对于每个节点,调度器将按照其配置顺序调用这些过滤插件。如果任何过滤插件将节点标记为不可行,则不会为该节点调用剩下的过滤插件。节点可以被同时进行评估。 +过滤插件用于过滤出不能运行该 Pod 的节点。对于每个节点,调度器将按照其配置顺序调用这些过滤插件。如果任何过滤插件将节点标记为不可行,则不会为该节点调用剩下的过滤插件。节点可以被同时进行评估。 - + +### 前置评分 {#pre-score} -### 后置过滤 + +前置评分插件用于执行 “前置评分” 工作,即生成一个可共享状态供评分插件使用。如果 PreScore 插件返回错误,则调度周期将终止。 - - -后置过滤是一个信息性的扩展点。通过过滤阶段的节点列表将调用这些后置过滤。插件将使用这些数据来更新内部的状态或者生成日志/指标。 - - - -**注意:**希望执行“预评分”工作的插件应该使用后置过滤扩展点。 - - - -### 评分 + +### 评分 {#scoring} -评分插件用于对通过过滤阶段的节点进行排名。调度器将为每个节点调用每个评分插件。将有一个定义明确的整数范围,代表最小和最大分数。在[标准化评分](#标准化评分)阶段之后,调度器将根据配置的插件权重合并所有插件的节点分数。 +评分插件用于对通过过滤阶段的节点进行排名。调度器将为每个节点调用每个评分插件。将有一个定义明确的整数范围,代表最小和最大分数。在[标准化评分](#normalize-scoring)阶段之后,调度器将根据配置的插件权重合并所有插件的节点分数。 -### 标准化评分 +### 标准化评分 {#normalize-scoring} -标准化评分插件用于在调度器计算节点的排名之前修改分数。在此扩展点注册的插件将使用同一插件的[评分](#评分)结果被调用。每个插件在每个调度周期调用一次。 +标准化评分插件用于在调度器计算节点的排名之前修改分数。在此扩展点注册的插件将使用同一插件的[评分](#scoring) 结果被调用。每个插件在每个调度周期调用一次。 -如果任何标准化评分插件返回错误,则调度阶段将终止。 +如果任何 NormalizeScore 插件返回错误,则调度阶段将终止。 - -**注意:**希望执行“预保留”工作的插件应该使用标准化评分扩展点。 +{{< note >}} +希望执行“预保留”工作的插件应该使用 NormalizeScore 扩展点。 +{{< /note >}} -保留是一个信息性的扩展点。管理运行时状态的插件(也成为“有状态插件”)应该使用此扩展点,以便调度器在节点给指定 pod 预留了资源时能够通知该插件。这是在调度器真正将 pod 绑定到节点之前发生的,并且它存在是为了防止在调度器等待绑定成功时发生竞争情况。 +保留是一个信息性的扩展点。管理运行时状态的插件(也成为“有状态插件”)应该使用此扩展点,以便调度器在节点给指定 Pod 预留了资源时能够通知该插件。这是在调度器真正将 Pod 绑定到节点之前发生的,并且它存在是为了防止在调度器等待绑定成功时发生竞争情况。 -这个是调度周期的最后一步。一旦 pod 处于保留状态,它将在绑定周期结束时触发[不保留](#不保留)插件(失败时)或 -[绑定后](#绑定后)插件(成功时)。 - - - -*注意:此概念曾被称为“假设”。* +这个是调度周期的最后一步。一旦 Pod 处于保留状态,它将在绑定周期结束时触发[不保留](#不保留) 插件(失败时)或 +[绑定后](#post-bind) 插件(成功时)。 -允许插件用于防止或延迟 pod 的绑定。一个允许插件可以做以下三件事之一。 +_Permit_ 插件在每个 Pod 调度周期的最后调用,用于防止或延迟 Pod 的绑定。一个允许插件可以做以下三件事之一: 1. **批准** \ - 一旦所有允许插件批准 pod 后,该 pod 将被发送以进行绑定。 + 一旦所有 Permit 插件批准 Pod 后,该 Pod 将被发送以进行绑定。 1. **拒绝** \ - 如果任何允许插件拒绝 pod,则该 pod 将被返回到调度队列。这将触发[不保留](#不保留)插件。 + 如果任何 Permit 插件拒绝 Pod,则该 Pod 将被返回到调度队列。这将触发[不保留](#不保留) 插件。 1. **等待**(带有超时) \ - 如果一个允许插件返回“等待”结果,则 pod 将保持在允许阶段,直到插件批准它。如果超时发生,**等待**变成**拒绝**,并且 pod 将返回调度队列,从而触发[不保留](#不保留)插件。 + 如果一个 Permit 插件返回 “等待” 结果,则 Pod 将保持在一个内部的 “等待中” 的 Pod 列表,同时该 Pod 的绑定周期启动时即直接阻塞直到得到[批准](#frameworkhandle)。如果超时发生,**等待** 变成 **拒绝**,并且 Pod 将返回调度队列,从而触发[不保留](#不保留) 插件。 + + + +{{< note >}} +尽管任何插件可以访问 “等待中” 状态的 Pod 列表并批准它们 (查看 [`FrameworkHandle`](#frameworkhandle))。我们希望只有允许插件可以批准处于 “等待中” 状态的 预留 Pod 的绑定。一旦 Pod 被批准了,它将发送到[预绑定](#pre-bind) 阶段。 +{{< /note >}} -**批准 pod 绑定** - - - -尽管任何插件可以从缓存中访问“等待”状态的 pod 列表并批准它们。我们希望只有允许插件可以批准处于“等待”状态的 预留 pod 的绑定。一旦 pod 被批准了,它将发送到预绑定阶段。 - - - -### 预绑定 +### 预绑定 {#pre-bind} -预绑定插件用于执行 pod 绑定前所需的任何工作。例如,一个预绑定插件可能需要提供网络卷并且在允许 pod 运行在该节点之前将其挂载到目标节点上。 +预绑定插件用于执行 Pod 绑定前所需的任何工作。例如,一个预绑定插件可能需要提供网络卷并且在允许 Pod 运行在该节点之前将其挂载到目标节点上。 -如果任何预绑定插件返回错误,则 pod 将被[拒绝](#不保留)并且返回到调度队列中。 +如果任何 PreBind 插件返回错误,则 Pod 将被[拒绝](#不保留) 并且返回到调度队列中。 -绑定插件用于将 pod 绑定到节点上。直到所有的预绑定插件都完成,绑定插件才会被调用。每个绑定插件按照配置顺序被调用。绑定插件可以选择是否处理指定的 pod。如果绑定插件选择处理 pod,**剩余的绑定插件将被跳过**。 +绑定插件用于将 Pod 绑定到节点上。直到所有的 PreBind 插件都完成,绑定插件才会被调用。每个绑定插件按照配置顺序被调用。绑定插件可以选择是否处理指定的 Pod。如果绑定插件选择处理 Pod,**剩余的绑定插件将被跳过**。 -### 绑定后 +### 绑定后 {#post-bind} -这是个信息性的扩展点。绑定后插件在 pod 成功绑定后被调用。这是绑定周期的结尾,可用于清理相关的资源。 +这是个信息性的扩展点。绑定后插件在 Pod 成功绑定后被调用。这是绑定周期的结尾,可用于清理相关的资源。 -这是个信息性的扩展点。如果 pod 被保留,然后在后面的阶段中被拒绝,则不保留插件将被通知。不保留插件应该清楚保留 pod 的相关状态。 +这是个信息性的扩展点。如果 Pod 被保留,然后在后面的阶段中被拒绝,则不保留插件将被通知。不保留插件应该清楚保留 Pod 的相关状态。 + +你可以在调度器配置中启用或禁用插件。如果你在使用 Kubernetes v1.18 或更高版本,大部分调度[插件](/docs/reference/scheduling/profiles/#scheduling-plugins) 都在使用中且默认启用。 -可以在调度器配置中启用插件。另外,默认的插件可以在配置中禁用。在 1.15 版本,调度框架没有默认的插件。 + +除了默认的插件,你同样可以实现自己的调度插件并且将他们与默认插件一起配置。你可以访问 [调度插件](https://github.com/kubernetes-sigs/scheduler-plugins) 了解更多详情。 - - -调度器配置也可以包含插件的配置。这些配置在调度器初始化插件时传给插件。配置是一个任意值。接收插件应该解码并处理配置信息。 - - - -下面的例子显示一个调度器配置,该配置在 `reserve` 和 `preBind` 扩展点启用了一些插件并且禁用了一个插件。它还提供了 `foo` 插件的配置。 - -```yaml -apiVersion: kubescheduler.config.k8s.io/v1alpha1 -kind: KubeSchedulerConfiguration - -... - -plugins: - reserve: - enabled: - - name: foo - - name: bar - disabled: - - name: baz - preBind: - enabled: - - name: foo - disabled: - - name: baz - -pluginConfig: -- name: foo - args: > - Arbitrary set of args to plugin foo -``` - - - -当配置省略扩展点时,将使用该扩展点的默认插件。当存在扩展掉并且配置为 `enabled`,则 `enabled` 的插件将和默认插件一同调用。首先调用默认插件,然后以配置中指定的顺序来调用其他已启用的插件。如果希望以不同的顺序来调用默认插件,默认插件必须 `disabled`,然后以期望的顺序 `enabled`。 - - - -假设在 `reserve` 扩展点有一个默认的 `foo` 插件,且添加 `bar` 插件并且希望在 `foo` 插件之前执行,我们应该禁用 `foo` 并且按顺序启用 `bar` 和 `foo`。下面的例子显示了实现此目的的配置: - -```yaml -apiVersion: kubescheduler.config.k8s.io/v1alpha1 -kind: KubeSchedulerConfiguration - -... - -plugins: - reserve: - enabled: - - name: bar - - name: foo - disabled: - - name: foo -``` + +如果你正在使用 Kubernetes v1.18 或更高版本,你可以将一组插件设置为一个调度器配置文件,然后定义不同的配置文件来满足各类工作负载。 +了解更多关于 [多配置文件](/docs/reference/scheduling/profiles/#multiple-profiles)。 {{% /capture %}} diff --git a/content/zh/docs/concepts/scheduling/_index.md b/content/zh/docs/concepts/scheduling/_index.md deleted file mode 100644 index 2f5138bfd8..0000000000 --- a/content/zh/docs/concepts/scheduling/_index.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "调度" -weight: 90 ---- diff --git a/content/zh/docs/concepts/scheduling/kube-scheduler.md b/content/zh/docs/concepts/scheduling/kube-scheduler.md deleted file mode 100644 index 5464e1a71b..0000000000 --- a/content/zh/docs/concepts/scheduling/kube-scheduler.md +++ /dev/null @@ -1,319 +0,0 @@ ---- -title: Kubernetes 调度器 -content_template: templates/concept -weight: 60 ---- - - -{{% capture overview %}} - - -在 Kubernetes 中,_调度_ 是指将 {{< glossary_tooltip text="Pod" term_id="pod" >}} 放置到合适的 -{{< glossary_tooltip text="Node" term_id="node" >}} 上,然后对应 Node 上的 {{< glossary_tooltip term_id="kubelet" >}} 才能够运行这些 pod。 - -{{% /capture %}} - -{{% capture body %}} - -## 调度概览 {#scheduling} - - -调度器通过 kubernetes 的 watch 机制来发现集群中新创建且尚未被调度到 Node 上的 Pod。调度器会将发现的每一个未调度的 Pod 调度到一个合适的 Node 上来运行。调度器会依据下文的调度原则来做出调度选择。 - - -如果你想要理解 Pod 为什么会被调度到特定的 Node 上,或者你想要尝试实现一个自定义的调度器,这篇文章将帮助你了解调度。 - - -## kube-scheduler - - -[kube-scheduler](/zh/docs/reference/command-line-tools-reference/kube-scheduler/) 是 Kubernetes 集群的默认调度器,并且是集群 {{< glossary_tooltip text="控制面" term_id="control-plane" >}} 的一部分。如果你真的希望或者有这方面的需求,kube-scheduler 在设计上是允许你自己写一个调度组件并替换原有的 kube-scheduler。 - - -对每一个新创建的 Pod 或者是未被调度的 Pod,kube-scheduler 会选择一个最优的 Node 去运行这个 Pod。然而,Pod 内的每一个容器对资源都有不同的需求,而且 Pod 本身也有不同的资源需求。因此,Pod 在被调度到 Node 上之前,根据这些特定的资源调度需求,需要对集群中的 Node 进行一次过滤。 - - -在一个集群中,满足一个 Pod 调度请求的所有 Node 称之为 _可调度节点_。如果没有任何一个 Node 能满足 Pod 的资源请求,那么这个 Pod 将一直停留在未调度状态直到调度器能够找到合适的 Node。 - - -调度器先在集群中找到一个 Pod 的所有可调度节点,然后根据一系列函数对这些可调度节点打分,然后选出其中得分最高的 Node 来运行 Pod。之后,调度器将这个调度决定通知给 kube-apiserver,这个过程叫做 _绑定_。 - - -在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、亲和以及反亲和要求、数据局域性、负载间的干扰等等。 - - -## kube-scheduler 调度流程 {#kube-scheduler-implementation} - - -kube-scheduler 给一个 pod 做调度选择包含两个步骤: - -1. 过滤 - -2. 打分 - - -过滤阶段会将所有满足 Pod 调度需求的 Node 选出来。例如,PodFitsResources 过滤函数会检查候选 Node 的可用资源能否满足 Pod 的资源请求。在过滤之后,得出一个 Node 列表,里面包含了所有可调度节点;通常情况下,这个 Node 列表包含不止一个 Node。如果这个列表是空的,代表这个 Pod 不可调度。 - - -在打分阶段,调度器会为 Pod 从所有可调度节点中选取一个最合适的 Node。根据当前启用的打分规则,调度器会给每一个可调度节点进行打分。 - - -最后,kube-scheduler 会将 Pod 调度到得分最高的 Node 上。如果存在多个得分最高的 Node,kube-scheduler 会从中随机选取一个。 - - -### 默认策略 - - -kube-scheduler 有一系列的默认调度策略。 - - -### 过滤策略 - -- `PodFitsHostPorts`:如果 Pod 中定义了 hostPort 属性,那么需要先检查这个指定端口是否 - 已经被 Node 上其他服务占用了。 - -- `PodFitsHost`:若 pod 对象拥有 hostname 属性,则检查 Node 名称字符串与此属性是否匹配。 - -- `PodFitsResources`:检查 Node 上是否有足够的资源(如,cpu 和内存)来满足 pod 的资源请求。 - -- `PodMatchNodeSelector`:检查 Node 的 {{< glossary_tooltip text="标签" term_id="label" >}} 是否能匹配 - Pod 属性上 Node 的 {{< glossary_tooltip text="标签" term_id="label" >}} 值。 - -- `NoVolumeZoneConflict`:检测 pod 请求的 {{< glossary_tooltip text="Volumes" term_id="volume" >}} 在 - Node 上是否可用,因为某些存储卷存在区域调度约束。 - -- `NoDiskConflict`:检查 Pod 对象请求的存储卷在 Node 上是否可用,若不存在冲突则通过检查。 - -- `MaxCSIVolumeCount`:检查 Node 上已经挂载的 {{< glossary_tooltip text="CSI" term_id="csi" >}} - 存储卷数量是否超过了指定的最大值。 - -- `CheckNodeMemoryPressure`:如果 Node 上报了内存资源压力过大,而且没有配置异常,那么 Pod 将不会被调度到这个 Node 上。 - -- `CheckNodePIDPressure`:如果 Node 上报了 PID 资源压力过大,而且没有配置异常,那么 Pod 将不会被调度到这个 Node 上。 - -- `CheckNodeDiskPressure`:如果 Node 上报了磁盘资源压力过大(文件系统满了或者将近满了), - 而且配置没有异常,那么 Pod 将不会被调度到这个 Node 上。 - -- `CheckNodeCondition`:Node 可以上报其自身的状态,如磁盘、网络不可用,表明 kubelet 未准备好运行 pod。 - 如果 Node 被设置成这种状态,那么 pod 将不会被调度到这个 Node 上。 - -- `PodToleratesNodeTaints`:检查 pod 属性上的 {{< glossary_tooltip text="tolerations" term_id="toleration" >}} 能否容忍 - Node 的 {{< glossary_tooltip text="taints" term_id="taint" >}}。 - -- `CheckVolumeBinding`:检查 Node 上已经绑定的和未绑定的 {{< glossary_tooltip text="PVCs" term_id="persistent-volume-claim" >}} - 能否满足 Pod 对象的存储卷需求。 - - -### 打分策略 - -- `SelectorSpreadPriority`:尽量将归属于同一个 {{< glossary_tooltip text="Service" term_id="service" >}}、{{< glossary_tooltip term_id="statefulset" >}} 或 {{< glossary_tooltip term_id="replica-set" >}} 的 Pod 资源分散到不同的 Node 上。 - -- `InterPodAffinityPriority`:遍历 Pod 对象的亲和性条目,并将那些能够匹配到给定 Node 的条目的权重相加,结果值越大的 Node 得分越高。 - -- `LeastRequestedPriority`:空闲资源比例越高的 Node 得分越高。换句话说,Node 上的 Pod 越多,并且资源被占用的越多,那么这个 Node 的得分就会越少。 - -- `MostRequestedPriority`:空闲资源比例越低的 Node 得分越高。这个调度策略将会把你所有的工作负载(Pod)调度到尽量少的 Node 上。 - -- `RequestedToCapacityRatioPriority`:为 Node 上每个资源占用比例设定得分值,给资源打分函数在打分时使用。 - -- `BalancedResourceAllocation`:优选那些使得资源利用率更为均衡的节点。 - -- `NodePreferAvoidPodsPriority`:这个策略将根据 Node 的注解信息中是否含有 `scheduler.alpha.kubernetes.io/preferAvoidPods` 来 - 计算其优先级。使用这个策略可以将两个不同 Pod 运行在不同的 Node 上。 - -- `NodeAffinityPriority`:基于 Pod 属性中 PreferredDuringSchedulingIgnoredDuringExecution 来进行 Node 亲和性调度。你可以通过这篇文章 - [Pods 到 Nodes 的分派](/zh/docs/concepts/configuration/assign-pod-node/) 来了解到更详细的内容。 - -- `TaintTolerationPriority`:基于 Pod 中对每个 Node 上污点容忍程度进行优先级评估,这个策略能够调整待选 Node 的排名。 - -- `ImageLocalityPriority`:Node 上已经拥有 Pod 需要的 {{< glossary_tooltip text="容器镜像" term_id="image" >}} 的 Node 会有较高的优先级。 - -- `ServiceSpreadingPriority`:这个调度策略的主要目的是确保将归属于同一个 Service 的 Pod 调度到不同的 Node 上。如果 Node 上 - 没有归属于同一个 Service 的 Pod,这个策略更倾向于将 Pod 调度到这类 Node 上。最终的目的:即使在一个 Node 宕机之后 Service 也具有很强容灾能力。 - -- `CalculateAntiAffinityPriorityMap`:这个策略主要是用来实现[pod反亲和] - (/zh/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity)。 - -- `EqualPriorityMap`:将所有的 Node 设置成相同的权重为 1。 - -{{% /capture %}} -{{% capture whatsnext %}} -* 阅读关于 [调度器性能调优](/zh/docs/concepts/scheduling/scheduler-perf-tuning/) -* 阅读关于 [Pod 拓扑分布约束](/zh/docs/concepts/workloads/pods/pod-topology-spread-constraints/) -* 阅读关于 kube-scheduler 的 [参考文档](/zh/docs/reference/command-line-tools-reference/kube-scheduler/) -* 了解关于 [配置多个调度器](/zh/docs/tasks/administer-cluster/configure-multiple-schedulers/) 的方式 -* 了解关于 [拓扑结构管理策略](/zh/docs/tasks/administer-cluster/topology-manager/) -* 了解关于 [Pod 额外开销](/zh/docs/concepts/configuration/pod-overhead/) -{{% /capture %}} diff --git a/content/zh/docs/concepts/scheduling/scheduler-perf-tuning.md b/content/zh/docs/concepts/scheduling/scheduler-perf-tuning.md deleted file mode 100644 index ccdb76fcc4..0000000000 --- a/content/zh/docs/concepts/scheduling/scheduler-perf-tuning.md +++ /dev/null @@ -1,185 +0,0 @@ ---- -title: 调度器性能调优 -content_template: templates/concept -weight: 70 ---- - - -{{% capture overview %}} - -{{< feature-state for_k8s_version="1.14" state="beta" >}} - - -作为 kubernetes 集群的默认调度器,kube-scheduler 主要负责将 Pod 调度到集群的 Node 上。 - - -在一个集群中,满足一个 Pod 调度请求的所有 Node 称之为 _可调度_ Node。调度器先在集群中找到一个 Pod 的可调度 Node,然后根据一系列函数对这些可调度 Node打分,之后选出其中得分最高的 Node 来运行 Pod。最后,调度器将这个调度决定告知 kube-apiserver,这个过程叫做 _绑定_。 - - -这篇文章将会介绍一些在大规模 Kubernetes 集群下调度器性能优化的方式。 - -{{% /capture %}} - -{{% capture body %}} - - -## 设置打分阶段 Node 数量占集群总规模的百分比 - - -在 Kubernetes 1.12 版本之前,kube-scheduler 会检查集群中所有节点的可调度性,并且给可调度节点打分。Kubernetes 1.12 版本添加了一个新的功能,允许调度器在找到一定数量的可调度节点之后就停止继续寻找可调度节点。该功能能提高调度器在大规模集群下的调度性能。这个数值是集群规模的百分比。这个百分比通过 `percentageOfNodesToScore` 参数来进行配置。其值的范围在 1 到 100 之间,最大值就是 100%。如果设置为 0 就代表没有提供这个参数配置。Kubernetes 1.14 版本又加入了一个特性,在该参数没有被用户配置的情况下,调度器会根据集群的规模自动设置一个集群比例,然后通过这个比例筛选一定数量的可调度节点进入打分阶段。该特性使用线性公式计算出集群比例,如在 100-node 的集群下取 50%。在 5000-node 的集群下取 10%。这个自动设置的参数的最低值是 5%。换句话说,调度器至少会对集群中 5% 的节点进行打分,除非用户将该参数设置的低于 5。 - - -下面就是一个将 `percentageOfNodesToScore` 参数设置为 50% 的例子。 - -```yaml -apiVersion: kubescheduler.config.k8s.io/v1alpha1 -kind: KubeSchedulerConfiguration -algorithmSource: - provider: DefaultProvider - -... - -percentageOfNodesToScore: 50 -``` - - -{{< note >}} 当集群中的可调度节点少于 50 个时,调度器仍然会去检查所有的 Node,因为可调度节点太少,不足以停止调度器最初的过滤选择。{{< /note >}} - - -**如果想要关闭这个功能**,你可以将 `percentageOfNodesToScore` 值设置成 100。 - - -### 调节 percentageOfNodesToScore 参数 - - -`percentageOfNodesToScore` 的值必须在 1 到 100 之间,而且其默认值是通过集群的规模计算得来的。另外,还有一个 50 个 Node 的数值是硬编码在程序里面的。设置这个值的作用在于:当集群的规模是数百个 Node 并且 `percentageOfNodesToScore` 参数设置的过低的时候,调度器筛选到的可调度节点数目基本不会受到该参数影响。当集群规模较小时,这个设置将导致调度器性能提升并不明显。然而在一个超过 1000 个 Node 的集群中,将调优参数设置为一个较低的值可以很明显的提升调度器性能。 - - -值得注意的是,该参数设置后可能会导致只有集群中少数节点被选为可调度节点,很多 node 都没有进入到打分阶段。这样就会造成一种后果,一个本来可以在打分阶段得分很高的 Node 甚至都不能进入打分阶段。由于这个原因,这个参数不应该被设置成一个很低的值。通常的做法是不会将这个参数的值设置的低于 10。很低的参数值一般在调度器的吞吐量很高且对 node 的打分不重要的情况下才使用。换句话说,只有当你更倾向于在可调度节点中任意选择一个 Node 来运行这个 Pod 时,才使用很低的参数设置。 - - -如果你的集群规模只有数百个节点或者更少,我们并不推荐你将这个参数设置得比默认值更低。因为这种情况下不太可能有效的提高调度器性能。 - - -### 调度器做调度选择的时候如何覆盖所有的 Node - - -如果你想要理解这一个特性的内部细节,那么请仔细阅读这一章节。 - - -在将 Pod 调度到 Node 上时,为了让集群中所有 Node 都有公平的机会去运行这些 Pod,调度器将会以轮询的方式覆盖全部的 Node。你可以将 Node 列表想象成一个数组。调度器从数组的头部开始筛选可调度节点,依次向后直到可调度节点的数量达到 `percentageOfNodesToScore` 参数的要求。在对下一个 Pod 进行调度的时候,前一个 Pod 调度筛选停止的 Node 列表的位置,将会来作为这次调度筛选 Node 开始的位置。 - - -如果集群中的 Node 在多个区域,那么调度器将从不同的区域中轮询 Node,来确保不同区域的 Node 接受可调度性检查。如下例,考虑两个区域中的六个节点: - -``` -Zone 1: Node 1, Node 2, Node 3, Node 4 -Zone 2: Node 5, Node 6 -``` - - -调度器将会按照如下的顺序去评估 Node 的可调度性: - -``` -Node 1, Node 5, Node 2, Node 6, Node 3, Node 4 -``` - - -在评估完所有 Node 后,将会返回到 Node 1,从头开始。 - -{{% /capture %}}