二十三. Kubernetes 安装时的调度策略

一. 基础解释

  1. 假设当前使用的是k8s集群,有多个节点, 在部署pod时底层会通过scheduler调度器计算调度,选择其中一个节点进行部署, 默认情况下这个计算调度过程是k8s决定的, 也可以通过设置一定的规则,根据规则选择指定的节点,例如部署pod时通过"spec.nodeName"属性设置选择指定节点部署
  2. 提出了一下调度设策略
  1. 通过"spec.nodeName"属性设置选择指定节点
  2. 通过nodeSelector选择器,根据节点标签选中
  3. Affinity: 亲和
  4. anti-affinity: 反亲和

nodeSelector

  1. nodeSelector是PodSpec的一个字段,包含键值对的映射,为了使pod在某个节点上运行,该节点标签中必须包含这里的键值对

实际可以理解为给k8s节点设置对应的标签,在部署pod时设置节点选择器,通过节点选择器选中指定节点安装部署

  1. nodeSelector 是硬亲和的一种
    在这里插入图片描述

NodeAffinity 亲和性

  1. NodeAffinity意为Node节点亲和性的调度策略,是用于替换NodeSelector的全新调度策略,分为:硬亲和性required和软亲和性preferred两种

1. node硬亲和性

  1. 例如nodeSelector节点选择器,可以设置Pod对象根据标签匹配的方式将Pod对象强制调度至某一类特定的节点之上 ,不过nodeSelector节点选择器只能设置简单的等值关系,而nodeAffinity中支持使用 matchExpressions属性构建更为复杂的标签选择机制
  2. 可以通过requiredDuringSchedulinglgnoredDuringExecution属性设置一个对象列表,用于定义节点硬亲和性,它可由一到多个nodeSelectorTerm定义的对象组成,彼此间为“逻辑或”的关系,进行匹配度检查时,在多个nodeSelectorTerm之间只要满足其中之一 即可
  3. 硬亲和支持:
  1. nodeAffinity: 节点亲和设置
  2. podAffinity: pod亲和设置
  3. podAntiAffinity: pod反亲和设置
  1. 注意点: 在Pod资源基于节点亲和性规则调度至某节点之后,节点标签发生了改变而不再符合此节点亲和性规则时 ,调度器不会将Pod对象从此节点上移出,因为,它仅对新建的Pod对象生效。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy
  labels:
    app: web
spec:
  replicas: 6
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx-deploy
        image: nginx:latest
        imagePullPolicy: IfNotPresent
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
            nodeSelectorTerms:
            - matchExpressions:
              - key: app
                operator: In  ##表示键与一组值的关系,有效的运算符有:In、NotIn、Exist、DoesNotExsit。GT和LT
                values:
                - web
		#podAffinity: #指定亲和的pod(与选中的亲和pod安装到同一个节点上)
		#podAntiAffinity: #反亲和pod(与反亲和pod不能安装到同一节点上)

2. node软亲和性

  1. 节点软亲和性为节点选择机制提供了一种柔性控制逻辑,被调度的Pod对象不再是“必须”而是“应该”放置于某些特定节点之上,当条件不满足时它也能够接受被编排于其他不符合条件的节点之上。另外,它还为每种倾向性提供了weight属性以便用户定义其优先级,取值范围是1 ~ 100,数字越大优先级越高
  2. 通过preferredDuringSchedulingIgnoredDuringExecution属性设置软亲和,
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy
  labels:
    app: web
spec:
  replicas: 6
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx-deploy
        image: nginx:latest
        imagePullPolicy: IfNotPresent
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution: #设置软亲和
            - weight: 60      ###设置app=web的权重为60
              preference: #指定亲和的条件
                matchExpressions:
                - key: app
                  operator: In
                  values:
                    - web
               preference: #指定亲和的条件
                 matchExpressions:
                 - key: disk #表示磁盘,综合起来看就是磁盘大于40的
				   values: ["40"]
				   operator: Gt #大于

            - weight: 40   ###设置app=server的权重为40
              preference:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                    - server

3. 拓扑键

  1. 在设置亲和与反亲和时存在一个topologyKey拓扑键,用来划分逻辑区域,
  2. pod亲和性调度需要各个相关的pod对象运行于"同一位置", 而反亲和性调度则要求他们不能运行于"同一位置",这里指定“同一位置” 就是通过 topologyKey 来定义的,topologyKey 对应的值是 node 上的一个标签名称,是指一个范围的概念,比如一个 Node、一个机柜、一个机房或者是一个地区(如杭州、上海)等,实际上对应的还是 Node 上的标签, 比如各别节点zone=A标签,各别节点有zone=B标签,pod affinity topologyKey定义为zone,那么调度pod的时候就会围绕着A拓扑,B拓扑来调度,而相同拓扑下的node就为“同一位置”
  3. 执行命令给"k8s-node1"节点设置zone标签为sh-1
kubectl label node k8s-node1 zone=sh-1
  1. 如果基于各个节点"kubernetes.io/hostname"标签作为评判标准,那么“同一位置”意味着同一节点,不同节点既为不同位置

也就是拓扑键为"kubernetes.io/hostname"作为标准时,如果在亲和策略中,那么会加入到同一个节点上,如果在反亲和策略中,那么就不能在同一节点上

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity: #pod亲和策略
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: failure-domain.beta.kubernetes.io/zone #设置亲和的拓扑键
    podAntiAffinity: #pod反亲和策略
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: kubernetes.io/hostname #反亲和策略拓扑键
  containers:
  - name: with-pod-affinity
    image: k8s.gcr.io/pause:2.0
  1. 注意事项,原则上topologyKey 可以是任何合法的标签 Key, 出于性能和安全原因,对 topologyKey 有一些限制:
  1. 对于亲和性和 requiredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,topologyKey 不能为空。
  2. 对于 requiredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,引入 LimitPodHardAntiAffinityTopology 准入控制器来限制 topologyKey 只能是 kubernetes.io/hostname。如果要使用自定义拓扑域,则可以修改准入控制器,或者直接禁用它。
  3. 对于 preferredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,空的 topologyKey 表示所有拓扑域。截止 v1.12 版本,所有拓扑域还只能是 kubernetes.io/hostname、failure-domain.beta.kubernetes.io/zone 和 failure-domain.beta.kubernetes.io/region 的组合。
  4. 除上述情况外,topologyKey 可以是任何合法的标签 key
拓扑分区约束
  1. 官方文档
  2. 拓扑键只能粗粒度划分区域,拓扑分区约束可以更细粒度设置
  3. 我们可以给节点设置标签,如下
    在这里插入图片描述
  4. 在部署pod时通过topologySpreadConstraints拓扑分区约束
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  # 配置一个拓扑分布约束
  topologySpreadConstraints:
    - maxSkew: 1 #最大倾斜,表示安装选中的pod时节点部署数量允许超过平均值的最大数?
      topologyKey: zone #拓扑键,例如根据zone分区此时就会出现zoneA与zoneB
      minDomains: <integer> # 可选;自从 v1.25 开始成为 Beta    
      labelSelector: #选择器(该选择器选的是pod类型,上面使用zone做了分区)
        matchLables:
          foo: bar #根据标签选中pod
      whenUnsatisfiable: <string>
      
      matchLabelKeys: <list> # 可选;自从 v1.25 开始成为 Alpha
      nodeAffinityPolicy: [Honor|Ignore] # 可选;自从 v1.25 开始成为 Alpha
      nodeTaintsPolicy: [Honor|Ignore] # 可选;自从 v1.25 开始成为 Alpha

二. 污点与容忍

  1. 官方文档
  2. 以k8s调度部署pod为例,在部署时首先会按照拓扑键拓扑分区约束进行划分,然后通过亲和与反亲和策略选择指定节点安装部署,然后会通过污点与容忍度去判断选择
  3. 首先污点是设置到节点上的,容忍是设置在pod上的,默认情况下不会给有污点标签的节点调度,除非pod中设置了容忍,容忍跟污点是有对应关系的
  4. 进而解释在k8s集群中安装部署时为什么不回安装部署到master节点,因为master节点给打了污点标签,查看污点命令

执行命令后返回的数据中,前面"node-role.kubernetes.io/master"是污点名,冒号后面是污点的作用效果,例如 “NoSchedule”

kubectl describe node 节点名称|grep Taint

在这里插入图片描述
5. 污点类型三种:

  1. NoSchedule: 不调度,不给有该类型污点的节点部署pod
  2. PreferNoSchedule: 比NoSchedule宽泛,尽量不会在该类型的节点上调度
  3. NoExecute: 不能在节点上运行,如果已经运行将被驱逐(被赶走后基于k8s的恢复机制,可以在其它节点重新拉起)
  1. 节点添加污点命令
kubectl taint node 节点名称 污点key=污点值(值是可选参数):污点类型
  1. 并且在k8s 1.6版本后如果发现节点存在一些特殊情况,会自动给节点添加污点,针对这些节点进行特殊处理,例如隔离防止应用部署到问题节点上
    在这里插入图片描述
  2. pod上设置容忍
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: deploymentdemo 
  labels: 
    app: deploymentdemo 
  spec: 
    replicas: 10 
    template: 
      metadata: 
        name: deploymentdemo 
        labels: 
          app: deploymentdemo 
      spec: 
        tolerations: #设置容忍
          - key: "offline" #容忍的污点key 
            value: "testtaint" #容忍的污点key对应的value 
            operator: "Equal" #容忍方式,Equal等值匹配,Exists存在
            effect: "NoSchedule" #容忍污点类型(如果不指定该属性表示可以容忍通过key拿到的任何类型污点)
            #tolerationSeconds: #容忍时间(指定时间内节点还是污点状态,则不再容忍) 
        containers: 
          - name: deploymentdemo 
            image: nginx:1.17.10-alpine 
            imagePullPolicy: IfNotPresent 
            ports: 
              - containerPort: 80 
        restartPolicy: Always 
  selector: 
    matchLabels: 
      app: deploymentdemo

三. 资源限制与调度策略

  1. 在部署pod时,containers容器中可以设置requests与limit, 在调度部署时,k8s底层会根据这个限制判断选择合适的节点安装
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值