袁党生博客

  • 主页
  • linux基础
  • SHELL
  • WEB
  • 负载
  • 企业级应用
  • 数据库
  • KVM
  • Docker
  • K8S
  • 监控
  • 存储
  • 博客搭建问题
  1. 首页
  2. K8S
  3. 正文

十二、kubernetes亲和与反亲和

2023年8月24日 1669点热度 0人点赞 0条评论


本章概述

  • node Affinity与anti-affinity(node亲和与反亲和)
  • pod Affinity与pod antiaffinity(pod亲和与反亲和)
  • 污点与容忍
  • kubernetes pod驱逐

12.1 node Affinity与anti-affinity(node亲和与反亲和)

12.1.1 nodeSelector

  nodeSelector 基于node标签选择器,将pod调度的指定的目的节点上。
  官网链接:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-node/
  可用于基于服务类型干预Pod调度结果,如对磁盘I/O要求高的pod调度到SSD节点,对内存要求比较高的pod调度的内存较高的节点。
  也可以用于区分不同项目的pod,如将node添加不同项目的标签,然后区分调度。
查看默认标签
kubectl describe node 172.31.7.111

也可以使用命令:kubectl get node --show-labels 查看所有node的标签

如果需要查看某个node的标签,需要在node后加上node ip地址。即:kubectl get node 172.31.7.111 --show-labels

为了便于演示,为node节点打标签
指定172.31.7.111属于magedu项目,且硬盘为ssd
指定172.31.7.112属于magedu项目,且硬盘为hdd
为节点172.31.7.111打标签
kubectl label node 172.31.7.111 project=magedu
kubectl label node 172.31.7.111 disktype=ssd
查看标签:
kubectl describe node 172.31.7.111

为节点172.31.7.112打标签
kubectl label node 172.31.7.112 project=magedu
kubectl label node 172.31.7.112 disktype=hdd
查看标签

如果node节点打错标签,如何删除标签:
kubectl label node 172.31.7.112 disktype- #只需要在标签的key值后加上“-”即可
再次查看标签,可以看到172.31.7.111节点的disktype标签被删除

示例:将pod调度到目的node节点,yaml文件中指定的key和value必须精确匹配(通过指定标签,该pod一定会被调度到172.31.7.112上)

vim  case1-nodeSelector.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app2-deployment-label
  name: magedu-tomcat-app2-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: magedu-tomcat-app2-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app2-selector
    spec:
      containers:
      - name: magedu-tomcat-app2-container
        image: tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
        resources:
          limits:
            cpu: 1
            memory: "512Mi"
          requests:
            cpu: 500m
            memory: "512Mi"
      nodeSelector:      #指定标签选择器,作用于整个pod,对pod中所有容器都生效
        project: magedu        #指定项目为magedu
        disktype: hdd         #指定磁盘类型为hdd

创建pod
kubectl apply -f case1-nodeSelector.yaml
查看pod,pod所在物理机节点为172.31.7.112

12.1.2 nodeName

通过nodename调度pod,将pod调度到指定的node上
如果目标node宕机,则会调度失败,使用场景较少
示例:通过指定nodename,将pod调度到172.31.7.113上

vim case2-nodename.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app2-deployment-label
  name: magedu-tomcat-app2-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: magedu-tomcat-app2-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app2-selector
    spec:
      nodeName: 172.31.7.113        #指定nodename为172.31.7.113
      containers:
      - name: magedu-tomcat-app2-container
        image: tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
        resources:
          limits:
            cpu: 1
            memory: "512Mi"
          requests:
            cpu: 500m
            memory: "512Mi"

创建pod
kubectl apply -f case2-nodename.yaml
查看pod

pod被调度到172.31.7.113上

12.1.3 node affinity(节点亲和)

affinity是Kubernetes 1.2版本后引入的新特性,类似于nodeSelector,允许使用者指定一些Pod在Node间调度的约束。
目前支持两种形式:
  requiredDuringSchedulingIgnoredDuringExecution #必须满足pod调度匹配条件,如果不满足则不进行调度
  preferredDuringSchedulingIgnoredDuringExecution #倾向满足pod调度匹配条件,不满足的情况下会调度的不符合条件的Node上

IgnoreDuringExecution表示如果在Pod运行期间Node的标签发生变化,导致亲和性策略不能满足,也会继续运行当前的Pod。
Affinity与anti-affinity的目的也是控制pod的调度结果,但是相对于nodeSelector,亲和与反亲和功能更加强大:

1、标签选择器不仅仅支持and,还支持In、NotIn、Exists、DoesNotExist、Gt、Lt。
    In:标签的值存在匹配列表中(匹配成功就调度到目的node,实现node亲和)
    NotIn:标签的值不存在指定的匹配列表中(不会调度到目的node,实现反亲和)
    Gt:标签的值大于某个值(字符串)
    Lt:标签的值小于某个值(字符串)
    Exists:指定的标签存在
2、可以设置软匹配和硬匹配,在软匹配下,如果调度器无法匹配节点,仍然将pod调度到其它不符合条件的节点。
3、还可以对pod定义亲和策略,比如允许哪些pod可以或者不可以被调度至同一台node。

注意:
  如果定义一个nodeSelectorTerms(条件)中通过一个matchExpressions基于列表指定了多个operator条件,则只要满足其中一个条件,就会被调度到相应的节点上,即or的关系,即如果nodeSelectorTerms下面有多个条件的话,只要满足任何一个条件就可以了,见12.1.3.1硬亲和示例1
  如果定义一个nodeSelectorTerms中都通过一个matchExpressions(匹配表达式)指定key匹配多个条件,则所有的目的条件都必须满足才会调度到对应的节点,即and的关系,即果matchExpressions有多个选项的话,则必须同时满足所有这些条件才能正常调度,见12.1.3.2硬亲和示例2 。

12.1.3.1 硬亲和示例1
编辑yaml文件

vim  case3-1.1-nodeAffinity-requiredDuring-matchExpressions.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app2-deployment-label
  name: magedu-tomcat-app2-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: magedu-tomcat-app2-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app2-selector
    spec:
      containers:
      - name: magedu-tomcat-app2-container
        image: tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions: #匹配条件1,多个values可以调度
              - key: disktype
                operator: In
                values:
                - hdd # 只有一个value是匹配成功也可以调度
                - xxx
            - matchExpressions: #匹配条件2,多个matchExpressions加上以及每个matchExpressions values只有其中一个value匹配成功就可以调度
              - key: project
                operator: In
                values:
                - mmm #即使这俩条件2的都匹配不上也可以调度
                - nnn

以上示例中,有两个匹配表达式matchExpressions,每个匹配表达式中都有一个key值,只要满足其中一个匹配表达式matchExpressions即可匹配
由于yaml文件中指定disktype为hdd的条件,因此pod会被调度到172.31.7.112上
创建pod
kubectl apply -f case3-1.1-nodeAffinity-requiredDuring-matchExpressions.yaml
查看pod,被调度到172.31.7.112上

12.1.3.2 硬亲和示例2
编辑yaml文件

vim  case3-1.2-nodeAffinity-requiredDuring-matchExpressions.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app2-deployment-label
  name: magedu-tomcat-app2-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: magedu-tomcat-app2-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app2-selector
    spec:
      containers:
      - name: magedu-tomcat-app2-container
        image: tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions: #硬亲和匹配条件1
              - key: disktype
                operator: In
                values:
                - ssd
                - xxx #同个key的多个value只有有一个匹配成功就行
              - key: project #硬亲和条件1和条件2必须同时满足,否则不调度
                operator: In
                values:
                - magedu

以上示例中有一个匹配表达式matchExpressions,在该匹配表达式中有两个key值,这两个key都要满足才可以匹配
必须要满足属于magedu项目,且disktype为ssd才会被调度,因此pod会被调度到172.31.7.111上
创建pod
kubectl apply -f case3-1.2-nodeAffinity-requiredDuring-matchExpressions.yaml
查看pod,被调度到172.31.7.111上

12.1.3.3 软亲和示例1
编辑yaml文件

vim case3-2.1-nodeAffinity-preferredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app2-deployment-label
  name: magedu-tomcat-app2-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: magedu-tomcat-app2-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app2-selector
    spec:
      containers:
      - name: magedu-tomcat-app2-container
        image: tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 80  #软亲和条件1,值越大优先级越高,越优先匹配调度,如果条件1匹配,则不会匹配后续的其他条件
            preference:
              matchExpressions:
              - key: project
                operator: In
                values:
                  - magedu
          - weight: 60    #软亲和条件2,在条件1不满足时匹配条件2
            preference:
              matchExpressions:
              - key: disktype
                operator: In
                values:
                  - hdd

创建pod,查看pod调度结果(这时条件1为project=magedu,172.31.7.111和112都满足条件,pod被调度到172.31.7.112上)

更改软亲和条件1,查看调度结果(以下备注部分为修改内容)

          - weight: 80  
            preference:
              matchExpressions:
              - key: project
                operator: In
                values:
                  - mageduxx        #此处为修改内容
          - weight: 60    #软亲和条件2,在条件1不满足时匹配条件2
            preference:
              matchExpressions:
              - key: disktype
                operator: In
                values:
                  - hdd

创建pod,查看pod调度结果(这时172.31.7.112满足disktype为hdd的条件,pod被调度到172.31.7.112上)

更改软亲和条件1和条件2,查看调度结果(以下备注部分为修改内容)

          - weight: 80  
            preference:
              matchExpressions:
              - key: project
                operator: In
                values:
                  - mageduxx      #此处为修改内容(软亲和条件1)
          - weight: 60    #软亲和条件2,在条件1不满足时匹配条件2
            preference:
              matchExpressions:
              - key: disktype
                operator: In
                values:
                  - hddxx        #此处为修改内容(软亲和条件2)

创建pod,查看pod调度结果(这时172.31.7.111和112都不满足条件,但由于是软亲和,不满足条件也会被调度,因此pod被调度到172.31.7.112上)

12.1.3.4 软亲和结合硬亲和示例
基于硬亲和和软亲和实现pod调度:
1.绝对不会调度在哪些node
2.倾向于调度到哪些node
示例:

vim  case3-2.2-nodeAffinity-requiredDuring-preferredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app2-deployment-label
  name: magedu-tomcat-app2-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: magedu-tomcat-app2-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app2-selector
    spec:
      containers:
      - name: magedu-tomcat-app2-container
        image: tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution: #硬亲和
            nodeSelectorTerms:
            - matchExpressions: #硬匹配条件1
              - key: "kubernetes.io/role"
                operator: NotIn    #NotIn表示取反,不匹配
                values:
                - "master"  #硬性匹配key 的值kubernetes.io/role不包含master的节点,即绝对不会调度到master节点(node反亲和)
          preferredDuringSchedulingIgnoredDuringExecution: #软亲和
          - weight: 80
            preference:
              matchExpressions:
              - key: project
                operator: In
                values:
                  - magedu
          - weight: 60
            preference:
              matchExpressions:
              - key: disktype
                operator: In
                values:
                  - ssd

yaml文件指定硬亲和:pod被调度的node绝对不包括master节点
软亲和:pod被调度到node节点时,匹配条件被调度,不匹配也会被调度,保证pod可以被拉起
创建pod,查看pod调度结果(被调度到172.31.7.111上)

12.1.4 node 反亲和-nodeantiaffinity

编辑yaml文件

vim  case3-3.1-nodeantiaffinity.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app2-deployment-label
  name: magedu-tomcat-app2-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: magedu-tomcat-app2-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app2-selector
    spec:
      containers:
      - name: magedu-tomcat-app2-container
        image: tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions: #匹配条件1
              - key: disktype
                operator: NotIn #调度的目的节点没有key为disktype且值为hdd的标签
                values:
                - hdd #绝对不会调度到含有label的key为disktype且值为hdd的hdd的节点,即会调度到没有key为disktype且值为hdd的hdd的节点

yaml文件指定反亲和:绝对不会调度到含有label的key为disktype且值为hdd的hdd的节点
创建pod,查看调度结果(172.31.7.111和113满足条件,pod被调度到172.31.7.111上)

12.2 pod Affinity与pod antiaffinity(pod亲和与反亲和)

12.2.1 Pod Affinity与anti-affinity简介

pod亲和和反亲和使用的场景不同:
  pod亲和性:把tomcat和nginx pod运行在同一个物理机节点,避免跨主机调用,降低消耗
  pod反亲和性:大数据或zookeeper等分布式集群需要独立部署的服务,调度到不同的节点,提升高可用
  Pod亲和性与反亲和性可以基于已经在node节点上运行的Pod的标签来约束新创建的Pod可以调度到的目的节点,注意不是基于node上的标签而是使用的已经运行在node上的pod标签匹配。
  其规则的格式为如果 node节点 A已经运行了一个或多个满足调度新创建的Pod B的规则,那么新的Pod B在亲和的条件下会调度到A节点之上,而在反亲和性的情况下则不会调度到A节点至上。
  其规则表示一个具有可选的关联命名空间列表的LabelSelector,只所以Pod亲和与反亲和可以通过LabelSelector选择namespace,是因为Pod是命名空间限定的而node不属于任何nemespace所以node的亲和与反亲和不需要namespace,因此作用于Pod标签的标签选择算符必须指定选择算符应用在哪个命名空间。
  从概念上讲,node节点是一个拓扑域(具有拓扑结构的域),比如k8s集群中的单台node节点、一个机架、云供应商可用区、云供应商地理区域等,可以使用topologyKey来定义亲和或者反亲和的颗粒度是node级别还是可用区级别,以便kubernetes调度系统用来识别并选择正确的目的拓扑域。

Pod 亲和性与反亲和性的合法操作符(operator)有 In、NotIn、Exists、DoesNotExist。
在Pod亲和性配置中,在requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution中,topologyKey不允许为空(Empty topologyKey is not allowed.)。
在Pod反亲和性中配置中,requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution 中,topologyKey也不可以为空(Empty topologyKey is not allowed.)。
对于requiredDuringSchedulingIgnoredDuringExecution要求的Pod反亲和性,准入控制器LimitPodHardAntiAffinityTopology被引入以确保topologyKey只能是 kubernetes.io/hostname,如果希望 topologyKey 也可用于其他定制拓扑逻辑,可以更改准入控制器或者禁用。
除上述情况外,topologyKey 可以是任何合法的标签键。

创建nginx pod用于后续pod亲和和反亲和测试

vim  case4-4.1-nginx.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: python-nginx-deployment-label
  name: python-nginx-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:       
    matchLabels:
      app: python-nginx-selector
  template:
    metadata:
      labels:
        app: python-nginx-selector
        project: python    #配置标签,key为project,value为python,用于后续演示
    spec:
      containers:
      - name: python-nginx-container
        image: nginx:1.20.2-alpine
        #command: ["/apps/tomcat/bin/run_tomcat.sh"]
        #imagePullPolicy: IfNotPresent
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"

---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: python-nginx-service-label
  name: python-nginx-service
  namespace: magedu
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30014
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
    nodePort: 30453
  selector:
    app: python-nginx-selector
    project: python #一个或多个selector,至少能匹配目标pod的一个标签

创建nginx pod
kubectl apply -f case4-4.1-nginx.yaml
pod被调度到172.31.7.112上

12.2.2 Pod Affinity(亲和)示例

1、pod软亲和示例:

vim  case4-4.2-podaffinity-preferredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app2-deployment-label
  name: magedu-tomcat-app2-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: magedu-tomcat-app2-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app2-selector
    spec:
      containers:
      - name: magedu-tomcat-app2-container
        image: tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
      affinity:
        podAffinity:   #指定pod亲和
          #requiredDuringSchedulingIgnoredDuringExecution:
          preferredDuringSchedulingIgnoredDuringExecution:   #配置软亲和
          - weight: 100    #设置权重为100
            podAffinityTerm:  #配置pod亲和
              labelSelector:
                matchExpressions:   #配置表达式
                - key: project        #匹配key值为project
                  operator: In
                  values:            #匹配value值为python
                    - python 
              topologyKey: kubernetes.io/hostname    #指定拓扑域,以hostname作为颗粒度,即新建pod与匹配条件的pod在同一台主机上
              namespaces:       #匹配在magedu这个namespace
                - magedu

yaml文件指定创建的pod与匹配条件的pod在同一个主机,条件为:在magedu 这个namespace,且key值为project,value值为python的pod。
查看新建pod所在主机为172.31.7.112,与nginx pod在同一个主机

注意:如果目标主机资源不足,且配置软亲和,会将pod调度到其他不满足条件的node上。

2、pod硬亲和示例:
编辑yaml文件

vim  case4-4.3-podaffinity-requiredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app2-deployment-label
  name: magedu-tomcat-app2-deployment
  namespace: magedu
spec:
  replicas: 3
  selector:
    matchLabels:
      app: magedu-tomcat-app2-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app2-selector
    spec:
      containers:
      - name: magedu-tomcat-app2-container
        image: tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
      affinity:
        podAffinity:     #指定pod亲和
          requiredDuringSchedulingIgnoredDuringExecution:   #指定pod硬亲和
          - labelSelector:
              matchExpressions:   #配置表达式
              - key: project      #匹配key值为project
                operator: In
                values:        #匹配value值为python
                  - python
            topologyKey: "kubernetes.io/hostname"   #指定拓扑域,以hostname作为颗粒度,即新建pod与匹配条件的pod在同一台主机上
            namespaces:
              - magedu    #匹配在magedu这个namespace

yaml文件指定新建的pod必须和匹配条件的pod在同一个主机
创建pod,查看pod调度情况(均和nginx pod在同一个主机)

注意:如果目标主机资源不足,且配置硬亲和,pod将不会被调度。
验证:
修改硬亲和条件:(以下备份部分为修改部分)

      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:   #指定pod硬亲和
          - labelSelector:
              matchExpressions:   #配置表达式
              - key: project      #匹配key值为project
                operator: In
                values:        #匹配value值为python
                  - pythonxx        #此处为修改内容(修改硬亲和条件)
            topologyKey: "kubernetes.io/hostname"   #指定拓扑域,以hostname作为颗粒度,即新建pod与匹配条件的pod在同一台主机上
            namespaces:
              - magedu    #匹配在magedu这个namespace

创建pod,查看pod状态为pending

查看pod日志,信息提示不匹配亲和条件
kubectl describe pod magedu-tomcat-app2-deployment-7ff7c989c7-cdpfg -n magedu

12.2.3 pod 反亲和

1、pod硬反亲和示例
基于硬反亲和实现多个pod调度不在一个node,要求必须满足
示例:

vim  case4-4.4-podAntiAffinity-requiredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app2-deployment-label
  name: magedu-tomcat-app2-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: magedu-tomcat-app2-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app2-selector
    spec:
      containers:
      - name: magedu-tomcat-app2-container
        image: tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
      affinity:
        podAntiAffinity:      #指定pod反亲和
          requiredDuringSchedulingIgnoredDuringExecution:   #指定硬亲和
          - labelSelector:
              matchExpressions:
              - key: project
                operator: In
                values:
                  - python
            topologyKey: "kubernetes.io/hostname"
            namespaces:
              - magedu

yaml文件指定新建pod和匹配条件的pod必须不在同一个主机,否则不会被调度
创建pod,查看pod(新建主机和nginx pod不在同一个主机,nginx pod在172.31.7.112上,新建pod在172.31.7.111上)

2、pod软反亲和示例

vim  case4-4.5-podAntiAffinity-preferredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app2-deployment-label
  name: magedu-tomcat-app2-deployment
  namespace: magedu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: magedu-tomcat-app2-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app2-selector
    spec:
      containers:
      - name: magedu-tomcat-app2-container
        image: tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        #imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: project
                  operator: In
                  values:
                    - python
              topologyKey: kubernetes.io/hostname
              namespaces:
                - magedu

yaml文件指定新建pod和符合条件的pod能不在同一个主机就不在同一个主机,如果没有满足条件的主机,则也可以和符合条件的pod在同一个主机
创建pod,查看pod调度情况新建主机和nginx pod不在同一个主机,nginx pod在172.31.7.112上,新建pod在172.31.7.111上)

软硬亲和与反亲和总结:
硬亲和-绝对会在一起
硬反亲和-绝对不会在一起
软亲和-能在一起一起就在一起
软反亲和-能不在一起就不在一起,如果匹配失败也会在一起

12.3 污点与容忍

12.3.1 污点与容器简介

1、污点
  污点(taints),用于node节点排斥 Pod调度,与亲和的作用是完全相反的,即taint的node和pod是排斥调度关系。
  容忍(toleration),用于Pod容忍node节点的污点信息,即node有污点信息也会将新的pod调度到node。
  官网链接:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/taint-and-toleration/
污点的三种类型:
(1)NoSchedule: 表示k8s将不会将Pod调度到具有该污点的Node上
示例:
kubectl taint nodes 172.31.7.111 key1=value1:NoSchedule #设置污点
kubectl describe node 172.31.7.111 #查看污点

注意:此时创建pod,不会调度到该node上
kubectl taint node 172.31.7.111 key1:NoSchedule- #取消污点
查看污点信息,已经被取消

(2)PreferNoSchedule: 表示k8s将尽量避免将Pod调度到具有该污点的Node上
(3)NoExecute: 表示k8s将不会将Pod调度到具有该污点的Node上,同时会将Node上已经存在的Pod强制驱逐出去(使用场景:node节点下线)
示例:
kubectl taint nodes 172.31.7.111 key1=value1:NoExecute

12.3.2 tolerations容忍

定义 Pod 的容忍度,可以调度至含有污点的node。
基于operator的污点匹配:
  如果operator是Exists,则容忍度不需要value而是直接匹配污点类型。
  如果operator是Equal,则需要指定value并且value的值需要等于tolerations的key。

示例:提前在node打上污点,然后再配置容忍
(1)为172.31.7.111节点打上污点
kubectl taint nodes 172.31.7.111 key1=value1:NoSchedule #设置污点
(2)创建pod,配置容忍,可以将该pod调度至设置污点的node上

vim  case5.1-taint-tolerations.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
  labels:
    app: magedu-tomcat-app1-deployment-label
  name: magedu-tomcat-app1-deployment
  namespace: magedu
spec:
  replicas: 5        #创建5个副本,便于查看演示效果
  selector:
    matchLabels:
      app: magedu-tomcat-app1-selector
  template:
    metadata:
      labels:
        app: magedu-tomcat-app1-selector
    spec:
      containers:
      - name: magedu-tomcat-app1-container
        #image: harbor.magedu.local/magedu/tomcat-app1:v7
        image: tomcat:7.0.93-alpine
        #command: ["/apps/tomcat/bin/run_tomcat.sh"]
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
      tolerations:         #指定pod容忍
      - key: "key1"        #容忍的key值为key1
        operator: "Equal"   #指定operator是Equal,必须匹配value
        value: "value1"      #指定容忍的value值为value1
        effect: "NoSchedule"     #指定污点类型

---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: magedu-tomcat-app1-service-label
  name: magedu-tomcat-app1-service
  namespace: magedu
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
    #nodePort: 40003
  selector:
    app: magedu-tomcat-app1-selector

创建pod,查看调度结果,有pod被调度至172.31.7.111(已经被打上污点)上,说明容忍配置已经生效

12.4 kubernetes pod驱逐

12.4.1 驱逐简介

1、通过命令手动进行驱逐:
(1)通过打污点的方式驱逐容器

kubectl taint nodes 172.31.7.111 key1=value1:NoExecute   #会将172.31.7.111上除了daemonset类型的其他容器驱逐至别的主机
注意:该命令执行完以后,会给node节点打上key1=value1:NoExecute的污点信息,并立即驱逐pod
取消key1=value1:NoExecute污点:
kubectl taint nodes 172.31.7.111 key1:NoExecute-

(2)通过kubectl drain命令驱逐容器

kubectl drain  172.31.7.111  --ignore-daemonsets    会将172.31.7.111上除了daemonset类型的其他容器驱逐至别的主机
注意:该命令执行完以后,会给node节点打上SchedulingDisabled的标签,并立即驱逐pod。
取消SchedulingDisabled标签:
kubectl uncordon  172.31.7.111

2、kubelet自动发起驱逐,回收资源
  节点压力驱逐是由各kubelet进程主动终止Pod,以回收节点上的内存、磁盘空间等资源的过程,kubelet监控当前node节点的CPU、内存、磁盘空间和文件系统的inode等资源,当这些资源中的一个或者多个达到特定的消耗水平,kubelet就会主动地将节点上一个或者多个Pod强制驱逐,以防止当前node节点资源无法正常分配而引发的OOM。
官网链接:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/node-pressure-eviction/

k8s集群会预留一部分资源,当预留资源不足时,kubelet会自动发起驱逐,以下为默认的预留资源阈值,当资源小于阈值时会发起驱逐:

宿主机内存:
memory.available     #node节点可用内存,默认 <100Mi
nodefs是节点的主要文件系统,用于保存本地磁盘卷、emptyDir、日志存储等数据,默认是/var/lib/kubelet/,或者是通过kubelet通过--root-dir所指定的磁盘挂载目录
nodefs.inodesFree     #nodefs的可用inode,默认<5%
nodefs.available       #nodefs的可用空间,默认<10%
imagefs是可选文件系统,用于给容器提供运行时存储容器镜像和容器可写层。
imagefs.inodesFree    #imagefs的inode可用百分比
imagefs.available     #imagefs的磁盘空间可用百分比,默认<15%
pid.available         #可用pid百分比

小知识

kube-controller-manager实现eviction:node宕机后的驱逐
kubelet实现的eviction:基于node负载、资源利用率等进行pod驱逐。

驱逐(eviction,节点驱逐),用于当node节点资源不足的时候自动将pod进行强制驱逐,以保证当前node节点的正常运行。Kubernetes基于是QoS(服务质量等级)驱逐Pod , Qos等级包括目前包括以下三个:

(1)Guaranteed: limits和request的值相等,等级最高、最后被驱逐
 resources:
   limits:
     cpu: 500m
     memory: 256Mi
   requests:
     cpu: 500m
     memory: 256Mi
(2)Burstable: limit和request不相等,等级折中、中间被驱逐
 resources:
   limits:
     cpu: 500m
     memory: 256Mi
   requests:
     cpu: 256m
     memory: 128Mi
(3)BestEffort: 没有限制,即resources为空,等级最低、最先被驱逐

驱逐条件:
(1)eviction-signal:kubelet捕获node节点驱逐触发信号,进行判断是否驱逐,比如通过cgroupfs获取memory.available的值来进行下一步匹配。
(2)operator:操作符,通过操作符对比条件是否匹配资源量是否触发驱逐。
(3)quantity:使用量,即基于指定的资源使用值进行判断,如memory.available: 300Mi、nodefs.available: 10%等。
比如:nodefs.available\<10% #当node节点磁盘空间可用率低于10%就会触发驱逐信号

12.4.2 软驱逐

软驱逐不会立即驱逐pod,可以自定义宽限期,在条件持续到宽限期还没有恢复,kubelet再强制杀死pod并触发驱逐。
软驱逐条件:

eviction-soft: 软驱逐触发条件,比如memory.available < 1.5Gi,如果驱逐条件持续时长超过指定的宽限期,可以触发Pod驱逐。
eviction-soft-grace-period:软驱逐宽限期, 如 memory.available=1m30s,定义软驱逐条件在触发Pod驱逐之前必须保持多长时间。
eviction-max-pod-grace-period:终止pod的宽限期,即在满足软驱逐条件而终止Pod时使用的最大允许宽限期(以秒为单位)。

12.4.3 硬驱逐

硬驱逐条件没有宽限期,当达到硬驱逐条件时,kubelet 会强制立即杀死 pod并驱逐:
kubelet 具有以下默认硬驱逐条件(可以自行调整):

memory.available<100Mi
nodefs.available<10%
imagefs.available<15%
nodefs.inodesFree<5%(Linux 节点)

查看k8s集群硬驱逐配置方法:
查找kubelet service文件:
vim /etc/systemd/system/kubelet.service

查看kubelet配置文件:

vim /var/lib/kubelet/config.yaml
evictionHard:
 imagefs.available: 15%
 memory.available: 300Mi
 nodefs.available: 10%
 nodefs.inodesFree: 5%


一旦被驱逐,pod状态会显示如下状态:

标签: k8s
最后更新:2023年8月24日

袁党生

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2023 linux学习. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

豫ICP备18039507号-1