调度框架
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="adsense-banner" @click="$sendGaEvent('AdSense', 'AdSenseBanner', 'AdSenseBanner')">
|
||||
<div class="adsense-banner">
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<!-- 正文-横幅 -->
|
||||
<ins class="adsbygoogle"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="adsense-left-top" @click="$sendGaEvent('AdSense', 'AdSenseLeftTop', 'AdSenseLeftTop')">
|
||||
<div class="adsense-left-top">
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<!-- AdsenseLeftTop -->
|
||||
<ins class="adsbygoogle"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="adsense-page-bottom" @click="$sendGaEvent('AdSense', 'AdSensePageBottom', 'AdSensePageBottom')">
|
||||
<div class="adsense-page-bottom">
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<!-- AdSensePageBottom -->
|
||||
<ins class="adsbygoogle"
|
||||
|
||||
@ -21,7 +21,7 @@ export default {
|
||||
<style scoped>
|
||||
.adsense-page-bottom-inline {
|
||||
border: 1px solid #d7dae2;
|
||||
height: 160px;
|
||||
max-height: 160px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="adsense-page-top" @click.capture="$sendGaEvent('AdSense', 'AdSensePageTop', 'AdSensePageTop')">
|
||||
<div class="adsense-page-top">
|
||||
<!-- <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<ins class="adsbygoogle"
|
||||
style="display:block; text-align:center;"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="adsense-paragraph" @click="$sendGaEvent('AdSense', 'AdSenseParagraph', 'AdSenseParagraph')">
|
||||
<div class="adsense-paragraph">
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<ins class="adsbygoogle"
|
||||
style="display:block; text-align:center;"
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
<template>
|
||||
<div class="adsense-right" @click="$sendGaEvent('AdSense', 'AdSenseRightSide', 'AdSenseRightSide')">
|
||||
<div class="adsense-right">
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<!-- 右侧垂直 -->
|
||||
<!-- AdSenseRightSide -->
|
||||
<ins class="adsbygoogle"
|
||||
style="display:block; height: 40vh; max-width: calc(50vw - 720px); min-width: 200px;"
|
||||
style="display:block"
|
||||
data-ad-client="ca-pub-3313149841665250"
|
||||
data-ad-slot="2638666669"
|
||||
></ins>
|
||||
<!-- data-ad-format="auto"
|
||||
data-full-width-responsive="true" -->
|
||||
data-ad-format="auto"
|
||||
data-full-width-responsive="true"></ins>
|
||||
<script>
|
||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
||||
</script>
|
||||
@ -28,13 +27,13 @@ export default {
|
||||
<style scoped>
|
||||
|
||||
.adsense-right {
|
||||
width: 500px;
|
||||
max-width: calc(50vw - 720px);
|
||||
height: 40vh;
|
||||
width: calc(50vw - 700px);
|
||||
max-width: 450px;
|
||||
height: 50vh;
|
||||
position: fixed;
|
||||
bottom: 80px;
|
||||
right: 10px;
|
||||
/* background-color: grey; */
|
||||
background-color: grey;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div @click="$sendGaEvent('AdSense', 'AdSenseSquare', 'AdSenseSquare')">
|
||||
<div>
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<!-- 正方形-正文 -->
|
||||
<ins class="adsbygoogle"
|
||||
|
||||
@ -1,11 +1,17 @@
|
||||
<template>
|
||||
<div class="adsense-under-title" @click="$sendGaEvent('AdSense', 'AdSensePageTopUnderTitle', 'AdSensePageTopUnderTitle')">
|
||||
<!-- <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> -->
|
||||
<!-- PageTopUnderTitle -->
|
||||
<!-- <ins class="adsbygoogle"
|
||||
style="display:inline-block;min-width:200px;max-width:1000px;width:100%;height:50px"
|
||||
<div>
|
||||
<p>
|
||||
<Qq></Qq> 群号: 808894550 <span style="color: red; font-weight: 500;">在线答疑</span>,也可以扫描本文末尾的二维码加群
|
||||
</p>
|
||||
<slot></slot>
|
||||
<div class="adsense-page-top">
|
||||
<!-- <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<ins class="adsbygoogle"
|
||||
style="display:block; text-align:center;"
|
||||
data-ad-layout="in-article"
|
||||
data-ad-format="fluid"
|
||||
data-ad-client="ca-pub-3313149841665250"
|
||||
data-ad-slot="1677363818"></ins>
|
||||
data-ad-slot="6968314981"></ins>
|
||||
<script>
|
||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
||||
</script> -->
|
||||
@ -13,13 +19,14 @@
|
||||
<ins class="adsbygoogle"
|
||||
style="display:block"
|
||||
data-ad-format="fluid"
|
||||
data-ad-layout-key="-i0-3+1f-3d+2z"
|
||||
data-ad-layout-key="-h2+d+5c-9-3e"
|
||||
data-ad-client="ca-pub-3313149841665250"
|
||||
data-ad-slot="3534684042"></ins>
|
||||
data-ad-slot="4299889232"></ins>
|
||||
<script>
|
||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -29,7 +36,12 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.adsense-under-title {
|
||||
.adsense-page-top {
|
||||
/* background-color: green; */
|
||||
cursor: pointer;
|
||||
padding-right: 2px;
|
||||
border: 1px solid #d7dae2;
|
||||
height: 124px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
35
.vuepress/components/AdSenseTitlePureText.vue
Normal file
35
.vuepress/components/AdSenseTitlePureText.vue
Normal file
@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div class="adsense-under-title">
|
||||
<!-- <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> -->
|
||||
<!-- PageTopUnderTitle -->
|
||||
<!-- <ins class="adsbygoogle"
|
||||
style="display:inline-block;min-width:200px;max-width:1000px;width:100%;height:50px"
|
||||
data-ad-client="ca-pub-3313149841665250"
|
||||
data-ad-slot="1677363818"></ins>
|
||||
<script>
|
||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
||||
</script> -->
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<ins class="adsbygoogle"
|
||||
style="display:block"
|
||||
data-ad-format="fluid"
|
||||
data-ad-layout-key="-i0-3+1f-3d+2z"
|
||||
data-ad-client="ca-pub-3313149841665250"
|
||||
data-ad-slot="3534684042"></ins>
|
||||
<script>
|
||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
||||
</script>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.adsense-under-title {
|
||||
border: 1px solid #d7dae2;
|
||||
}
|
||||
</style>
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div @click="$sendGaEvent('AdSense', 'AdSenseVertical', 'AdSenseVertical')">
|
||||
<div>
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<!-- 正文-垂直 -->
|
||||
<ins class="adsbygoogle"
|
||||
|
||||
@ -443,6 +443,8 @@ module.exports = {
|
||||
collapsable: true,
|
||||
children: [
|
||||
'k8s-advanced/schedule/',
|
||||
'k8s-advanced/schedule/tuning',
|
||||
'k8s-advanced/schedule/framework',
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
@ -34,15 +34,8 @@
|
||||
<div class="tip custom-block" style="padding: 10px 20px; margin-top: 0;">
|
||||
<div style="display: inline-block; vertical-align: top;">
|
||||
<li><span style="color: red; font-weight: 500;">免费</span> Kubernetes 教程,绝不降低品质</li>
|
||||
<!-- <li><span style="color: red; font-weight: 500;">在线答疑</span> 扫第一个二维码完成打赏,扫第二个进微信群聊</li> -->
|
||||
<li><Qq></Qq> <span style="color: red; font-weight: 500;">在线答疑</span>,也可以扫描本文末尾的二维码加群</li>
|
||||
|
||||
<!-- <li>根据答疑反馈,<span style="color: red; font-weight: 500;">不断完善</span> 教程</li> -->
|
||||
<!-- <li><Qq></Qq> <span style="color: red; font-weight: 500;">在线答疑</span>,也可以扫描本文末尾的二维码加群</li> -->
|
||||
</div>
|
||||
<!-- <div style="display: inline-block; margin-left: 10px;">
|
||||
<img src="/images/dz.png" style="width: 100px; margin-right: 100px;"></img>
|
||||
<img src="/images/dz2.jpeg" style="width: 100px;"></img>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div slot="page-bottom" class="bottom-description">Copyright © 2019-present 邵欢庆 <a href="http://www.eigpay.com" target="_blank">仁聚汇通</a> | 京ICP备19008693号-2
|
||||
|
||||
@ -29,7 +29,7 @@ meta:
|
||||
|
||||
# 使用kubeadm安装kubernetes_v1.16.1
|
||||
|
||||
<AdSenseTitle/>
|
||||
<!-- <AdSenseTitle/> -->
|
||||
|
||||
<script>
|
||||
|
||||
@ -158,29 +158,18 @@ export default {
|
||||
* **Cent OS 7.6**
|
||||
|
||||
<grid :rwd="{compact: 'stack'}">
|
||||
<grid-item size="1/2" :rwd="{tablet: '1/1', compact: '1/1'}" style="padding: 1rem 0 1rem 1rem;">
|
||||
<grid-item size="2/3" :rwd="{tablet: '1/1', compact: '1/1'}" style="padding: 1rem 0 1rem 1rem;">
|
||||
|
||||
<div>
|
||||
|
||||
[领取腾讯云最高2860元代金券](https://cloud.tencent.com/act/cps/redirect?redirect=1040&cps_key=2ee6baa049659f4713ddc55a51314372&from=console)
|
||||
|
||||
[腾讯云限时1折秒杀](https://cloud.tencent.com/act/cps/redirect?redirect=1044&cps_key=2ee6baa049659f4713ddc55a51314372&from=console)
|
||||
|
||||
[领取阿里云最高2000元红包](https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=obezo3pg)
|
||||
|
||||
[阿里云服务器限时2折](https://www.aliyun.com/acts/limit-buy?userCode=obezo3pg)
|
||||
|
||||
</div>
|
||||
|
||||
</grid-item>
|
||||
<grid-item size="1/2" :rwd="{tablet: '1/1', compact: '1/1'}" style="padding: 2rem 1rem 1rem 1rem;">
|
||||
<a href="https://cloud.tencent.com/act/cps/redirect?redirect=1040&cps_key=2ee6baa049659f4713ddc55a51314372&from=console">
|
||||
<img src="/images/pr/tencent-345x200-.jpg" alt="Kubernetes安装_服务器选择" style="width: 270px;">
|
||||
</a>
|
||||
</grid-item>
|
||||
</grid>
|
||||
|
||||
<grid :rwd="{compact: 'stack'}">
|
||||
<grid-item size="2/3" :rwd="{tablet: '1/1', compact: '1/1'}" style="padding: 1rem 0 1rem 1rem;">
|
||||
|
||||
<div>
|
||||
|
||||
**安装后的软件版本为**
|
||||
|
||||
* Kubernetes v1.16.1
|
||||
|
||||
@ -10,18 +10,21 @@ meta:
|
||||
|
||||
# Kubernetes免费中文教程
|
||||
|
||||
<AdSenseTitle/>
|
||||
|
||||
<AdSenseTitle>
|
||||
|
||||
本教程的主要依据是:Kubernetes 官网文档,以及使用 Kubernetes 落地 Spring Cloud 微服务并投产的实战经验。适用人群:
|
||||
* Kubernetes 初学者
|
||||
* 学习过 Kubernetes,但在投产过程中仍有诸多疑虑和困惑的技术爱好者
|
||||
|
||||
<div style="background-color: #0063dc;">
|
||||
</AdSenseTitle>
|
||||
|
||||
|
||||
|
||||
<!-- <div style="background-color: #0063dc;">
|
||||
<div style="max-width: 363px; margin: auto;">
|
||||
<img src="/images/logo-main.png" style="background-color: #0063dc; max-width: 100%;" alt="Kubernetes管理界面:Kuboard Logo"/>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
## **Kubernetes 介绍**
|
||||
|
||||
@ -88,10 +91,12 @@ meta:
|
||||
|
||||
## **Kubernetes 高级**
|
||||
|
||||
* [Kubernetes 日志](/learning/k8s-advanced/logs/)
|
||||
* Kubernetes 监控
|
||||
* Kubernetes 联邦
|
||||
* 扩展 Kubernetes
|
||||
* [问题诊断](/learning/k8s-advanced/ts/application.html)
|
||||
* [日志](/learning/k8s-advanced/logs/)
|
||||
* [调度](/learning/k8s-advanced/schedule)
|
||||
* 安全
|
||||
* 监控
|
||||
* 联邦
|
||||
|
||||
## **Kubernetes 实战**
|
||||
|
||||
|
||||
@ -11,9 +11,8 @@ description: Kubernetes教程_高级篇_主要涉及日志采集_安全_监控_
|
||||
Kubernetes教程的深入篇部分,主要涉及的内容有如下几个方面:
|
||||
|
||||
* [问题诊断](./ts/application.html)
|
||||
* [Kubernetes 日志](./logs/)
|
||||
* Kubernetes 安全
|
||||
* Kubernetes 监控
|
||||
* Kubernetes 联邦
|
||||
|
||||
将在 Kubernetes 教程进阶篇,以及 Kubernetes 教程的实战篇完成后开始编写。
|
||||
* [日志](./logs/)
|
||||
* [调度](./schedule)
|
||||
* 安全
|
||||
* 监控
|
||||
* 联邦
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 73 KiB |
238
learning/k8s-advanced/schedule/framework.md
Normal file
238
learning/k8s-advanced/schedule/framework.md
Normal file
@ -0,0 +1,238 @@
|
||||
---
|
||||
vssueId: 131
|
||||
layout: LearningLayout
|
||||
description: Kubernete教程_Kubernetes v1.15 版本中引入了可插拔架构的调度框架,使得定制调度器这个任务变得更加的容易。调库框架向现有的调度器中添加了一组插件化的 API。
|
||||
meta:
|
||||
- name: keywords
|
||||
content: Kubernetes 教程,Kubernetes 调度,Kubernetes Scheduling
|
||||
---
|
||||
|
||||
# 框架
|
||||
|
||||
> 参考文档:[Scheduling Framework](https://kubernetes.io/docs/concepts/configuration/scheduling-framework/)
|
||||
|
||||
<AdSenseTitle/>
|
||||
|
||||
**FEATURE STATE:** `Kubernetes v1.15` <Badge type="error">alpha</Badge>
|
||||
|
||||
Kubernetes v1.15 版本中引入了可插拔架构的调度框架,使得定制调度器这个任务变得更加的容易。调库框架向现有的调度器中添加了一组插件化的 API。该 API在保持调度程序“核心”保持简单且易于维护的同时,使得大部分的调度功能以插件的形式存在。参考 [Design proposal of the scheduling framework](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/20180409-scheduling-framework.md) 可了解调度框架更多的技术细节。
|
||||
|
||||
## 工作流
|
||||
|
||||
调度框架定义了一组扩展点。用户可以实现扩展点定义的接口以定义自己的调度逻辑(我们称之为扩展),并将扩展注册到扩展点上,调度框架在执行调度工作流时,遇到对应的扩展点时,将调用用户注册的扩展。调度框架在预留扩展点时,都是有特定的目的,有些扩展点上的扩展可以改变调度程序的决策方法,有些扩展点上的扩展只是发送一个通知。
|
||||
|
||||
## 调度过程/绑定过程
|
||||
|
||||
参考 [调度](./) 中所描述的,每一次调度一个 Pod 时,都按照两个过程来执行:调度过程和绑定过程。
|
||||
|
||||
调度过程为 Pod 选择一个合适的节点,绑定过程则将调度过程的决策应用到集群中(在被选定的节点上运行 Pod)。调度过程和绑定过程合在一起,称之为 **调度上下文(scheduling context)**。
|
||||
|
||||
调度过程同步运行(同一时间点只为一个 Pod 进行调度),绑定过程可异步运行(同一时间点可并发为多个 Pod 执行绑定)。
|
||||
|
||||
调度过程和绑定过程在如下情况时,会中途退出:
|
||||
* 调度程序认为当前没有该 Pod 的可选节点
|
||||
* 内部错误
|
||||
|
||||
此时,Pod 将被放回到 待调度队列,并等待下次重试。
|
||||
|
||||
## 扩展点 Extension Points
|
||||
|
||||
下图展示了调度框架中的调度上下文及其中的扩展点。该图中 “Filter(过滤器)”与“Soring(评分)”的解释,请参考 [使用kube-scheduler调度](learning/k8s-advanced/schedule/#使用kube-scheduler调度)。
|
||||
|
||||
一个扩展可以注册多个扩展点,以便可以执行更复杂的有状态的任务。
|
||||
|
||||
<p style="max-width: 750px">
|
||||
<img src="./framework.assets/scheduling-framework-extensions.png" style="padding: 5px;" alt="Kubernetes教程_调度框架及扩展点"/>
|
||||
</p>
|
||||
|
||||
### Queue sort
|
||||
|
||||
Que sort 扩展用于对 Pod 的待调度队列进行排序,以决定先调度哪个 Pod。 Que sort扩展本质上只需要实现一个方法 `less(Pod1, Pod2)` 用于比较两个 Pod 谁更优先获得调度。同一时间点只能有一个 que sort 插件生效。
|
||||
|
||||
### Pre-filter
|
||||
|
||||
Pre-filter 扩展用于对 Pod 的信息进行预处理,或者检查一些集群或 Pod 必须满足的前提条件。如果 pre-filter 返回了 error,则调度过程终止。
|
||||
|
||||
### Filter
|
||||
|
||||
Filter 扩展用于排除那些不能运行该 Pod 的节点。对于每一个节点,调度器将按顺序执行 filter 扩展;如果任何一个 filter 将节点标记为不可选,则余下的 filter 扩展将不会被执行。调度器可以同时对多个节点执行 filter 扩展。
|
||||
|
||||
### Post-filter
|
||||
|
||||
Post-filter 是一个通知类型的扩展点。调用该扩展的参数是 filter 阶段结束后被筛选为 ***可选节点*** 的节点列表。可以在扩展中使用这些信息更新内部状态,或者产生日志或度量信息。
|
||||
|
||||
::: tip
|
||||
如果想要在 "Scoring" 评分工作之前执行一些逻辑,应该实现 post-filter 扩展点。
|
||||
:::
|
||||
|
||||
### Scoring
|
||||
|
||||
Scoring 扩展用于为所有可选节点评分。调度器将针对每一个节点调用 Soring 扩展。评分结果是一个范围内的整数。在 `normalize scoring` 阶段,调度器将会把每个 scoring 扩展对具体某个个节点的评分结果和该扩展的权重合并起来,作为最终评分结果。
|
||||
|
||||
### Normalize scoring
|
||||
|
||||
Normalize scoring 扩展在调度器对节点进行最终排序之前修改每个节点的评分结果。注册到该扩展点的扩展时在被调用时,将获得同一个插件中的 scoring 扩展的评分结果作为参数。调度框架每执行一次调度,都将调用所有插件中的一个 normalize scoring 扩展一次。
|
||||
|
||||
::: tip 译者注
|
||||
如前所述,一个插件中可以包括多个扩展,每个扩展可以注册到调度框架中的一个扩展点。可以认为
|
||||
* 插件是扩展的打包
|
||||
* 扩展是针对扩展点的实现
|
||||
* 扩展点是调度框架预先定义的可插拔可客户化的接口,必须有实现该扩展点接口的扩展注册到调度框架
|
||||
:::
|
||||
|
||||
例如,假设 `BlinkingLightScorer` 插件注册了 scoring 扩展点,该扩展根据节点拥有的 "blinking lights" 数量对节点评分。(blinking light是假想的一个节点属性)
|
||||
|
||||
``` go
|
||||
func ScoreNode(_ *v1.pod, n *v1.Node) (int, error) {
|
||||
return getBlinkingLightCount(n)
|
||||
}
|
||||
```
|
||||
|
||||
然而,Scoring 扩展对节点计算出来的 `NodeScoreMax`(节点实际的 `blinking light` 最大数)可能比评分结果允许的 `blinking light` 最大数要大。为了修正此问题,`BlinkingLightScorer` 插件同样要注册 Normalize scoring 扩展点,逻辑如下所示:
|
||||
|
||||
``` go
|
||||
func NormalizeScores(scores map[string]int) {
|
||||
highest := 0
|
||||
for _, score := range scores {
|
||||
highest = max(highest, score)
|
||||
}
|
||||
for node, score := range scores {
|
||||
scores[node] = score*NodeScoreMax/highest
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
如果任何一个 normalize-scoring 插件返回了错误,调度过程将终止。
|
||||
|
||||
::: tip
|
||||
如果想要在 `Reserve` 之前执行某些逻辑,可以使用 `normalize-scoring` 扩展点。
|
||||
:::
|
||||
|
||||
### Reserve
|
||||
|
||||
Reserve 是一个通知性质的扩展点。有状态的插件可以使用该扩展点获得如下通知:已在节点上为 Pod 预留资源。该事件发生在调度器将 Pod 绑定到节点之前,目的是避免调度器在等待 Pod 与节点绑定的过程中调度新的 Pod 到节点上时,发生实际使用资源超出可用资源的情况。(如前面所述,绑定 Pod 到节点上是异步发生的)
|
||||
|
||||
这是调度过程的最后一个步骤。Pod 进入 `reserved` 状态以后,要么在绑定失败时触发 [Unreserve](#unreserve) 扩展,要么在绑定成功时,由 [Post-bind](#post-bind) 扩展结束绑定过程。
|
||||
|
||||
### Permit
|
||||
|
||||
Permit 扩展用于阻止或者延迟 Pod 与节点的绑定。Permit 扩展可以做如下三项当中的一个选择:
|
||||
* **approve**
|
||||
|
||||
当所有的 permit 扩展都 `approve`(批准)了 Pod 与节点的绑定,调度器将继续执行绑定过程
|
||||
|
||||
* **deny**
|
||||
|
||||
如果任何一个 permit 扩展 `deny`(拒绝)了 Pod 与节点的绑定,Pod 将被放回到待调度队列,此时将触发 [Unreserve](#unreserve) 扩展
|
||||
|
||||
* **wait** (等待超时时间)
|
||||
|
||||
如果一个 permit 扩展返回了 `wait`(等待),则 Pod 将保持在 permit 阶段,直到被其他扩展 approve。如果超时事件发生,`wait` 状态变成 `deny`,Pod 将被放回到待调度队列,此时将触发 [Unreserve](#unreserve) 扩展
|
||||
|
||||
### Pre-bind
|
||||
|
||||
Pre-bind 扩展用于在 Pod 绑定之前执行某些逻辑。例如,pre-bind 扩展可以将一个基于网络的数据卷挂载到节点上,以便 Pod 可以使用。
|
||||
|
||||
如果任何一个 pre-bind 扩展返回错误,Pod 将被放回到待调度队列,此时将触发 [Unreserve](#unreserve) 扩展
|
||||
|
||||
### Bind
|
||||
|
||||
Bind 扩展用于将 Pod 绑定到节点上。
|
||||
* 只有所有的 pre-bind 扩展都成功执行了,bind 扩展才会执行
|
||||
* 调度框架按照 bind 扩展注册的顺序逐个调用 bind 扩展
|
||||
* 具体某个 bind 扩展可以选择处理或者不处理该 Pod
|
||||
* 如果某个 bind 扩展处理了该 Pod 与节点的绑定,**余下的 bind 扩展将被忽略**
|
||||
|
||||
### Post-bind
|
||||
|
||||
Post-bind 是一个通知性质的扩展:
|
||||
* Post-bind 扩展在 Pod 成功绑定到节点上之后被动调用
|
||||
* Post-bind 扩展式绑定过程的最后一个步骤,可以用来执行资源清理的动作
|
||||
|
||||
### Unreserve
|
||||
|
||||
Unreserve 是一个通知性质的扩展。如果为 Pod 预留了资源,Pod 有在被绑定过程中被拒绝绑定,则 unreserve 扩展将被调用。Unreserve 扩展应该释放已经为 Pod 预留的节点上的计算资源。
|
||||
|
||||
在一个插件中,reserve 扩展和 unreserve 扩展应该成对出现。
|
||||
|
||||
## 插件接口
|
||||
|
||||
向调度框架提供扩展,必须完成两个步骤:
|
||||
* 向调度框架注册插件并完成配置
|
||||
* 插件必须实现扩展点接口
|
||||
|
||||
扩展点接口的格式如下所示:
|
||||
|
||||
``` go
|
||||
type Plugin interface {
|
||||
Name() string
|
||||
}
|
||||
|
||||
type QueueSortPlugin interface {
|
||||
Plugin
|
||||
Less(*v1.pod, *v1.pod) bool
|
||||
}
|
||||
|
||||
type PreFilterPlugin interface {
|
||||
Plugin
|
||||
PreFilter(PluginContext, *v1.pod) error
|
||||
}
|
||||
|
||||
// ...
|
||||
```
|
||||
|
||||
## 插件配置
|
||||
|
||||
可以通过配置启用或者禁用调度框架的插件。
|
||||
|
||||
调度框架的配置中,也可以包含插件自己所需要的配置。这些配置信息将在调度框架初始化插件的时候传递给插件。插件自己的配置信息可以是任何内容,由使用该配置的插件自己解析和使用该配置信息。
|
||||
|
||||
下面的例子中展示的配置启用了一个实现了 `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: >
|
||||
foo插件可以解析的任意内容
|
||||
```
|
||||
|
||||
扩展的调用顺序如下:
|
||||
* 如果某个扩展点没有配置对应的扩展,调度框架将使用默认插件中的扩展
|
||||
* 如果为某个扩展点配置且激活了扩展,则调度框架将先调用默认插件的扩展,再调用配置中的扩展。
|
||||
* 默认插件的扩展始终被最先调用,然后按照 `KubeSchedulerConfiguration` 中扩展的激活 `enabled` 顺序逐个调用扩展点的扩展。
|
||||
* 可以先禁用默认插件的扩展,然后在 `enabled` 列表中的某个位置激活默认插件的扩展。这种做法可以改变默认插件的扩展被调用时的次序
|
||||
|
||||
假设默认插件 `foo` 实现了 `reserve` 扩展点,此时我们要添加一个插件 `bar`,想要在 `foo` 之前被调用,则应该先禁用 `foo` 在按照 `bar` `foo` 的顺序激活。示例配置如下所示:
|
||||
|
||||
``` yaml
|
||||
apiVersion: kubescheduler.config.k8s.io/v1alpha1
|
||||
kind: KubeSchedulerConfiguration
|
||||
|
||||
...
|
||||
|
||||
plugins:
|
||||
reserve:
|
||||
enabled:
|
||||
- name: bar
|
||||
- name: foo
|
||||
disabled:
|
||||
- name: foo
|
||||
```
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
# vssueId: 117
|
||||
vssueId: 129
|
||||
layout: LearningLayout
|
||||
description: Kubernete教程_在Kubernetes中,调度(Scheduling),指的是为 Pod 找到一个合适的节点,并由该节点上的 kubelet 运行 Pod。
|
||||
meta:
|
||||
|
||||
79
learning/k8s-advanced/schedule/tuning.md
Normal file
79
learning/k8s-advanced/schedule/tuning.md
Normal file
@ -0,0 +1,79 @@
|
||||
---
|
||||
vssueId: 130
|
||||
layout: LearningLayout
|
||||
description: Kubernete教程_kube-scheduler是 Kubernetes 中的默认调度器。负责为 Pod 在集群中选择合适的节点。本文解释了在规模较大的 Kubernetes 集群中如何对 kube-scheduler 进行性能调优。
|
||||
meta:
|
||||
- name: keywords
|
||||
content: Kubernetes 教程,Kubernetes 调度,Kubernetes Scheduling
|
||||
---
|
||||
|
||||
# 调优
|
||||
|
||||
<AdSenseTitle/>
|
||||
|
||||
> 参考文档: [Scheduler Performance Tuning](https://kubernetes.io/docs/concepts/scheduling/scheduler-perf-tuning/)
|
||||
|
||||
**FEATURE STATE:** `Kubernetes v1.14` <Badge type="warning">beta</Badge>
|
||||
|
||||
[kube-scheduler](/learning/k8s-advanced/schedule/#kube-scheduler) 是 Kubernetes 中的默认调度器。负责为 Pod 在集群中选择合适的节点。
|
||||
|
||||
集群中能够满足某一个 Pod 的资源需求的节点,我们称其为 ***可选节点***(feasible node)。调度器在执行调度时,执行的步骤如下:
|
||||
1. 找出该 Pod 的所有 ***可选节点***
|
||||
2. 按照某种方式对每一个 ***可选节点*** 评分
|
||||
3. 选择评分最高的 ***可选节点***
|
||||
4. 将最终选择结果通知 API Server,`这个过程,我们称其为绑定(binding)`
|
||||
|
||||
本文解释了在规模较大的 Kubernetes 集群中如何对 kube-scheduler 进行性能调优。
|
||||
|
||||
## 参与评分的节点的比例
|
||||
|
||||
在 Kubernetes v1.12 版本之前,kube-scheduler 检查集群中的所有节点是否对 Pod 可选,并对 ***可选节点*** 进行评分。在 Kubernetes v1.12 中,添加了一个新的特性,使得 kube-scheduler 在找到了一定数量的 ***可选节点*** 后,变停止继续寻找更多 ***可选节点***。 这个特性可以显著提高 kube-scheduler 在大规模 Kubernetes 集群中的性能。通过 `percentageOfNodesToScore` 这个配置参数,我们可以控制 kube-scheduler 在找到多少 ***可用节点*** 之后变停止继续寻找。该参数的可选值为 1 - 100 之间的数字,大于 100 的将被认为是 100%,0 代表忽略该配置。
|
||||
|
||||
在 Kubernetes v1.14 中,如果不定义 `percentageOfNodesToScore`,kube-scheduler 将按照一个线性公式来确定该餐朱的取值。按照该公式:
|
||||
* 100节点集群,`percentageOfNodesToScore` 为 50%
|
||||
* 5000节点集群,`percentageOfNodesToScore` 为 10%
|
||||
* `percentageOfNodesToScore` 的最小值为 5%;(即,不论集群规模有多大,按照该公式,`percentageOfNodesToScore` 最终取值为 5%,除非集群管理员将该参数配置为小于 5% 的值)
|
||||
|
||||
下面的例子中,将 `percentageOfNodesToScore` 配置为 50%
|
||||
|
||||
``` yaml
|
||||
apiVersion: kubescheduler.config.k8s.io/v1alpha1
|
||||
kind: KubeSchedulerConfiguration
|
||||
algorithmSource:
|
||||
provider: DefaultProvider
|
||||
|
||||
...
|
||||
|
||||
percentageOfNodesToScore: 50
|
||||
```
|
||||
|
||||
::: tip 例外
|
||||
当集群中可选节点数量少于 50 时,调度器仍将继续检查剩余的节点。
|
||||
:::
|
||||
|
||||
如果要禁用该特性,可将 `percentageOfNodesToScore` 设定为 100。
|
||||
|
||||
### 调优 percentageOfNodesToScore
|
||||
|
||||
`percentageOfNodesToScore` 的取值在 1 到 100 之间,默认值基于集群节点的数量计算得出。并且,将至少要找出 50 个可选节点,否则仍会检查集群中所有节点是否对 Pod 可用。这就意味着,当集群的节点数不超过 1000 时,修改该参数并不会对实际结果产生多大的影响。Kubernetes 有意做了此设计,因为在小规模集群中,kube-scheduler 的性能差异不大。当集群节点数超过 1000 时,调整此参数将有可能显著提升 kube-scheduler 的性能。
|
||||
|
||||
关于 `percentageOfNodesToScore`,一个重要的考虑因素是,如果只检查了集群中一小部分节点对 Pod 是否可选,也就意味着更多的节点未能参与该 Pod 的评分。此时存在的可能性是,未参与评分的节点数量可能实际得分会比最终选中的节点得分更高,即,Pod 并没有找到集群中“最”适合其运行的节点。因此,`percentageOfNodesToScore` 不应该设置为一个过低的数值。通常,不要将其设置为低于 10 的数字。在如下情况都满足时,可以考虑更低的数字:
|
||||
* kube-scheduler 的吞吐量(每秒钟执行调度的次数)非常重要
|
||||
* 节点的评分是否为最高,没那么重要
|
||||
|
||||
当集群节点数量不超过 1000甚至更少时,不推荐修改该参数的默认取值,此时调整此参数对 kube-scheduler 性能的影响不大。
|
||||
|
||||
### 调度器遍历节点的方法
|
||||
|
||||
为了让集群中的每个节点都有公平的机会被 Pod 选中,调度器按照 round-robin(轮询)的方式遍历节点。您可以认为,节点被放在一个数组中,调度器从数组的第一个元素开始检查节点是否为 ***可选节点***,直到其找到足够多数量(由`percentageOfNodesToScore`指定)的 ***可选节点***。当调度器调度下一个 Pod 时,将继续从上一次停止的地方往后面便利节点的数组,到达数组的末尾时,又从数组的第一个元素继续遍历。
|
||||
|
||||
如果节点在多个高可用区,调度器将遍历多个高可用区终端额节点,以确保不同的可用区都有合适的机会。例如,假设 6 个节点分布于两个可用区:
|
||||
```
|
||||
Zone 1: Node 1, Node 2, Node 3, Node 4
|
||||
Zone 2: Node 5, Node 6
|
||||
```
|
||||
调度器将按照下面的顺序评估节点是否为可选节点:
|
||||
```
|
||||
Node 1, Node 5, Node 2, Node 6, Node 3, Node 4
|
||||
```
|
||||
到达结尾 Node 4 后,又从 Node 1 继续遍历。
|
||||
@ -8,8 +8,6 @@ meta:
|
||||
|
||||
# Kuboard简介
|
||||
|
||||
<AdSenseTitle/>
|
||||
|
||||
<div style="background-color: #0063dc;">
|
||||
<div style="max-width: 363px; margin: auto;">
|
||||
<img src="/images/logo-main.png" style="background-color: #0063dc; max-width: 100%; vertical-align: bottom;" alt="Kubernetes管理界面:Kuboard Logo"/>
|
||||
|
||||
Reference in New Issue
Block a user