Kubernetes 的亲和性污点与容忍

Kubernetes 的亲和性污点与容忍

在Kubernetes 中,调度 是指将 Pod 部署到合适的节点(node)上。

k8s的默认调度器是kube-scheduler,它执行的是一个类似平均分配的原则,让同一个service管控下的pod尽量分散在不同的节点。

 节点标签

节点标签关联的指令是kubectl label,标签是是一种键值对,可以用来标识和选择资源。例如:需要给某个节点打个标记以便后面用的上,这个标记就叫标签。

增加标签

kubectl label node docker-desktop restype=strong-cpu
这里增加了一个 restype=strong-cpu 的标签,表示这个节点cpu很强;

查看标签

kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
docker-desktop Ready <none> 328d v1.22.5 disktype=ssd

删除标签

kubectl label node docker-desktop restype-
nodeSelector-简单的节点选择器
nodeSelector:在部署pod的时候告诉集群,我要部署到符合我要求的节点;
前面已经看到我k8s的节点 docker-desktop ,已经打了 disktype=ssd 的标签,那我们来部署一个测试的pod看看

affinity: 亲和性

requiredDuringSchedulingIgnoredDuringExecution:硬策略
preferredDuringSchedulingIgnoredDuringExecution:软策略
nodeSelectorTerms:节点选择项,数组
matchExpressions:匹配表达式,数组
weight: preferredDuringSchedulingIgnoredDuringExecution 可设置的权重字段,值范围是 1 到 100。会计算到调度打分算法上,分数高的优先级高;
operator:逻辑操作符,比如这里的in表示包含,一共有以下逻辑运算符;
- In:label 的值在某个列表中
- NotIn:label 的值不在某个列表中
- Gt:label 的值大于某个值
- Lt:label 的值小于某个值
- Exists:某个 label 存在
- DoesNotExist:某个 label 不存在
#可用NotIn和DoesNotExist实现反亲和性;
匹配规则:

如果你同时指定了 nodeSelector 和 nodeAffinity , 两者必须都要满足, 才能将 Pod 调度到候选节点上。
如果你在与 nodeAffinity 类型关联的 nodeSelectorTerms 中指定多个条件, 只要其中一个 nodeSelectorTerms 满足,Pod 就可以被调度到节点上。
如果你在与 nodeSelectorTerms 的一个 matchExpressions 中写个表达式, 则只有当所有表达式都满足,Pod 才能被调度到节点上。

pod间的亲和反亲和性

前面的节点亲和性是通过pod和节点之间的标签进行匹配,选择的;

pod的亲和性和反亲和性调度指:通过已在运行中的pod标签进行选择调度部署的节点;
pod的亲和性调度:一个典型的使用场景就是在集群环境是有多数据中心的,那一个服务部署已经部署到广东了,那我跟他相关的需要大量通信的其他服务也尽量部署到广东,降低彼此间的通信延迟;
pod的反亲和性调度:一个典型的使用场景就是我的服务要尽可能分散到各个数据中心、区域,比如广东、西安、上海、北京,都要有我的服务,避免某个数据中心故障服务全部宕机;

案列:

复制代码
podAffinity: #pod亲和性
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: restype
operator: In
values:
- strong-cpu
topologyKey: topology.kubernetes.io/zone #topology.kubernetes.io/hostname 表示同一节点
podAntiAffinity: #pod间反亲和性
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
topologyKey: topology.kubernetes.io/zone
复制代码

亲和性规则表示:当且仅当至少一个已运行且有 restype=strong-cpu 的标签的 Pod 处于同一区域时(topology.kubernetes.io/zone=GuangDong),才可以将该 Pod 调度到节点上。

反亲和性规则表示:如果节点处于 Pod 所在的同一可用区(也是看topology.kubernetes.io/zone)且至少一个 Pod 具有 disktype=ssd 标签,则该 Pod 不应被调度到该节点上。

亲和性调度

kubernetes亲和性调度(Affinity),它在NodeSelector的基础之上进行了扩展,可以通过配置的形式,实现优先选择满足条件的Node进行调度,如果没有,也可以调度到不满足条件的节点上,使调度更加灵活。

Affinity主要分为三类:

nodeAffinity(node亲和性): 以node为目标,解决pod可以调度到哪些node的问题
podAffinity(pod亲和性) : 以pod为目标,解决pod可以和哪些已存在的pod部署在同一个拓扑域中的问题
podAntiAffinity(pod反亲和性) : 以pod为目标,解决pod不能和哪些已存在pod部署在同一个拓扑域中的问题

 关于亲和性(反亲和性)使用场景的说明:
  亲和性:如果两个应用频繁交互,那就有必要利用亲和性让两个应用的尽可能的靠近,这样可以减少因网络通信而带来的性能损耗。
  反亲和性:当应用的采用多副本部署时,有必要采用反亲和性让各个应用实例打散分布在各个node上,这样可以提高服务的高可用性。

NodeAffinity(节点亲和性)

首先来看一下NodeAffinity的可配置项:

pod.spec.affinity.nodeAffinity
  requiredDuringSchedulingIgnoredDuringExecution  Node节点必须满足指定的所有规则才可以,相当于硬限制(找不到会调度失败)
    nodeSelectorTerms  节点选择列表
      matchFields   按节点字段列出的节点选择器要求列表
      matchExpressions   按节点标签列出的节点选择器要求列表(推荐)
        key    键
        values 值
        operator 关系符 支持Exists(存在), DoesNotExist(不存在), In(范围), NotIn(范围取反), Gt(大于), Lt(小于)
  preferredDuringSchedulingIgnoredDuringExecution 优先调度到满足指定的规则的Node,相当于软限制 (倾向,找不到不会调度失败)
    preference   一个节点选择器项,与相应的权重相关联
      matchFields   按节点字段列出的节点选择器要求列表
      matchExpressions   按节点标签列出的节点选择器要求列表(推荐)
        key    键
        values 值
        operator 关系符 支持In, NotIn, Exists, DoesNotExist, Gt, Lt
    weight 倾向权重,在范围1-100。

关系符operator的使用说明: 

复制代码
关系符的使用说明:
 
- matchExpressions:
  - key: nodeenv              # 匹配存在标签的key为nodeenv的节点,只匹配key就行
    operator: Exists
  - key: nodeenv              # 匹配标签的key为nodeenv,且value是"xxx""yyy"的节点,key和value都要匹配
    operator: In
    values: ["xxx","yyy"]
  - key: nodeenv              # 匹配标签的key为nodeenv,且value大于"xxx"的节点
    operator: Gt
    values: "xxx"
复制代码

硬限制演示

接下来首先演示一下requiredDuringSchedulingIgnoredDuringExecution(硬限制) ,
创建pod-nodeaffinity-required.yaml,内容如下:

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-nodeaffinity-required
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
  affinity:  #亲和性设置
    nodeAffinity: #设置node亲和性
      requiredDuringSchedulingIgnoredDuringExecution: # 硬限制
        nodeSelectorTerms:
        - matchExpressions: # 匹配env的值在["xxx","yyy"]中的标签,实际没有设置此标签,所以会匹配失败
          - key: nodeenv
            operator: In
            values: ["xxx","yyy"]
复制代码

软限制演示

接下来再演示一下requiredDuringSchedulingIgnoredDuringExecution(软限制) ,
创建pod-nodeaffinity-preferred.yaml,内容如下:

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-nodeaffinity-preferred
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
  affinity:  #亲和性设置
    nodeAffinity: #设置node亲和性
      preferredDuringSchedulingIgnoredDuringExecution: # 软限制
      - weight: 1
        preference:
          matchExpressions: # 匹配env的值在["xxx","yyy"]中的标签(当前环境没有)
          - key: nodeenv
            operator: In
            values: ["xxx","yyy"]
复制代码

 

PodAffinity(Pod亲和性)

PodAffinity主要实现以运行的Pod为参照,实现让新创建的Pod跟参照pod在一个区域的功能。
首先来看一下PodAffinity的可配置项:

复制代码
pod.spec.affinity.podAffinity
  requiredDuringSchedulingIgnoredDuringExecution  硬限制
    namespaces       指定参照pod的namespace
    topologyKey      指定调度作用域
    labelSelector    标签选择器
      matchExpressions  按节点标签列出的节点选择器要求列表(推荐)
        key    键
        values 值
        operator 关系符 支持In, NotIn, Exists, DoesNotExist.
      matchLabels    指多个matchExpressions映射的内容
  preferredDuringSchedulingIgnoredDuringExecution 软限制
    podAffinityTerm  选项
      namespaces      
      topologyKey
      labelSelector
        matchExpressions  
          key    键
          values 值
          operator
        matchLabels 
    weight 倾向权重,在范围1-100
复制代码

topologyKey用于指定调度时作用域,例如:
如果指定为kubernetes.io/hostname,那就是以Node节点为区分范围
如果指定为beta.kubernetes.io/os,则以Node节点的操作系统类型来区分

关于weight权重的解释:

这里weight权重的作用是,一个pod节点可以有多个软策略,每个软策略可以有不同的权重,然后根据权重由高到选择不同软策略,直到选中符合条件的节点。如果设置了多个软策略,权重价值就体现出来了。比如张三节点权重为4,先看看三节点符不符合选中条件,不符合,再看权重为3的李四节点符不符合选中条件...直到找到符合选中条件的节点。

 

接下来,演示下requiredDuringSchedulingIgnoredDuringExecution,

(1)首先创建一个参照Pod,pod-podaffinity-target.yaml

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-podaffinity-target
  namespace: dev
  labels:
    podenv: pro #设置标签
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
  nodeName: node1 # 将目标pod名确指定到node1上
复制代码

启动Pod:

kubectl create -f pod-podaffinity-target.yaml
kubectl get pods pod-podaffinity-target -n dev -o wide --show-labels

(2)、创建pod-podaffinity-required.yaml,内容如下:

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-podaffinity-required
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
  affinity:  #亲和性设置
    podAffinity: #设置pod亲和性
      requiredDuringSchedulingIgnoredDuringExecution: # 硬限制
      - labelSelector:  #标签选择器
          matchExpressions: # 匹配env的值在["xxx","yyy"]中的标签
          - key: podenv
            operator: In
            values: ["xxx","yyy"]
        topologyKey: kubernetes.io/hostname   #调度作用域,即如果匹配到,就调度到目标pod同一节点上
复制代码

上面配置表达的意思是:新Pod必须要与拥有标签nodeenv=xxx或者nodeenv=yyy的pod在同一Node上,显然现在没有这样pod,接下来,运行测试一下:

kubectl create -f pod-podaffinity-required.yaml
 
#查看pod状态,发现未运行
kubectl get pods pod-podaffinity-required -n dev

查看详细信息:

kubectl describe pods pod-podaffinity-required -n dev

 接下来修改  values: ["xxx","yyy"]----->values:["pro","yyy"]

意思是:新Pod必须要与拥有标签nodeenv=xxx或者nodeenv=yyy的pod在同一Node上

kubectl delete -f pod-podaffinity-required.yaml
# 修改  values: ["xxx","yyy"]----->values:["pro","yyy"]
vim pod-podaffinity-required.yaml
kubectl create -f pod-podaffinity-required.yaml
kubectl get pods pod-podaffinity-required -n dev

 

 

posted @   逆风飞翔的博客  阅读(15)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示