k8s-调度亲和性
简介
Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 pod 分配到集群的节点上。听起来非常简单,但有
 很多要考虑的问题:
- 公平:如何保证每个节点都能被分配资源
- 资源高效利用:集群所有资源最大化被使用
- 效率:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作
- 灵活:允许用户根据自己的需求控制调度的逻辑
Sheduler 是作为单独的程序运行的,启动之后会一直坚挺 API Server,获PodSpec.NodeName 为空的 pod,对每个 pod 都会创建一个 binding,表明该 pod 应该放到哪个节点上
调度过程
调度分为几个部分:首先是过滤掉不满足条件的节点,这个过程称为 predicate ;然后对通过节点按照优先级排序,这个是priority ;最后从中选择优先级最高的节点。如果中间任何一步骤有错误,就直接返回错误
Predicate 有一系列的算法可以使用:
PodFitsResources :节点上剩余的资源是否大于 pod 请求的资源
PodFitsHost :如果 pod 指定了 NodeName,检查节点名称是否和 NodeName 匹配
PodFitsHostPorts :节点上已经使用的 port 是否和 pod 申请的 port 冲突
PodSelectorMatches :过滤掉和 pod 指定的 label 不匹配的节点
NoDiskConflict :已经 mount 的 volume 和 pod 指定的 volume 不冲突,除非它们都是只读
如果在 predicate 过程中没有合适的节点,pod 会一直在 pending 状态,不断重试调度,直到节点满足条件。经过这个步骤,如果有多个节点满足条件,就继续 priorities 过程: 按照优先级小对节点排序
优先级由一系列键值对组成,键是该优先级项的名称,值是它的权重(该项的重要性)。这些优先级选项包括:
- LeastRequestedPriority:通过计算 CPU 和 Memory 的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标倾向于资源使用比例更低的节点
- BalancedResourceAllocation:节点上 CPU 和 Memory 使用率越接近,权重越高。这个应该和上面的一起使用,不应该单独使用
- ImageLocalityPriority:倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高通过算法对所有的优先级项目和权重进行计算,得出最终的结果
自定义调度器
除了 kubernetes 自带的调度器,你也可以编写自己的调度器。通过 spec:schedulername 参指定调度器的名字,可以为 pod 选择某个调度器进行调度。比如下面的 pod 选择 my-scheduler 进行调度,而不是默认的default-scheduler :
apiVersion: v1
kind: Pod
metadata:
  name: annotation-second-scheduler
  labels:
    name: multischeduler-example
spec:
  schedulername: my-scheduler
  containers:
  - name: pod-with-second-annotation-container
    image: gcr.io/google_containers/pause:2.0
节点亲和性
pod.spec.nodeAffinity
- preferredDuringSchedulingIgnoredDuringExecution:软策略
- requiredDuringSchedulingIgnoredDuringExecution:硬策略
requiredDuringSchedulingIgnoredDuringExecution(硬亲和)
 例子:节点强制不在node2上调度
[root@master scheduler]# cat node-affinity.yml
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: nginx
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:#硬亲和策略
        nodeSelectorTerms:#
        - matchExpressions:
          - key: kubernetes.io/hostname#节点键值hostname选择策略
            operator: NotIn  #策略选择不在,与下面的值共同存在;是不在node2的意思
            values:
            - node2
结果调度到node1上(多次删除pod,重新调度仍会调度到node1):
[root@master ~]# kubectl get pod -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
affinity   1/1     Running   0          14s   10.244.166.133   node1   <none>           <none>
如果修改策略operator: In values: - node3
 硬亲和情况下,让pod调度到node3(节点不存在),会一直处于pendding状态。
[root@master ~]# kubectl get pod
NAME       READY   STATUS    RESTARTS   AGE
affinity   0/1     Pending   0          7s
preferredDuringSchedulingIgnoredDuringExecution(软亲和)
 例子:让pod尽量调度到node2节点(多次删除多次重建,仍然调度到node2)
[root@master scheduler]# cat node-prefer-affinity.yml
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: nginx
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
       - weight: 1
         preference:
          matchExpressions: 
          - key: kubernetes.io/hostname
            operator: In
            values:
            - node2
合体
[root@master scheduler]# cat affinin.yml 
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
 - name: with-node-affinity
    image: nginx
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: NotIn
            values:
            - node02
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: source
            operator: In
            values:
            - qikqiak
键值运算关系:
- In:label 的值在某个列表中
- NotIn:label 的值不在某个列表中
- Gt:label 的值大于某个值
- Lt:label的值小于某个值
- Exists:某个 label 存在
- DoesNotExist:某个 label 不存在
Pod亲和性
pod.spec.affinity.podAffinity/podAntiAffinity
 preferredDuringSchedulingIgnoredDuringExecution:软策略
  requiredDuringSchedulingIgnoredDuringExecution:硬策略
演示:先启动两个简单的pod1,pod2
vim pod1.yml
apiVersion: v1
kind: Pod
metadata:
  name: pod-1
  labels:
    app: pod-1
spec:
  containers:
  - name: pod-1
    image: nginx
vim pod2.yml
apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  labels:
    app: pod-2
spec:
  containers:
  - name: pod-2
    image: nginx
kubectl apply -f pod1.yml
kubectl apply -f pod2.yml
#查看
[root@master pod-affinity]# kubectl get pod -o wide
NAME    READY   STATUS              RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-1   1/1     Running             0          42s   10.244.1.47   node1   <none>           <none>
pod-2   1/1     Running             0          38s   10.244.2.46   node2   <none>           <none>
启动具有亲和性的的pod-3(亲pod-1,远离pod-2)
[root@master pod-affinity]# cat pod-affinity.yml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-3
  labels:
    app: pod-3
spec:
  containers:
  - name: pod-3
    image: nginx
  affinity:
    podAffinity:#必须先满足硬策略
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In#在pod-1
            values:
            - pod-1
        topologyKey: kubernetes.io/hostname
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - pod-2
          topologyKey: kubernetes.io/hostname
 kubectl apply -f pod-affinity.yml
结果:pod-3调用到和pod-1相同的节点node1上,不在pod-2调度的节点node2
[root@master pod-affinity]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-1   1/1     Running   0          47s   10.244.1.47   node1   <none>           <none>
pod-2   1/1     Running   0          43s   10.244.2.46   node2   <none>           <none>
pod-3   1/1     Running   0          16s   10.244.1.48   node1   <none>           <none>
亲和性/反亲和性调度策略比较如下:




















