kubernetes/MD/kubernetes调度粘性.md

9.4 KiB
Raw Blame History

kubernetes调度粘性

著作:行癫 <盗版必究>


一:调度粘性

1.三种调度粘性

NodeSelector(定向调度)

NodeAffinity(Node亲和性)

PodAffinity(Pod亲和性)

通常情况下使用的都是k8s默认的调度调度方式但是在有些情况下我们需要将pod运行在具有特点的标签的node上才能都运行这个时候pod的调度策略就不能使用k8s默认的调度策略了这个时候就需要指定调度策略告诉k8s需要将pod调度到那些node上。

2.nodeSelector

常规情况下会直接使用nodeSelector这种调度策略。labels标签 是k8s里面用来编标记资源的一种常用的方式我们可以给node标记特殊的标签然后nodeSelector会将pod调度到带有指定labels的node上的提供简单的pod部署限制pod选择一个或多个node的label部署

给node添加label

kubectl label nodes <node-name> <label-key>=<label-value>

pod添加nodeSelector机制

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd

部署pod

[root@master ~]# kubectl create -f test.yaml
pod/nginx created

查看结果:

[root@master ~]# kubectl get pod -A -o wide
NAMESPACE   NAME   READY   STATUS    RESTARTS   AGE     IP           NODE   NOMINATED NODE   READINESS GATES
default      nginx        0/1     ContainerCreating   0          37s     <none>     node-1   <none>   

从上面的执行结果可以看出pod 通过默认的 default-scheduler 调度器到了node-1节点上。不过这种调度方式属于强制性的。如果node02上的资源不足那么pod的状态将会一直是pending状态。

3.亲和性和反亲和性调度

k8s的默认调度流程实际上是经过了两个阶段predicates判断,priorities优先选择 。使用默认的调度流程的话k8s会将pod调度到资源充裕的节点上使用nodeselector的调度方法又会将pod调度具有指定标签的节点上。然后在实际生产环境中我们需要将pod调度到具有些label的一组node才能满足实际需求这个时候就需要nodeAffinity、podAffinity以及 podAntiAffinity(pod 反亲和性)

亲和性可以分为具体可以细分为硬和软两种亲和性:

软亲和性:如果调度的时候,没有满足要求,也可以继续调度,即能满足最好,不能也无所谓

硬亲和性是指调度的时候必须满足特定的要求如果不满足那么pod将不会被调度到当前node

requiredDuringSchedulingIgnoredDuringExecution #硬性强制

preferredDuringSchedulingIgnoredDuringExecution #软性配置

4.nodeAffinity 节点亲和性

节点亲和性主要是用来控制 pod 能部署在哪些节点上以及不能部署在哪些节点上的它可以进行一些简单的逻辑组合了不只是简单的相等匹配preferredDuringSchedulingIgnoredDuringExecution

强调优先满足制定规则调度器会尝试调度pod到Node上但并不强求相当于软限制。多个优先级规则还可以设置权重值以定义执行的先后顺序

nodeAffinity控制 pod 的调度:

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: beta.kubernetes.io/arch
            operator: In
            values:
            - amd64
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: disk-type
            operator: In
            values:
            - ssd
  containers:
  - name: with-node-affinity
    image: nginx

设置label

[root@master ~]# kubectl label nodes node-2 disk-type=ssd
node/node-2 labeled

创建pod并查看运行结果

[root@master yaml]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP   NODE     NOMINATED NODE   READINESS GATES
with-node-affinity   0/1     ContainerCreating   0   4m    <none>   node-2   <none>    <none>

NodeAffinity规则设置的注意事项如下

如果同时定义了nodeSelector和nodeAffinityname必须两个条件都得到满足pod才能最终运行在指定的node上

如果nodeAffinity指定了多个nodeSelectorTerms那么其中一个能够匹配成功即可

如果在nodeSelectorTerms中有多个matchExpressions则一个节点必须满足所有matchExpressions才能运行该pod

matchExpressions : 匹配表达式,这个标签可以指定一段例如pod中定义的key为zoneoperator为In(包含那些)values为 foo和bar就是在node节点中包含foo和bar的标签中调度

kubernetes提供的操作符有下面的几种

Inlabel 的值在某个标签中

NotInlabel 的值不在某个标签中

Gtlabel 的值大于某个值

Ltlabel 的值小于某个值

Exists某个 label 存在

DoesNotExist某个 label 不存在

5.podAffinity pod亲和性

Pod的亲和性主要用来解决pod可以和哪些pod部署在同一个集群里面即拓扑域由node组成的集群里面而pod的反亲和性是为了解决pod不能和哪些pod部署在一起的问题二者都是为了解决pod之间部署问题。需要注意的是Pod 间亲和与反亲和需要大量的处理这可能会显著减慢大规模集群中的调度不建议在具有几百个节点的集群中使用而且Pod 反亲和需要对节点进行一致的标记即集群中的每个节点必须具有适当的标签能够匹配topologyKey。如果某些或所有节点缺少指定的topologyKey标签可能会导致意外行为

Pod亲和性场景我们的k8s集群的节点分布在不同的区域或者不同的机房当服务A和服务B要求部署在同一个区域或者同一机房的时候我们就需要亲和性调度了

labelSelector : 选择跟那组Pod亲和

namespaces : 选择哪个命名空间

topologyKey : 指定节点上的哪个键

pod亲和性调度需要各个相关的pod对象运行于"同一位置" 而反亲和性调度则要求他们不能运行于"同一位置"

这里指定“同一位置” 是通过 topologyKey 来定义的topologyKey 对应的值是 node 上的一个标签名称比如各别节点zone=A标签各别节点有zone=B标签pod affinity topologyKey定义为zone那么调度pod的时候就会围绕着A拓扑B拓扑来调度而相同拓扑下的node就为“同一位置”如果基于各个节点kubernetes.io/hostname标签作为评判标准那么很明显“同一位置”意味着同一节点不同节点既为不同位置

pod亲和性

apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: daocloud.io/library/nginx:latest
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: db
    tier: db
spec:
  containers:
  - name: busybox
    image: daocloud.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3600"]
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - {key: app, operator: In, values: ["myapp"]}
        topologyKey: kubernetes.io/hostname

查看结果:

[root@master yaml]# kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE     IP     NODE     NOMINATED NODE   READINESS GATES
pod-first            1/1     Running   0          10m     10.244.1.6   node-1   <none>           <none>
pod-second           1/1     Running   0          10m     10.244.1.7   node-1   <none>           <none>

pod反亲和性

Pod反亲和性场景当应用服务A和数据库服务B要求尽量不要在同一台节点上的时候

apiVersion: v1
kind: Pod
metadata:
  name: pod-first-1
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: daocloud.io/library/nginx:latest
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second-2
  labels:
    app: backend
    tier: db
spec:
  containers:
  - name: busybox
    image: daocloud.io/library/busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3600"]
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - {key: app, operator: In, values: ["myapp"]}
        topologyKey: kubernetes.io/hostname

查看结果:

[root@master yaml]# kubectl get pod -o wide
NAME                 READY   STATUS    RESTARTS   AGE     IP           NODE     NOMINATED NODE   READINESS GATES
pod-first-1          1/1     Running   0          7m28s   10.244.1.8   node-1   <none>           <none>
pod-second-2         1/1     Running   0          7m28s   10.244.2.6   node-2   <none>           <none>