k8s series 18: 调度

425 阅读4分钟

这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战

简介

在kubernetes中的调度,是指将Pod放到最佳的节点上,以便Pod在相对最优环境中运行

调度这一行为由调度器操作,通过k8s的Watch机制来发现集群中新创建的 还未被调度到节点上的pod,调度器会将发布的每一个未调度的pod放到一个合适的节点上

kube-scheduler

kubernetes中默认调度器是kube-scheduler,默认集群安装时的组件

kube-scheduler给pod调度时分为2步:

  1. 过滤
  2. 打分

过滤阶段会将所有满足Pod调度需要的节点选出来,例如,PodFitsResources 过滤函数会检查候选 Node 的可用资源能否满足 Pod 的资源请求。 在过滤之后,得出一个 Node 列表,里面包含了所有可调度节点;通常情况下, 这个 Node 列表包含不止一个 Node。如果这个列表是空的,代表这个 Pod 不可调度。

打份阶段会根据当前的打分规则,调度器会给所有可调度节点中每一个节点进行打分,然后将Pod调度到得分最高的节点上,如果多个得分最高,会随机选一下

节点选择器

想要约束Pod在指定的节点上运行,常见的做是给节点打标签,然后在部署时使用nodeSelector选择标签,调度器将自动进行匹配放置

#打标签
kubectl label nodes node1 disktype=ssd
#使用标签选择器,pod将运行在node1节点上
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd

亲和性和反亲和性

亲和性功能包含两种类型的亲和性,即节点亲和性Pod间亲和性/反亲和性

亲和性和反亲和性增强了:

  1. 语言更具表现力(不仅仅是"对完全匹配规则的 AND")
  2. 要求非锁死,针对规则是软需求或偏好,而不是硬要求,可以继续调度
  3. 多种标签选择,支持pod标签来约束,不止node标签一种

节点亲和性

节点亲和性概念和nodeSelector类似,可以根据节点上的标签来约束Pod可以调度到哪些节点

目前有两种类型的节点亲和性:

  • requiredDuringSchedulingIgnoredDuringExecution 硬需求
  • preferredDuringSchedulingIgnoredDuringExecution 软需求

硬需求是Pod调度到一个节点必须满足需求

软需求是调度器尝试执行但不能保证偏好

节点亲和性例子:

#节点亲和性通过 PodSpec 的 `affinity` 字段下的 `nodeAffinity` 字段进行指定
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
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: k8s.gcr.io/pause:2.0
  • Pod只能调度在具有标签键 kubernetes.io/e2e-az-name 且标签值为e2e-az1或 e2e-az2的节点上
  • 满足这些标准的节点中,具有标签键为another-node-label-key且标签值为another-node-label-value的节点应该优先使用
  • 同时指定了nodeSelector和 nodeAffinity,两者必须都要满足, 才能将 Pod 调度到候选节点上

Pod亲和性和反亲和性

Pod亲和性和反亲和性可以基于节点上运行的Pod标答来约束 Pod可以调度到的节点

其中规则是如果x节点上已经运行了一个或多个满足规则Y的Pod,则这个Pod应该(或在反亲和性的情况下不应该) 运行在x节点 (Y 表示一个具有可选的关联命令空间列表的 LabelSelector)

  • Pod 间亲和性通过 PodSpec 中 affinity 字段下的 podAffinity 字段进行指定
  • Pod 间反亲和性通过 PodSpec 中 affinity 字段下的 podAntiAffinity 字段进行指定
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: topology.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: topology.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: k8s.gcr.io/pause:2.0

污点和容忍度

污点是让节点排斥一类特定的pod

容忍度是加在pod上的,允许(但不要求) pod调度到匹配的污点的节点上

污点例子

#增加一个污点
kubectl taint nodes node1 key1=value1:NoSchedule

表示只有拥有和这个污点相匹配的Pod才能够被分配到 node1节点上

#移除一个污点
kubectl taint nodes node1 key1=value1:NoSchedule-

容忍度例子

容忍度是允许,但不强求pod调度到 有污点规则的节点上

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  tolerations:
  - key: "key1"
    operator: "Exists"
    effect: "NoSchedule"
  • key 匹配创建污点时设置的key,没有key表示容忍一切
  • 没有value的话operator是Exists,有value就是Equal
  • operator 默认是Equal,与任意的key,value,effect匹配,能容忍任意污点节
  • effect 规则,NoSchedule:不调到不能容忍污点的节点,PreferNoSchedule:尽量不调度到不能容忍污点的节点上