Skip to the content.

《A Deep Dive into Kubernetes Scheduling》笔记

原文链接:https://granulate.io/blog/a-deep-dive-into-kubernetes-scheduling/

Kubernetes Scheduler 是 Kubernetes 控制面的核心组件之一。 其默认行为是将 pod 分配给节点,同时平衡节点之间的资源利用率。

当 pod 被分配到一个新节点时,运行在该节点上的 kubelet 从 Kubernetes API 中检索 pod 规格,然后,kubelet 根据规范创建资源和容器。

概览

Kubernetes 调度只是将 pod 分配给集群中匹配节点的过程。 调度程序监视新创建的 pod 并为它们的分配找到最佳节点。

nodeName 示例:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeName: node-0

nodeSelector 示例,调度器将过滤标签包含 disktype: ssd的节点:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeSelector:
    disktype: ssd

节点亲和

规则

# hard rules
requiredDuringSchedulingIgnoredDuringExecution
requiredDuringSchedulingRequiredDuringExecution

# soft rules
preferredDuringSchedulingIgnoredDuringExecution
preferredDuringSchedulingRequiredDuringExecution

以下示例,pod 有一个节点亲和性规则,表明 Kubernetes Scheduler 应该只将 pod 放置到 us-east 区域中的节点。 第二条规则表明应该首选 us-east-1 或 us-east-2 区域。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/region
            operator: In
            values:
            - us-east

      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - us-east-1
            - us-east-2
  containers:
  - name: nginx
    image: nginx

污点和容忍度

给节点增加污点:

kubectl taint nodes node1 test-environment=true:NoSchedule

Kubernetes 调度器将不会为上午污点节点分配任何 pod,除非 pod 规格中具有匹配的容忍度。如下:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  tolerations:
  - key: "test-environment"
    operator: "Exists"
    effect: "NoSchedule"

调度瓶颈

“Noisy Neighbors”: RequestsLimits

例如,假设在同一个节点上有两个 pod,A 和 B。 如果 pod B 试图消耗所有 CPU 或内存,那么 pod A 就会有问题。
幸运的是,为容器设置资源请求和限制可以控制邻居。

系统进程资源不足

抢占

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority-nonpreempting
value: 100000
preemptionPolicy: Never
globalDefault: false
description: "This priority class will not preempt other pods."

---

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
priorityClassName: high-priority-nonpreempting

调度框架

工作流和扩展点

调度 Pod 包括两个阶段:调度阶段和绑定阶段。 在调度阶段中,调度器找到一个可行的节点。 然后,在绑定阶段中,将决策应用于集群。

Scheduling workflow

调度器性能调优

当集群中的节点数量非常多时,调度程序的工作量呈指数级增长。 在大型集群中,找到最佳节点可能需要很长时间。

percentageOfNodesToScore 设置了参与评分的节点数量。 默认情况下,Kubernetes 会设置一个线性阈值, 在 100 节点集群 50% 和 5000 节点集群的 10% 之间。 默认值的最小值是 5%。确保您的集群中至少有 5% 的节点被考虑进行调度。