33. Kubernetes深入Pod-Pod调度策略之podAffinity

释放双眼,带上耳机,听听看~!

podAffinity介绍

出于高效通信的需求,我们要把几个Pod对象运行在比较近的位置,例如APP PodDB Pod,我们的APP Pod需要连接DB Pod,这个时候就需要把这两个Pod运行在较近的位置以便于网络通信,一般可以按照区域、机房、地区等来划分。像这种类型就属于Pod的亲和性调度。但是有时候出于安全或者分布式考虑,也有可能将Pod运行在不同区域、不同机房,这个时候Pod的关系就是为反亲和性。

podAffinity也被分为硬亲和性和软亲和性,其原理与Node中的硬亲和性及软亲和性一致。
硬亲和性(required):硬亲和性实现的是强制性规则,它是Pod调度时必须要满足的规则,而在不存在满足规则的Node时,Pod对象会被置为Pending状态。
软亲和性(preferred):软亲和性规则实现的是一种柔性调度限制,它倾向于将Pod对象运行于某类特定节点之上,而调度器也将尽量满足此需求,但在无法满足需求时它将退而求其次地选择一个不匹配规则的节点之上。

定义Pod亲和性规则的关键点有两个:

  1. 为节点配置合乎需求的标签。
  2. 为Pod对象定义合理的标签选择器labelSelector,从而能够基于标签选择器选择出符合需求的标签。

帮助文档kubectl explain pods.spec.affinity.podAffinity

Pod反亲和硬亲和性

Pod硬亲和性调度使用requiredDuringSchedulingIgnoredDuringExecution属性进行定义,Pod硬亲和性使用topologyKey参数来指定要运行在具备什么样标签key的Node上,然后再通过labelSelector选择你想关联Pod的标签,可能有点绕,下面看示例应该就明白了。

帮助文档:kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution

Pod硬亲和性参数解析:
labelSelector:标签选择器🏷️。
topologyKey:指定要将当前创建Pod运行在具备什么样的Node标签上,通常指定Node标签的Key。
namespaces:指定labelSelector应用于哪个名称空间,null或空列表表示“此pod的名称空间”。
matchExpressions:按照Pod label列出节点选择器列表。(与matchLabels是两种方式,不过结果是一至)。
matchLabels:按照节点字段列出节点选择器列表。(与matchExpressions是两种方式,不过结果是一至)。
key:指定要选择节点label的key。
values:指定要选择节点label的value,值必须为数组 ["value"] ,如果操作符为In或者 Notin,value则不能为空,如果操作符为Exists或者DoesNotExist ,value则必须为空[],如果操作符为GtLt,则value必须有单个元素,该元素将被解释为整数。
operator:操作符,指定key与value的关系。
In:key与value同时存在,一个key多个value的情况下,value之间就成了逻辑或效果。
NotIn:label 的值不在某个列表中。
Exists:只判断是否存在key,不用关心value值是什么。
DoesNotExist:某个 label 不存在。
Gt:label 的值大于某个值。
Lt:label 的值小于某个值

1.为Node打上不同地区的标签
node01标签为beijing
node02标签为shanghai
node03标签为shenzhen

kubectl label node k8s-node01 zone=beijing
kubectl label node k8s-node02 zone=shanghai
kubectl label node k8s-node03 zone=shenzhen

2.创建资源配置清单
下面清单中,Pod首先会选择标签key为zone的Node,我们上面做了三个Node标签key都为zone,匹配之后,开始在标签key为zone的Node上寻找标签key为app,values为proxy或者web的Pod,然后与其运行在那台Node之上。

cat podaffinity-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: podaffinity-required-pod
spec:
  containers:
  - name: nginx-containers
    image: nginx:latest
  affinity:
    podAffinity:
    #硬亲和性
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          #选择标签key为app,values为proxy或者web的Pod,然后与其运行在同一个Node上
          - { key: app, operator: In, values: ["proxy","web"] }
          #选择key为zone的Node
        topologyKey: zone

3.查看调度结果
如下可以看到,三台Node上没有标签key为app,values为proxy或者web的Pod,我们采用的是硬亲和性,所以该Pod一直为Pending状态。

kubectl apply -f podaffinity-pod.yaml
kubectl get pods -o wide | grep podaffinity
podaffinity-required-pod                         0/1     Pending   0          3m43s   <none>         <none>       <none>           <none>

4.创建标签key为app,值为proxy或者web的Pod

cat app_proxy.yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-proxy-pod
  labels:
    app: proxy
spec:
  containers:
  - name: app-proxy
    image: busybox:latest
    command: [ "/bin/sh", "-c", "tail -f /etc/passwd" ]

5.查看调度结果

kubectl apply -f app_proxy.yaml

#具备标签key为app,values的Pod被调度到了node03上
kubectl get pods -owide | grep app-proxy
app-proxy-pod                                    1/1     Running   0          42s     10.244.5.102   k8s-node03   <none>           <none>

#如下podAffinity硬亲和性调度也被调度到此Node
kubectl get pods -owide | grep podaff
podaffinity-required-pod                         1/1     Running   0          2m30s   10.244.5.103   k8s-node03   <none>           <none>

Pod软亲和性

Pod软亲和性使用preferredDuringSchedulingIgnoredDuringExecution属性进行定义,Pod软亲和性使用podAffinityTerm属性来挑选Pod标签,当调度的Pod对象不再是”必须”,而是“应该”放置于某些特性节点之上,当条件不满足时,它也能够接受编排于其它不符合条件的节点之上,另外,它还为每种倾向性提供了weight属性以便用户定义其优先级,取值范围是1-100,数字越大优先级越高。

帮助文档:kubectl explain pods.spec.affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution

Pod软亲和性参数解析:
podAffinityTerm:Pod亲和性选择器。
weight:在1-100范围内,与匹配相应的节点选项相关联的权重。
labelSelector:标签选择器。
matchExpressions:按照Pod label列出节点选择器列表。(与matchLabels是两种方式,不过结果是一至)。
matchLabels:按照节点字段列出节点选择器列表。(与matchExpressions是两种方式,不过结果是一至)。
key:指定要选择节点label的key。
values:指定要选择节点label的value,值必须为数组 ["value"] ,如果操作符为In或者 Notin,value则不能为空,如果操作符为Exists或者DoesNotExist ,value则必须为空[],如果操作符为GtLt,则value必须有单个元素,该元素将被解释为整数。
operator:操作符,指定key与value的关系。
In:key与value同时存在,一个key多个value的情况下,value之间就成了逻辑或效果。
NotIn:label 的值不在某个列表中。
Exists:只判断是否存在key,不用关心value值是什么。
DoesNotExist:某个 label 不存在。
Gt:label 的值大于某个值。
Lt:label 的值小于某个值

1.创建资源配置清单
下面创建一个Pod软亲和性资源配置清单,定义了两组亲和性判断机制,一个是选择cache Pod所在节点的zone标签,并赋予权重为80,另一个是选择db Pod所在的zone标签,权重为20,调度器首先会将Pod调度到具有zone标签key的Node上,然后将多数Pod调度到具备标签为app=cache的Pod同节点,其次调度到具备标签app=db的Pod同节点。如果Node上的Pod都具备app=cache和app=db,那么根据Pod软亲和性策略,调度器将退而求其次的将Pod调度到其它Node,如果甚至连Node都具备标签zone键,那么根据软亲和策略,调度器还是会退而求其次的将Pod调度到不存在zone键的Node上。

cat podaffinity-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: podaffinity-perferred-pod
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      name: myapp
      labels:
        app: myapp
    spec:
      affinity:
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 80
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - { key: app, operator: In, values: ["cache"] }
              topologyKey: zone
          - weight: 20
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - { key: app, operator: In, values: ["db"] }
              topologyKey: zone
      containers:
      - name: myapp
        image: busybox:latest
        command: ["/bin/sh", "-c", "tail -f /etc/passwd" ]

2.查看调度结果

#Pod调度结果为node01两个,node03一个
kubectl get pods -o wide | grep podaffinity-perferred-pod
podaffinity-perferred-pod-7cddc8c964-5tfr2       1/1     Running   0          12m    10.244.5.106   k8s-node03   <none>           <none>
podaffinity-perferred-pod-7cddc8c964-kqsmk       1/1     Running   0          12m    10.244.3.109   k8s-node01   <none>           <none>
podaffinity-perferred-pod-7cddc8c964-wpqqw       1/1     Running   0          12m    10.244.3.110   k8s-node01   <none>           <none>

#以下三个Node都具备标签键为zone,但是这三个Node上没有Pod标签为app=cache及app=db,所以上面的调度策略在选择Pod标签的时候进行退步才得以将Pod调度到Node01和Node03
k8sops@k8s-master01:~/manifests/pod$ kubectl get nodes -l zone -L zone
NAME         STATUS   ROLES    AGE   VERSION   ZONE
k8s-node01   Ready    <none>   28d   v1.18.2   beijing
k8s-node02   Ready    <none>   28d   v1.18.2   shanghai
k8s-node03   Ready    <none>   29d   v1.18.2   shenzhen
Ops工具

32. Kubernetes深入Pod-Pod调度策略之nodeAffinity

2020-6-16 11:45:12

Ops工具

34. Kubernetes深入Pod-Pod调度策略之podAntiffinity

2020-6-16 11:45:45

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索