浅谈kubernetes调度

引言

在kunernetes当中,调度是一个核心功能,他负责将容器(封装在pods中)分配到集群中的节点上运行。本文将深入探讨kubernetes的调度机制,包括其工作原理、关键组件、调度策略以及高级调度特性。

什么是调度器

Kubernetes调度器是一个独立的控制平面组件,它负责监视新创建的Pod,这些Pod尚未被分配到节点上,或者Pod当前运行的节点不再满足其要求。调度器通过一系列算法和策略,为这些未调度的Pod找到一个最合适的节点来运行。

调度过程

kube-scheduler 选择一个最佳节点来运行新创建的或尚未调度(unscheduled)的 Pod。 由于 Pod 中的容器和 Pod 本身可能有不同的要求,调度程序会过滤掉任何不满足 Pod 特定调度需求的节点。 或者,API 允许你在创建 Pod 时为它指定一个节点

kube-scheduler工作流程大致分为以下几个步骤:
监听 API Server:调度器通过 Kubernetes 的监听(Watch)机制来发现集群中新创建且尚未被调度到节点上的 Pod。

过滤(Filtering):调度器首先会根据一系列的过滤算法(Predicates)来筛选出满足 Pod 调度需求的节点。这些过滤算法包括资源匹配、节点选择器、亲和性与反亲和性规则、污点与容忍度检查等。

打分(Scoring):过滤之后,调度器会进入打分阶段,对所有通过过滤的节点进行打分。这个阶段会使用一系列的打分算法(Priorities),根据节点的资源利用率、负载均衡、亲和性规则等因素为节点打分。

选择节点:调度器会根据打分结果选择得分最高的节点来运行 Pod。如果有多个节点得分相同,调度器会随机选择一个。

绑定(Binding):选定节点后,调度器将这个调度决定通知给 API Server,这个过程称为绑定。绑定后,相应的节点上的 Kubelet 会启动 Pod。

当我们了解了kube-scheduler的工作流程后,这时候可能就有人问什么是过滤?什么是打分?这就要讲到我们的调度策略了

调度策略

调度器的调度策略主要分为两大类:过滤(Predicates)和打分(Priorities)。

1.过滤(Predicates):这一阶段的任务是筛选出满足 Pod 调度条件的节点。过滤策略包括但不限于:
PodFitsResources:检查节点是否有足够的资源(如 CPU 和内存)来满足 Pod 的需求。
PodFitsHost:如果 Pod 指定了特定的 NodeName,检查是否匹配。
PodFitsHostPorts:确保 Pod 所需的 HostPort 没有被节点上的其他 Pod 使用。
PodSelectorMatches:检查 Pod 的标签选择器是否与节点的标签匹配。
NoDiskConflict:确保 Pod 请求的卷不会与节点上已挂载的卷冲突。
TaintToleration:检查 Pod 是否能容忍节点的污点(Taints)。

2.打分(Priorities):在过滤阶段之后,打分阶段会对所有符合条件的节点进行打分,以确定哪个节点最适合运行 Pod。打分策略包括:
LeastRequestedPriority:倾向于选择资源使用率最低的节点。
MostRequestedPriority:倾向于选择资源使用率最高的节点。
NodePreferAvoidPodsPriority:根据节点上的注解来调整节点的优先级,避免将 Pod 调度到某些节点。
NodeAffinityPriority:基于 Pod 的节点亲和性设置来打分。
TaintTolerationPriority:根据 Pod 对节点污点的容忍度来打分。

除了这些默认的调度策略,Kubernetes 还支持通过亲和性(Affinity)和反亲和性(Anti-affinity)规则来进一步控制 Pod 的调度行为。例:
NodeSelector:用户可以在Pod的定义中指定NodeSelector,要求Pod只能被调度到具有特定标签的节点上。这是一种简单且直接的调度方式,适用于基于节点标签进行调度的场景。

NodeAffinityNodeAffinity提供了比NodeSelector更灵活的调度规则,包括硬亲和性和软亲和性。硬亲和性规则是强制性的,如果找不到满足条件的节点,Pod将保持未调度状态。软亲和性规则是优先级的,调度器会尽量满足这些规则,但如果找不到完全满足条件的节点,也会选择其他节点来运行Pod。

PodAffinity和PodAntiAffinity:这些调度策略允许用户根据Pod的标签来选择或避免与特定Pod调度到同一个节点上。PodAffinity用于将具有相同或相似属性的Pod调度到同一个节点上,以优化缓存、数据局部性等。PodAntiAffinity则用于将具有不同属性的Pod分散到不同的节点上,以提高应用的可用性和容错性。

污点和容忍度(Taints and Tolerations):污点(Taints)允许节点拒绝某些Pod的调度,除非这些Pod声明了能够容忍节点的污点。容忍度(Tolerations)是Pod定义中的一个字段,用于指定Pod能够容忍哪些节点的污点。这种机制提供了一种灵活的方式来控制Pod的调度位置,特别是当某些节点具有特殊属性(如只能运行特定类型的Pod)时。

需要注意的是:在大型集群中,过多的亲和性和反亲和性规则可能会对调度器的性能产生负面影响,尤其是在节点数量众多的情况下。

使用示例

1.Nodeselector

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: my-image:1.0
        ports:
        - containerPort: 8080 #该容器监听的端口
      nodeSelector:
        disktype: ssd #Pod只会被调度到具有此标签的节点上

总结:以上意味着Deployment中的Pod只会被调度到具有disktype: ssd标签的节点上。如果集群中有节点被标记为disktype: ssd,那么Pod将会被调度到这些节点上。如果没有节点具有这个标签,那么Pod将不会被调度,直到有合适的节点出现。

2.Nodeaffinity(node亲和性)

注:包括两种类型

**1).硬亲和性**:
硬亲和性规则是强制性的。如果找不到满足条件的节点,Pod将保持未调度状态,直到有节点满足条件或NodeAffinity规则被修改。
它确保了Pod只能被调度到符合特定条件的节点上,有助于满足应用的硬件、软件或地理位置等需求。
**2).软亲和性**:
软亲和性规则是优先级的。调度器会尽量满足这些规则,但如果找不到完全满足条件的节点,也会选择其他节点来运行Pod。
它提供了一种灵活的调度方式,允许在满足其他调度条件的前提下,优先将Pod调度到符合特定条件的节点上。
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:   #Pod 必须被调度到具有下面对应标签的节点上
      nodeSelectorTerms:
      - matchExpressions:
        - key: disktype 
          operator: In
          values:
          - ssd   #标签disktype的值
    preferredDuringSchedulingIgnoredDuringExecution:  #Pod 首选被调度到具有下面对应标签的节点上
    - weight: 1   #表示这个规则的优先级
      preference:
        matchExpressions:
        - key: rack
          operator: In
          values:
          - rack1   #标签rack的值

这里定义了两个亲和性规则,我们来简单总结一下:

1.RequiredDuringSchedulingIgnoredDuringExecution(硬亲和性):Pod 必须被调度到具有 disktype: ssd 标签的节点上。
2.PreferredDuringSchedulingIgnoredDuringExecution(软亲和性):Pod 首选被调度到具有 rack: rack1 标签的节点上,weight 值为 1,表示这个规则的优先级。
请注意,weight 值的范围是 1 到 100,它表示这个偏好规则的优先级。调度器会尝试将 Pod 调度到满足首选亲和性规则的节点上,但如果找不到这样的节点,Pod 仍然可以被调度到其他节点。

3.PodAffinity(pod亲和性)与PodAntiAffinity(pod反亲和性)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: my-image:1.0
        ports:
        - containerPort: 8080
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:   #Pod必须被调度到具有下面对应标签的Pod的节点上
          - labelSelector:
              matchLabels:
                app: another-app      #对应标签
            namespaces:
            - default
            topologyKey: "kubernetes.io/hostname"
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:   #Pod首选不被调度到具有以下对应标签的 Pod 的节点上
          - weight: 100       #表示这个规则的优先级
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  app: another-app    #对应标签
              namespaces:
              - default   #表明以上规则也适用于default命名空间中的Pod
              topologyKey: "kubernetes.io/hostname"

在这个示例中,我们来总结一下,可以看到spec.template.spec.affinity 部分包含了 Pod Affinity 的配置:
1).Pod Affinity:
requiredDuringSchedulingIgnoredDuringExecution:Pod 必须被调度到运行有标签为app: another-app的Pod的节点上。这个规则适用于default命名空间中的 Pod,并且使用 kubernetes.io/hostname 作为拓扑键,这意味着 Pod 必须被调度到同一个节点上。
2).Pod Anti-Affinity:
preferredDuringSchedulingIgnoredDuringExecution:Pod 首选不被调度到运行有标签为 app: another-app 的 Pod 的节点上。这个规则也适用于 default 命名空间中的 Pod,并且使用 kubernetes.io/hostname 作为拓扑键。
请注意,topologyKey可以是任何有效的标签键,例如 kubernetes.io/hostname、kubernetes.io/region、kubernetes.io/zone 等,它用于确定 Pod Affinity 规则的拓扑范围。

4.Taints(污点)

Taints(污点)是一种节点属性,用于确保Pod不会被调度到不希望的节点上。污点可以被添加到节点上,以表示该节点具有某些不希望的特性或问题,比如节点正在维护中、节点具有特定的硬件或软件限制等。然后,只有那些能够容忍(Tolerate)这些污点的Pod才会被调度到这些节点上。
举个栗子:

tolerations:
- key: "key"
  operator: "Equal"		#默认值是 Equal
  value: "value"
  effect: "NoSchedule"

Taints由三个部分组成:
key:污点的键,用于唯一标识污点。
value:污点的值,与键一起形成污点的唯一标识。这个值可以是空字符串,但在某些情况下,它可能包含有关污点性质的额外信息。
effect:污点的作用效果,它决定了Pod与污点节点的交互方式。Kubernetes定义了三种effect

NoSchedule新的Pod不会调度到带有此污点的节点上。
PreferNoSchedule这是一个"软"污点,调度器会尽量避免将Pod调度到带有此污点的节点,但不是绝对的
NoExecute新的Pod不会调度到带有此污点的节点上,如果节点上已经存在Pod,它们会被驱逐。

注意事项:

1)当污点的effect为NoExecute时,如果Pod不能容忍此污点,它将立即被驱逐。如果Pod能够
   容忍此污点,并且在容忍中定义了tolerationSeconds,则Pod会在指定的时间后被驱逐。
2)可以在节点上设置多个污点,也可以在Pod上设置多个容忍度。
3)如果Pod没有容忍与节点上的污点相匹配,那么Pod将不会被调度到该节点上,
   除非手动指定了spec.nodeName。

努力码字中…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值