Custom Scheduler 测验(第 1 部分)
本测验用于测试你对在 Kubernetes 中实现和使用 Custom Scheduler 的理解。
测验问题
1. 在 Kubernetes 中,scheduler 的主要作用是什么?
A. Pod 的创建和删除 B. 将 Pod 分配给合适的 Node C. Node 资源监控 D. Container image 下载
显示答案
答案: B. 将 Pod 分配给合适的 Node
解析: 在 Kubernetes 中,scheduler 的主要作用是将 Pod 分配给合适的 Node。scheduler 会监听新创建的 Pod,并为尚未分配到 Node 的 Pod 找到最适合运行它们的 Node。
Scheduler 的主要功能:
- Pod-Node 分配: 根据 Pod 需求和 Node 可用资源选择最优 Node。
- Filtering: 排除无法运行该 Pod 的 Node(例如资源不足、taints 等)。
- Scoring: 对合适的 Node 进行评分,以选择最优 Node。
- Binding: 将 Pod 绑定到所选 Node,以最终确定调度决策。
调度流程:
Filtering Stage (Predicates): 排除无法运行该 Pod 的 Node。
- PodFitsResources: 检查 Node 是否有足够资源满足 Pod 的 resource requests
- PodFitsHostPorts: 检查请求的 host ports 是否可用
- PodMatchNodeSelector: 检查 Pod 的 node selector 是否匹配 Node labels
- NoVolumeZoneConflict: 检查 volume zone 约束
- CheckNodeMemoryPressure: 检查 Node memory pressure 状态
- CheckNodeDiskPressure: 检查 Node disk pressure 状态
Scoring Stage (Priorities): 对合适的 Node 进行评分。
- LeastRequestedPriority: 给已请求资源较少的 Node 更高分数
- BalancedResourceAllocation: 给资源使用更均衡的 Node 更高分数
- NodeAffinityPriority: 基于 node affinity 规则评分
- TaintTolerationPriority: 基于 taint toleration 评分
- InterPodAffinityPriority: 基于 inter-pod affinity/anti-affinity 评分
Binding: 将 Pod 绑定到得分最高的 Node。
默认 Scheduler 配置示例:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
plugins:
score:
disabled:
- name: NodeResourcesLeastAllocated
enabled:
- name: NodeResourcesBalancedAllocation
weight: 1其他选项的问题:
- A. Pod 的创建和删除: 这主要是 controller manager 和 API server 的职责。
- C. Node 资源监控: 这主要是 kubelet 和 metrics server 的职责。
- D. Container image 下载: 这是 kubelet 和 container runtime 的职责。
2. 以下哪一项不是实现 Custom Scheduler 的方法?
A. 扩展现有的 kube-scheduler B. 实现一个全新的 scheduler C. 开发 scheduling framework plugin D. 修改 kubelet
显示答案
答案: D. 修改 kubelet
解析: 修改 kubelet 不是实现 Custom Scheduler 的方法。kubelet 是运行在每个 Node 上并管理 Pod 执行的代理,但它不做调度决策。调度由 kube-scheduler 或 custom schedulers 执行。
实现 Custom Scheduler 的方法:
扩展现有的 kube-scheduler:
- 使用 KubeSchedulerConfiguration 自定义默认 scheduler 的行为。
- 调整 plugin 权重、启用/禁用等。
yamlapiVersion: kubescheduler.config.k8s.io/v1 kind: KubeSchedulerConfiguration profiles: - schedulerName: custom-scheduler plugins: score: disabled: - name: NodeResourcesLeastAllocated enabled: - name: NodeResourcesBalancedAllocation weight: 2实现一个全新的 scheduler:
- 开发一个与 Kubernetes API 通信的独立 scheduler。
- 直接实现 Pod 监听、Node 选择和绑定逻辑。
go// Simple Go scheduler example func main() { config, err := clientcmd.BuildConfigFromFlags("", os.Getenv("KUBECONFIG")) if err != nil { log.Fatal(err) } clientset, err := kubernetes.NewForConfig(config) if err != nil { log.Fatal(err) } // Watch unscheduled pods watchPods(clientset) } func watchPods(clientset *kubernetes.Clientset) { watch, err := clientset.CoreV1().Pods("").Watch(context.TODO(), metav1.ListOptions{ FieldSelector: "spec.schedulerName=custom-scheduler,spec.nodeName=", }) if err != nil { log.Fatal(err) } for event := range watch.ResultChan() { if event.Type != watch.Added { continue } pod := event.Object.(*v1.Pod) // Implement node selection logic node := selectNode(clientset, pod) if node != "" { bindPod(clientset, pod, node) } } }开发 scheduling framework plugin:
- 使用 Kubernetes scheduling framework 为特定调度阶段开发 plugins。
- 实现 filter、score、bind 等 extension points。
go// Scoring plugin example type MyScorePlugin struct{} func (pl *MyScorePlugin) Name() string { return "MyScorePlugin" } func (pl *MyScorePlugin) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) { // Implement custom scoring logic return score, nil } func (pl *MyScorePlugin) ScoreExtensions() framework.ScoreExtensions { return pl } func (pl *MyScorePlugin) NormalizeScore(ctx context.Context, state *framework.CycleState, pod *v1.Pod, scores framework.NodeScoreList) *framework.Status { // Implement score normalization logic return nil }
kubelet 的作用: kubelet 是运行在每个 Node 上的代理,执行以下职责:
- 根据 Pod specs 运行和管理 containers
- 监控并报告 Node 状态
- 执行 container health checks
- 管理 volume mounts
kubelet 执行 scheduler 做出的决策(在哪个 Node 上运行哪个 Pod),它本身不做调度决策。
其他选项说明:
- A. 扩展现有的 kube-scheduler: 有效的 Custom Scheduler 实现方法。
- B. 实现一个全新的 scheduler: 有效的 Custom Scheduler 实现方法。
- C. 开发 scheduling framework plugin: 有效的 Custom Scheduler 实现方法。
3. 在 Pod 中,用于指定特定 scheduler 的字段是什么?
A. spec.scheduler B. spec.schedulerName C. metadata.scheduler D. spec.nodeName
显示答案
答案: B. spec.schedulerName
解析: 在 Pod 中用于指定特定 scheduler 的字段是 spec.schedulerName。设置此字段后,Pod 只会由具有指定名称的 scheduler 进行调度。默认值是 "default-scheduler"。
Pod Spec 示例:
apiVersion: v1
kind: Pod
metadata:
name: custom-scheduled-pod
labels:
app: my-app
spec:
schedulerName: my-custom-scheduler # Specify custom scheduler
containers:
- name: main-container
image: nginx:1.19
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"此 Pod 只会由名为 "my-custom-scheduler" 的 scheduler 调度。如果集群中不存在该名称的 scheduler,Pod 将保持在 Pending 状态。
部署多个 Scheduler 的示例:
# Custom scheduler deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-custom-scheduler
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
component: my-custom-scheduler
template:
metadata:
labels:
component: my-custom-scheduler
spec:
serviceAccountName: my-custom-scheduler
containers:
- name: scheduler
image: my-custom-scheduler:v1.0
args:
- --scheduler-name=my-custom-scheduler
- --leader-elect=false选择 Scheduler 时的注意事项:
- Availability: 如果指定的 scheduler 未运行,Pod 将不会被调度。
- Functionality: 每个 scheduler 可以有不同的调度算法和策略。
- Resource isolation: 可以使用不同的 scheduler 来隔离 workloads。
- Special hardware: 可以为 GPU 或 FPGA 等特殊硬件使用专用 scheduler。
检查 Scheduler 状态:
# Check pod status
kubectl get pod custom-scheduled-pod
# Check scheduling events
kubectl describe pod custom-scheduled-pod | grep -A 5 Events
# Check scheduler logs
kubectl logs -n kube-system -l component=my-custom-scheduler其他选项的问题:
- A. spec.scheduler: Kubernetes API 中不存在的字段。
- C. metadata.scheduler: Kubernetes API 中不存在的字段。
- D. spec.nodeName: 此字段用于绕过 scheduler 并将 Pod 直接分配给特定 Node。它不是用于指定 scheduler 的字段。
A. 对 Node 进行评分 B. 将 Pod 绑定到 Node C. 排除 Pod 无法运行的 Node D. 对 scheduling queue 中的 Pod 进行排序
显示答案
答案: C. 排除 Pod 无法运行的 Node
解析: 在 Kubernetes scheduling framework 中,"Filter" extension point(以前称为 "Predicate")的作用是排除 Pod 无法运行的 Node。Filter plugins 会检查每个 Node 是否满足 Pod 的需求,并将不满足需求的 Node 从候选列表中排除。
Scheduling Framework Extension Points: Scheduling framework 提供了多种 extension points,可以在调度周期的不同阶段集成 plugins:
- Queue Sort: 决定 Pod 在 scheduling queue 中的顺序。
- PreFilter: 在 filtering 之前对 Pod 和集群状态执行预处理。
- Filter: 排除 Pod 无法运行的 Node。
- PreScore: 执行 scoring 前所需的计算。
- Score: 为通过 filtering 的 Node 分配分数。
- NormalizeScore: 规范化每个 scoring plugin 的分数。
- Reserve: 在所选 Node 上为 Pod 预留资源。
- Permit: 允许、拒绝或延迟 Pod 调度。
- PreBind: 执行 binding 前所需的工作。
- Bind: 将 Pod 绑定到 Node。
- PostBind: 在 binding 后执行清理工作。
默认 Filter Plugins: Kubernetes 提供以下默认 filter plugins:
- NodeResourcesFit: 检查 Node 是否有足够资源满足 Pod 的 resource requests。
- NodeName: 检查 Pod 的 spec.nodeName 字段是否匹配 Node 名称。
- NodeUnschedulable: 检查 Node 是否被标记为不可调度。
- TaintToleration: 检查 Pod 是否 tolerates Node 的 taints。
- NodeAffinity: 检查是否满足 Pod 的 node affinity 要求。
- PodAffinity: 检查是否满足 Pod 的 pod affinity 要求。
- VolumeRestrictions: 检查 volume 约束。
- EBSLimits: 检查 Amazon EBS volume 限制。
- NoVolumeZoneConflict: 检查 volume zone 约束。
- CheckNodeMemoryPressure: 检查 Node memory pressure 状态。
- CheckNodeDiskPressure: 检查 Node disk pressure 状态。
Custom Filter Plugin 示例:
// Custom filter plugin example
type MyFilterPlugin struct{}
func (pl *MyFilterPlugin) Name() string {
return "MyFilterPlugin"
}
// Filter method implementation
func (pl *MyFilterPlugin) Filter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeInfo *framework.NodeInfo) *framework.Status {
// Check if the node meets certain conditions
node := nodeInfo.Node()
if node == nil {
return framework.NewStatus(framework.Error, "node not found")
}
// Example: Only allow nodes with a specific label
if value, exists := node.Labels["custom-label"]; !exists || value != "required-value" {
return framework.NewStatus(framework.Unschedulable, "node does not have required label")
}
return nil // Returning nil means the node is suitable
}在 Scheduler 配置中启用 Filter Plugin:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: custom-scheduler
plugins:
filter:
enabled:
- name: MyFilterPlugin
disabled:
- name: NodeResourcesFit # Disable default plugin其他选项的问题:
- A. 对 Node 进行评分: 这是 "Score" extension point 的作用。
- B. 将 Pod 绑定到 Node: 这是 "Bind" extension point 的作用。
- D. 对 scheduling queue 中的 Pod 进行排序: 这是 "Queue Sort" extension point 的作用。
5. 以下哪一项不是实现 Custom Scheduler 时需要考虑的内容?
A. Node 资源使用情况 B. Pod 优先级和抢占 C. Container image 大小 D. Node affinity 和 anti-affinity
显示答案
答案: C. Container image 大小
解析: Container image 大小通常不是实现 Custom Scheduler 时需要考虑的内容。Image 大小影响的是 image 下载和 container 启动时间,而不是调度决策;这些由 kubelet 和 container runtime 负责。
实现 Custom Scheduler 时的关键考虑事项:
Node 资源使用情况:
- CPU、memory、disk、network 等资源使用情况
- 根据当前使用情况和 requests 进行最优放置
- Resource overcommit policy
go// Resource usage based filtering example func filterByResourceUsage(pod *v1.Pod, node *v1.Node) bool { // Check node's allocatable resources allocatable := node.Status.Allocatable // Calculate sum of resource requests for pods running on the node // Check if new pod's resource requests exceed available resources return podFitsResources(pod, allocatable, usedResources) }Pod 优先级和抢占:
- 优先调度更高优先级的 Pod
- 必要时抢占较低优先级的 Pod
- 考虑 PriorityClass 和 preemptionPolicy
yaml# Priority class example apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority value: 1000000 globalDefault: false description: "High priority pods"Node affinity 和 anti-affinity:
- 满足 Pod 的 nodeSelector、nodeAffinity 要求
- 应用 inter-pod affinity 和 anti-affinity 规则
- 考虑 topology spread constraints
yaml# Node affinity example apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/e2e-az-name operator: In values: - e2e-az1 - e2e-az2其他重要考虑事项:
- Taints and tolerations: 匹配 Node taints 和 Pod tolerations
- Topology spread: 将 Pod 分散到不同 topology domains
- Node status: Node 状态(Ready、MemoryPressure、DiskPressure 等)
- Workload characteristics: batch、service、daemonset 等各种 workload 类型的需求
- Network topology: Node 之间的 network latency 和 bandwidth
- Hardware characteristics: GPU、FPGA 等特殊硬件需求
与 container image 大小相关的考虑: 通常,container image 大小不会出于以下原因直接影响调度决策:
- Image availability: image 是否已缓存在 Node 上由 kubelet 处理,而不是 scheduler。
- Download time: Image 下载发生在调度决策之后,并由 kubelet 负责。
- Storage usage: Image 存储通常不包含在 Node allocatable resources 的计算中。
不过,在特殊情况下,可以实现一个考虑 image locality 的 custom scheduler。这可以通过优先选择已缓存该 image 的 Node 来帮助缩短启动时间。
其他选项说明:
- A. Node 资源使用情况: 调度决策中的重要因素,对选择能够满足 Pod resource requests 的 Node 至关重要。
- B. Pod 优先级和抢占: 在资源竞争期间决定哪些 Pod 先调度,以及必要时抢占哪些 Pod 很重要。
- D. Node affinity 和 anti-affinity: 对于处理 Pod 应该与特定 Node 或其他 Pod 一起调度或分开调度的约束很重要。
A. 排除 Pod 无法运行的 Node B. 对通过 filtering 的 Node 进行评分 C. 将 Pod 绑定到 Node D. 对 scheduling queue 中的 Pod 进行排序
显示答案
答案: B. 对通过 filtering 的 Node 进行评分
解析: 在 Kubernetes scheduling framework 中,"Score" extension point(以前称为 "Priority")的作用是为通过 filtering 的 Node 分配分数。Scoring plugins 会为每个 Node 分配分数,并根据这些分数选择最优 Node。
Scoring 流程:
- 每个 scoring plugin 为每个 Node 计算一个分数(通常范围为 0-100)。
- 每个 plugin 的分数根据配置的 weight 进行加权。
- 汇总所有 plugins 的加权分数。
- 选择总分最高的 Node 用于 Pod 放置。
默认 Scoring Plugins: Kubernetes 提供以下默认 scoring plugins:
- NodeResourcesBalancedAllocation: 给 CPU 和 memory 使用均衡的 Node 更高分数。
- NodeResourcesFit: 根据相对于 requested resources 的可用资源多少,给 Node 更高分数。
- NodeAffinity: 基于 node affinity 规则评分。
- InterPodAffinity: 基于 inter-pod affinity/anti-affinity 规则评分。
- PodTopologySpread: 给能让 Pod 在 topology domains 间均匀分布的 Node 更高分数。
- TaintToleration: 给 taints 更少的 Node 更高分数。
- ImageLocality: 给已经有所需 container images 的 Node 更高分数。
Custom Scoring Plugin 示例:
// Custom scoring plugin example
type MyScorePlugin struct{}
func (pl *MyScorePlugin) Name() string {
return "MyScorePlugin"
}
// Score method implementation
func (pl *MyScorePlugin) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) {
// Get node info
nodeInfo, err := pl.handle.SnapshotSharedLister().NodeInfos().Get(nodeName)
if err != nil {
return 0, framework.NewStatus(framework.Error, fmt.Sprintf("getting node %q from Snapshot: %v", nodeName, err))
}
node := nodeInfo.Node()
// Example: Score based on specific label value
if value, exists := node.Labels["custom-score-label"]; exists {
score, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return 0, framework.NewStatus(framework.Error, fmt.Sprintf("invalid score value: %v", err))
}
// Score range should be 0-100
if score < 0 {
score = 0
} else if score > 100 {
score = 100
}
return score, nil
}
return 0, nil
}
// ScoreExtensions interface implementation
func (pl *MyScorePlugin) ScoreExtensions() framework.ScoreExtensions {
return pl
}
// NormalizeScore method implementation
func (pl *MyScorePlugin) NormalizeScore(ctx context.Context, state *framework.CycleState, pod *v1.Pod, scores framework.NodeScoreList) *framework.Status {
// Score normalization logic
var highest int64 = 0
for _, nodeScore := range scores {
if nodeScore.Score > highest {
highest = nodeScore.Score
}
}
if highest == 0 {
return nil
}
// Adjust all scores relative to the highest score
for i := range scores {
scores[i].Score = scores[i].Score * 100 / highest
}
return nil
}在 Scheduler 配置中启用 Scoring Plugin 并设置 Weight:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: custom-scheduler
plugins:
score:
enabled:
- name: MyScorePlugin
weight: 5 # Set weight
- name: NodeResourcesBalancedAllocation
weight: 2 # Change default plugin weight
disabled:
- name: NodeResourcesFit # Disable default pluginScoring 结果示例: 假设 Node A、B、C 通过了 filtering,并且有两个 scoring plugins:
MyScorePlugin (weight: 5)
- Node A: 80 分
- Node B: 60 分
- Node C: 90 分
NodeResourcesBalancedAllocation (weight: 2)
- Node A: 70 分
- Node B: 90 分
- Node C: 50 分
加权总分:
- Node A: (80 x 5) + (70 x 2) = 400 + 140 = 540 分
- Node B: (60 x 5) + (90 x 2) = 300 + 180 = 480 分
- Node C: (90 x 5) + (50 x 2) = 450 + 100 = 550 分
在这种情况下,Node C 得分最高,因此 Pod 被调度到 Node C。
其他选项的问题:
- A. 排除 Pod 无法运行的 Node: 这是 "Filter" extension point 的作用。
- C. 将 Pod 绑定到 Node: 这是 "Bind" extension point 的作用。
- D. 对 scheduling queue 中的 Pod 进行排序: 这是 "Queue Sort" extension point 的作用。
7. 以下哪一项不是在 Kubernetes 中扩展 scheduler 的方法?
A. Scheduling framework plugin B. Scheduler extender C. 部署多个 scheduler D. 修改 node controller
显示答案
答案: D. 修改 node controller
解析: 修改 node controller 不是在 Kubernetes 中扩展 scheduler 的方法。node controller 是一个 control plane 组件,用于监控和管理 Node 状态,与调度决策没有直接关系。
在 Kubernetes 中扩展 Scheduler 的方法:
Scheduling framework plugin:
- 在 Kubernetes 1.15 中引入,允许在调度周期的各个阶段插入 plugins。
- 提供 filter、score、bind 等 extension points。
- 为提高效率,直接与 scheduler codebase 集成。
go// Scheduling framework plugin registration example func NewPlugin(args runtime.Object, handle framework.Handle) (framework.Plugin, error) { // Parse plugin configuration config, ok := args.(*Config) if !ok { return nil, fmt.Errorf("want args to be of type Config, got %T", args) } // Create plugin instance return &Plugin{ handle: handle, config: config, }, nil } // Plugin interface implementation type Plugin struct { handle framework.Handle config *Config } func (pl *Plugin) Name() string { return "MyPlugin" } // Implement required extension point methods func (pl *Plugin) Filter(...) { ... } func (pl *Plugin) Score(...) { ... }Scheduler extender:
- 通过外部 HTTP service 扩展 scheduler 功能。
- 可以扩展 filtering、prioritization、binding 阶段。
- 因为它与 scheduler 分开运行,可能产生性能开销。
yaml# Scheduler extender configuration example apiVersion: kubescheduler.config.k8s.io/v1 kind: KubeSchedulerConfiguration profiles: - schedulerName: default-scheduler extenders: - urlPrefix: "http://extender-service:8080" filterVerb: "filter" prioritizeVerb: "prioritize" weight: 5 bindVerb: "bind" enableHTTPS: false部署多个 scheduler:
- 将 custom schedulers 与默认 scheduler 一起部署。
- 每个 scheduler 独立运行,Pod 可以通过
spec.schedulerName指定特定 scheduler。 - 提供完全灵活性,但实现和维护可能较复杂。
yaml# Custom scheduler deployment example apiVersion: apps/v1 kind: Deployment metadata: name: my-custom-scheduler namespace: kube-system spec: replicas: 1 selector: matchLabels: component: my-custom-scheduler template: metadata: labels: component: my-custom-scheduler spec: serviceAccountName: my-custom-scheduler containers: - name: scheduler image: my-custom-scheduler:v1.0 args: - --scheduler-name=my-custom-scheduler - --leader-elect=false
Node Controller 的作用: node controller 是一个 control plane 组件,执行以下职责:
- Node 注册和状态监控
- Node 状态更新(Ready、NotReady 等)
- 根据 Node 状态移除 Pod(当 Node 长时间处于 NotReady 时)
- Node lifecycle management
node controller 不直接参与调度决策;它会更新 scheduler 使用的 Node 信息。因此,修改 node controller 不是扩展 scheduler 的方法。
选择 Scheduler 扩展方法时的注意事项:
- Complexity: Scheduling framework plugins 实现起来可能复杂,但与 scheduler 紧密集成。
- Performance: Scheduler extenders 可能有 HTTP 调用开销,会影响性能。
- Maintenance: 多个 schedulers 需要维护独立的 codebases。
- Upgrades: Kubernetes 升级时可能出现兼容性问题。
- Features: 每种方法提供不同级别的功能和灵活性。
其他选项说明:
- A. Scheduling framework plugin: 有效的 scheduler 扩展方法。
- B. Scheduler extender: 有效的 scheduler 扩展方法。
- C. 部署多个 scheduler: 有效的 scheduler 扩展方法。
A. 授予 scheduler 领导权限 B. 在多个 scheduler instances 中只激活一个 instance C. 仅在集群的 leader Node 上运行 scheduler D. 赋予 scheduler 比其他组件更高的优先级
显示答案
答案: B. 在多个 scheduler instances 中只激活一个 instance
解析: Kubernetes scheduler 中 --leader-elect flag 的用途是,在 high availability (HA) 配置中确保只有一个 scheduler instance 处于活跃状态并执行工作。这可以防止多个 scheduler instances 同时工作时可能发生的冲突和 race conditions。
Leader Election 机制:
- 部署多个 scheduler instances 时,leader election 算法只选举一个 instance 作为 leader。
- 只有被选为 leader 的 instance 执行实际调度工作。
- 其他 instances 保持 standby mode,如果当前 leader 失败,会选举新的 leader。
- 该机制使用 Kubernetes resource locks 实现。
Leader Election 相关 Flags:
--leader-elect=true # Whether to enable leader election (default: true)
--leader-elect-lease-duration=15s # Leadership lease duration
--leader-elect-renew-deadline=10s # Leadership renewal deadline
--leader-elect-retry-period=2s # Leadership retry period
--leader-elect-resource-lock=leases # Resource type to use for leadership lock
--leader-elect-resource-name=kube-scheduler # Leadership lock resource name
--leader-elect-resource-namespace=kube-system # Leadership lock resource namespaceHigh Availability Scheduler 部署示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: kube-scheduler
namespace: kube-system
spec:
replicas: 3 # Deploy multiple instances
selector:
matchLabels:
component: kube-scheduler
template:
metadata:
labels:
component: kube-scheduler
spec:
containers:
- name: kube-scheduler
image: k8s.gcr.io/kube-scheduler:v1.23.0
command:
- kube-scheduler
- --leader-elect=true # Enable leader election
- --leader-elect-lease-duration=15s
- --leader-elect-renew-deadline=10s
- --leader-elect-retry-period=2s检查 Leader Election 状态:
# Check leadership resource
kubectl get leases -n kube-system | grep kube-scheduler
# Check leadership details
kubectl describe lease kube-scheduler -n kube-system
# Check leadership related messages in scheduler logs
kubectl logs -n kube-system -l component=kube-scheduler | grep -i leaderCustom Scheduler 中的 Leader Election: 实现 custom scheduler 时,可以使用相同的 leader election 机制。这会使用 client-go library 中的 leaderelection package。
// Leader election implementation example in custom scheduler
import (
"context"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/leaderelection"
"k8s.io/client-go/tools/leaderelection/resourcelock"
)
func runWithLeaderElection(ctx context.Context, client clientset.Interface, schedulerName string) {
// Leader election configuration
lock := &resourcelock.LeaseLock{
LeaseMeta: metav1.ObjectMeta{
Name: schedulerName,
Namespace: "kube-system",
},
Client: client.CoordinationV1(),
LockConfig: resourcelock.ResourceLockConfig{
Identity: schedulerName + "-" + uuid.New().String(),
},
}
// Execute leader election
leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{
Lock: lock,
ReleaseOnCancel: true,
LeaseDuration: 15 * time.Second,
RenewDeadline: 10 * time.Second,
RetryPeriod: 2 * time.Second,
Callbacks: leaderelection.LeaderCallbacks{
OnStartedLeading: func(ctx context.Context) {
// Execute scheduler logic when becoming leader
runScheduler(ctx)
},
OnStoppedLeading: func() {
// Handle when leadership is lost
log.Printf("Lost leadership, shutting down")
os.Exit(0)
},
OnNewLeader: func(identity string) {
// Handle when a new leader is elected
log.Printf("New leader elected: %s", identity)
},
},
})
}应禁用 Leader Election 的情况:
- Single instance deployment: 当 scheduler 只部署为一个 instance 时
- Using a different leader election mechanism: 当外部 orchestration tool 管理 instance 激活时
- Different scheduler names: 当每个 scheduler instance 使用不同的
schedulerName时
在这些情况下,可以通过设置 --leader-elect=false 来禁用 leader election。
其他选项的问题:
- A. 授予 scheduler 领导权限: 这是模糊描述,没有解释 leader election 的具体用途。
- C. 仅在集群的 leader Node 上运行 scheduler: Kubernetes 中没有 "leader node" 的概念;scheduler 运行在 control plane nodes 上。
- D. 赋予 scheduler 比其他组件更高的优先级: Leader election 与优先级无关;它用于多个 scheduler instances 之间的协调。
9. Kubernetes 中用于设置 Pod 调度优先级的资源是什么?
A. PodSchedulingPolicy B. PriorityClass C. SchedulingPriority D. PodPriority
显示答案
答案: B. PriorityClass
解析: Kubernetes 中用于设置 Pod 调度优先级的资源是 PriorityClass。PriorityClass 定义 Pod 的相对重要性,使 scheduler 在做出调度和抢占决策时可以考虑优先级。
PriorityClass 资源:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000 # Priority value (higher value means higher priority)
globalDefault: false # Whether to use this class as the default
description: "High priority pods" # Description
preemptionPolicy: PreemptLowerPriority # Preemption policy (default: PreemptLowerPriority)关键字段:
- value: 优先级值;值越大表示优先级越高。System Pods 通常使用 1000000000(10 亿)或更高的值。
- globalDefault: 设置为 true 时,此 priority class 会应用到未指定 priority class 的 Pod。
- description: priority class 的描述。
- preemptionPolicy: 抢占策略,可设置为
PreemptLowerPriority(默认)或Never。
将 PriorityClass 应用于 Pod:
apiVersion: v1
kind: Pod
metadata:
name: high-priority-pod
spec:
priorityClassName: high-priority # Reference PriorityClass name
containers:
- name: nginx
image: nginxPriority 和 Preemption 行为:
- Scheduling priority: 更高优先级的 Pod 会在 scheduling queue 中先处理。
- Preemption: 当没有 Node 可以调度高优先级 Pod 时,scheduler 可以移除(抢占)较低优先级的 Pod 以释放空间。
- Preemption policy: 使用带有
preemptionPolicy: Never的 PriorityClass 的 Pod 不会抢占其他 Pod。
System PriorityClasses: Kubernetes 提供以下 system PriorityClasses:
- system-cluster-critical: 用于对集群运行至关重要的 Pod(value: 2000000000)
- system-node-critical: 用于对 Node 运行至关重要的 Pod(value: 2000001000)
# Check system PriorityClasses
kubectl get priorityclasses | grep systemPriorityClass 使用示例:
# Define multiple priority classes
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "High priority pods"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: medium-priority
value: 100000
globalDefault: true
description: "Medium priority pods"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low-priority
value: 10000
globalDefault: false
description: "Low priority pods"
preemptionPolicy: Never # Do not preempt监控 Priority 和 Preemption 相关指标:
# Check preemption events
kubectl get events | grep -i preempt
# Check pod priorities
kubectl get pods -o custom-columns=NAME:.metadata.name,PRIORITY:.spec.priority在 Custom Scheduler 中处理 Priority: 实现 custom scheduler 时,在做出调度决策时应考虑 Pod 优先级。
// Pod priority check example
func getPodPriority(pod *v1.Pod) int32 {
if pod.Spec.Priority != nil {
return *pod.Spec.Priority
}
return 0
}
// Priority-based pod sorting example
func sortPodsByPriority(pods []*v1.Pod) {
sort.Slice(pods, func(i, j int) bool {
return getPodPriority(pods[i]) > getPodPriority(pods[j])
})
}其他选项的问题:
- A. PodSchedulingPolicy: Kubernetes API 中不存在的资源。
- C. SchedulingPriority: Kubernetes API 中不存在的资源。
- D. PodPriority: 这不是资源类型,而是 Pod spec 中的字段(
spec.priority)。此字段会由 PriorityClass 自动设置。
10. Kubernetes scheduler 的 NodeResourcesFit plugin 的作用是什么?
A. 根据 Node 的物理位置放置 Pod B. 比较 Node resource capacity 和 Pod resource requests C. 检查 Node operating system 与 Pod 的兼容性 D. 测量 Node network bandwidth
显示答案
答案: B. 比较 Node resource capacity 和 Pod resource requests
解析: Kubernetes scheduler 的 NodeResourcesFit plugin 的作用是比较 Node resource capacity 和 Pod resource requests,以检查 Pod 是否可以在该 Node 上运行。此 plugin 会考虑 CPU、memory、ephemeral storage 和 extended resources(GPU 等)在内的各种 resource types。
NodeResourcesFit Plugin 的主要功能:
- Resource request verification: 检查 Pod 的 resource requests 是否不超过 Node 的 allocatable resources。
- Resource limit verification: 检查 Pod 的 resource limits 是否不超过 Node 的 capacity。
- Extended resource verification: 检查 GPU、FPGA 等 extended resource requests 在 Node 上是否可用。
- Scoring: 基于资源使用情况,为通过 filtering 阶段的 Node 分配分数。
资源验证流程:
- 汇总 Pod 中所有 containers 的 resource requests。
- 检查 Node 的 allocatable resources。
- 检查 Pod 的 resource requests 是否不超过 Node 的 allocatable resources。
- 如果超过,该 Node 会被过滤掉。
Scheduler 中的 NodeResourcesFit 配置:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
plugins:
filter:
enabled:
- name: NodeResourcesFit
score:
enabled:
- name: NodeResourcesFit
weight: 1
pluginConfig:
- name: NodeResourcesFit
args:
scoringStrategy:
type: MostAllocated # or LeastAllocated, RequestedToCapacityRatio
resources:
- name: cpu
weight: 1
- name: memory
weight: 1Scoring Strategies: NodeResourcesFit plugin 支持以下 scoring strategies:
LeastAllocated: 给已使用资源较少的 Node 更高分数。这适用于分散资源使用。
score = (capacity - requested) / capacityMostAllocated: 给已使用资源较多的 Node 更高分数。这适用于集中资源使用,以最小化 Node 数量。
score = requested / capacityRequestedToCapacityRatio: 使用自定义函数根据 requested resources 与 capacity 的比率分配分数。
Resource Types: NodeResourcesFit plugin 会考虑以下 resource types:
- CPU: 以 cores 或 millicores 度量。
- Memory: 以 bytes 度量。
- Ephemeral storage: Node 的本地 ephemeral storage。
- Extended resources: GPU、FPGA 等 custom resources。
检查 Node Resources:
# Check node's allocatable resources
kubectl describe node <node-name> | grep Allocatable -A 5
# Check node's resource usage
kubectl top node <node-name>检查 Pod Resource Requests:
# Check pod's resource requests
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[*].resources.requests}'在 Custom Scheduler 中实现 Resource Fit Check:
// Node resource fit check example
func checkNodeResourcesFit(pod *v1.Pod, node *v1.Node) bool {
// Get node's allocatable resources
allocatable := node.Status.Allocatable
// Calculate pod's resource requests
var requestedCPU, requestedMemory resource.Quantity
for _, container := range pod.Spec.Containers {
if request, ok := container.Resources.Requests[v1.ResourceCPU]; ok {
requestedCPU.Add(request)
}
if request, ok := container.Resources.Requests[v1.ResourceMemory]; ok {
requestedMemory.Add(request)
}
}
// Calculate resources already in use on the node
// (In actual implementation, sum resource requests of all pods running on the node)
// Check resource fit
if allocatableCPU, ok := allocatable[v1.ResourceCPU]; ok {
if requestedCPU.Cmp(allocatableCPU) > 0 {
return false // CPU request exceeds allocatable amount
}
}
if allocatableMemory, ok := allocatable[v1.ResourceMemory]; ok {
if requestedMemory.Cmp(allocatableMemory) > 0 {
return false // Memory request exceeds allocatable amount
}
}
return true // All resource requests are satisfied
}其他选项的问题:
- A. 根据 Node 的物理位置放置 Pod: 这是 topology 相关 plugins(例如 NodeAffinity、PodTopologySpread)的作用。
- C. 检查 Node operating system 与 Pod 的兼容性: 这是通过 NodeSelector 或 NodeAffinity 处理的,而不是单独的 plugin。
- D. 测量 Node network bandwidth: Kubernetes scheduler 默认不考虑 network bandwidth。需要 custom metrics 和 plugins 来实现这一点。