K8S高级调度——亲和性和反亲和性
参考:

Assigning Pods to Nodes

Inter-pod topological affinity and anti-affinity

what

  • 亲和性:应用A与应用B两个应用频繁交互,所以有必要利用亲和性让两个应用的尽可能的靠近,甚至在一个node上,以减少因网络通信而带来的性能损耗。
  • 反亲和性:当应用的采用多副本部署时,有必要采用反亲和性让各个应用实例打散分布在各个node上,以提高HA。

node

node亲和性可以约束调度器基于node labels调度pod。

考虑以下场景:

有az1,az2两个zone,现在我们只希望pod实例部署在az1

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: with-node-affinity
  5. spec:
  6. affinity:
  7. nodeAffinity:
  8. requiredDuringSchedulingIgnoredDuringExecution:
  9. nodeSelectorTerms:
  10. - matchExpressions:
  11. - key: kubernetes.io/e2e-az-name
  12. operator: In
  13. values:
  14. - az1
  15. preferredDuringSchedulingIgnoredDuringExecution:
  16. - weight: 1
  17. preference:
  18. matchExpressions:
  19. - key: another-node-label-key
  20. operator: In
  21. values:
  22. - another-node-label-value
  23. containers:
  24. - name: with-node-affinity
  25. image: k8s.gcr.io/pause:2.0

两种类型:

  • requiredDuringSchedulingIgnoredDuringExecution: hard,严格执行,满足规则调度,否则不调度,在预选阶段执行,所以违反hard约定一定不会调度到
  • preferredDuringSchedulingIgnoredDuringExecution:soft,尽力执行,优先满足规则调度,在优选阶段执行,
  • 后缀IgnoredDuringExecution表示如果labels发生改变,使得原本运行的pod不在满足规则,那么这个pod将忽视这个改变,继续运行。

  • requiredDuringSchedulingRequiredDuringExecution:未实现,与之前类似,只是后缀不同,代表如果labels发生改变,kubelet将驱逐不满足规则的pod

  • Note: 支持的operator操作: In, NotIn, Exists, DoesNotExist, Gt, Lt. 其中,NotIn and DoesNotExist用于实现反亲和性。

Note: weight范围1-100。这个涉及调度器的优选打分过程,每个node的评分都会加上这个weight,最后bind最高的node。

限制

  • 同时指定nodeSelector and nodeAffinity,pod必须都满足
  • nodeAffinity有多个nodeSelectorTerms ,pod只需满足一个
  • nodeSelectorTerms多个matchExpressions ,pod必须都满足
  • 由于IgnoredDuringExecution,所以改变labels不会影响已经运行pod

总的来说,node亲和性与nodeSelector类似,是它的扩展。

Inter-pod

在K8S中,我们可以根据node上已运行pod的标签来决定将pod调度到哪个node。

例如:pod是否(亲和性:是,反亲和性:否)可以调度在X上;此时在X上,已经运行了一些pods;调度器需要考虑这些pods是否满足规则Y。

  • 规则Y就是LabelSelector,
  • X是一个逻辑拓扑概念,可以是node,rack,az,region等等;用topologyKey表示,具体值用node label表示。
  1. kubernetes.io/hostname
  2. failure-domain.beta.kubernetes.io/zone
  3. failure-domain.beta.kubernetes.io/region
  4. beta.kubernetes.io/instance-type
  5. beta.kubernetes.io/os
  6. beta.kubernetes.io/arch

Note: 此特性有明显的性能损耗,需要大量运算。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: with-pod-affinity
  5. spec:
  6. affinity:
  7. podAffinity:
  8. requiredDuringSchedulingIgnoredDuringExecution:
  9. - labelSelector:
  10. matchExpressions:
  11. - key: security
  12. operator: In
  13. values:
  14. - S1
  15. topologyKey: failure-domain.beta.kubernetes.io/zone

Note: 合法的operator包括:In, NotIn, Exists, DoesNotExist.

  • In:表示目标对象的某个 label 的值等于给定的一组值之一。例如,key=value1 和 key=value2 中的 key 都是相同的,且都属于 {value1, value2},则选中这两个对象。
  • NotIn:表示目标对象的某个 label 的值不等于给定的任何一个值。例如,key=value1 不属于 {value2, value3},则选中该对象。
  • Exists:表示目标对象必须定义了指定的 label,而不论其具体的值是什么。
  • DoesNotExist:表示目标对象不能定义指定的 label。

限制

topologyKey:

  1. 对于亲和性和软反亲和性,不允许空topologyKey;
  2. 对于硬反亲和性,LimitPodHardAntiAffinityTopology控制器用于限制topologyKey只能是kubernetes.io/hostname;
  3. 对于软反亲和性,空topologyKey被解读成kubernetes.io/hostname, failure-domain.beta.kubernetes.io/zone and failure-domain.beta.kubernetes.io/region的组合;

    example

    1. apiVersion: apps/v1
    2. kind: Deployment
    3. metadata:
    4. name: redis-cache
    5. spec:
    6. selector:
    7. matchLabels:
    8. app: store
    9. replicas: 3
    10. template:
    11. metadata:
    12. labels:
    13. app: store
    14. spec:
    15. affinity:
    16. podAntiAffinity:
    17. requiredDuringSchedulingIgnoredDuringExecution:
    18. - labelSelector:
    19. matchExpressions:
    20. - key: app
    21. operator: In
    22. values:
    23. - store
    24. topologyKey: "kubernetes.io/hostname"
    25. containers:
    26. - name: redis-server
    27. image: redis:3.2-alpine
    部署3个redis实例,并且为了提升HA,都不在一个node。
    1. apiVersion: apps/v1
    2. kind: Deployment
    3. metadata:
    4. name: web-server
    5. spec:
    6. selector:
    7. matchLabels:
    8. app: web-store
    9. replicas: 3
    10. template:
    11. metadata:
    12. labels:
    13. app: web-store
    14. spec:
    15. affinity:
    16. podAntiAffinity:
    17. requiredDuringSchedulingIgnoredDuringExecution:
    18. - labelSelector:
    19. matchExpressions:
    20. - key: app
    21. operator: In
    22. values:
    23. - web-store
    24. topologyKey: "kubernetes.io/hostname"
    25. podAffinity:
    26. requiredDuringSchedulingIgnoredDuringExecution:
    27. - labelSelector:
    28. matchExpressions:
    29. - key: app
    30. operator: In
    31. values:
    32. - store
    33. topologyKey: "kubernetes.io/hostname"
    34. containers:
    35. - name: web-app
    36. image: nginx:1.12-alpine
    部署三个web实例,为了提升HA,都不在一个node;并且为了方便与redis交互,尽量与redis在同一个node。

对称性

考虑一个场景,两个应用S1和S2。现在严格要求S1 pod不能与S2 pod运行在一个node,如果仅设置S1的hard反亲和性是不够的,必须同时给S2设置对应的hard反亲和性。即调度S1 pod时,考虑node没有S2 pod,同时需要在调度S2 pod时,考虑node上没有S1 pod。考虑下面两种情况:

先调度S2,后调度S1,可以满足反亲和性,
先调度S1,后调度S2,违反S1的反亲和性规则,因为S2没有反亲和性规则,所以在schedule-time可以与S1调度在一个拓扑下。
这就是对称性,即S1设置了与S2相关的hard反亲和性规则,就必须对称地给S2设置与S1相关的hard反亲和性规则,以达到调度预期。

Note:

  • 反亲和性(soft/hard)具备对称性,上面已经举过例子了
  • hard亲和性不具备对称性,例如期望S1、S2亲和,那么调度S2的时候没有必要node上一定要有S1,但是有一个隐含规则,node上有S1更好
  • soft亲和性具备对称性,不是很理解,遗留

Note:

hard反亲和性对称性问题代码已经解决了:

kubernetes\pkg\scheduler\algorithm\predicates\predicates.go

  1. // InterPodAffinityMatches checks if a pod can be scheduled on the specified node with pod affinity/anti-affinity configuration.
  2. func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) {
  3. c.satisfiesExistingPodsAntiAffinity(pod, meta, nodeInfo)
  4. c.satisfiesPodsAffinityAntiAffinity(pod, meta, nodeInfo, affinity)
  5. }

检查pod是否会打破已经运行pods(从cache中获取)的反亲和性,利用了pods反亲和性的RequiredDuringSchedulingIgnoredDuringExecution
检查pod的亲和性/反亲和性是否满足,都是hard
ps. 所以说hard是在预选过程使用,优选打分过程使用soft

特别注意

  • Don’t co-locate pods of this service with any other pods including pods of this service: {LabelSelector: empty, TopologyKey: “node”},在反亲和性中,空的selector表示不与任何pod亲和。

  • 由于hard规则在预选阶段处理,所以如果只有一个node满足hard亲和性,但是这个node又不满足其他预选判断,比如资源不足,那么就无法调度。所以何时用hard,何时用soft需要根据业务考量。

  • 如果所有node上都没有符合亲和性规则的target pod,那么pod调度可以忽略亲和性

作者:陈先生_9e91
链接:https://www.jianshu.com/p/61725f179223
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

文档更新时间: 2023-03-17 07:30   作者:admin