Kubernetes NodeTaint PodAffinity NodeAffinity


今天主要介绍一下kubernetes中调度的一些用法

简介

  • Scheduler
    当用户请求创建一个Pod通过ApiServer认证完成以后,将请求送达到调度器上,然后通过一系列的调度算法,将Pod调度到合理的Node节点上

1. Scheduler

1.1 NodeScheduler

在实际情况下我们可能需要将Pod调度到指定的一些Node节点上,可以通过Node的标签(Label)和Pod的NodeSelector属性相匹配,来达到上述目的。

NodeScheduler实现方式

我们可以通过在节点打上Label,通过定义Pod时,指定Label将Pod调度到指定的节点上

kubectl label node nodename label=labelname

[root@k8s-master01 ~]# kubectl get node --show-labels
NAME           STATUS   ROLES    AGE    VERSION   LABELS
k8s-master01   Ready    <none>   6d6h   v1.19.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master01,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-master02   Ready    <none>   6d6h   v1.19.0   app=linux,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master02,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-node01     Ready    <none>   6d6h   v1.19.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ds=true,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01,kubernetes.io/os=linux,node.kubernetes.io/node=,xinyuan=liu
k8s-node02     Ready    <none>   6d6h   v1.19.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ds=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node02,kubernetes.io/os=linux,node.kubernetes.io/node=,zone=foo
[root@k8s-master01 ~]# 
[root@k8s-master01 ~]# 
[root@k8s-master01 ~]# kubectl label node k8s-node01 itax=app

配置yaml文件
在template.metadata.spec.nodeSelector定义node标签

[root@k8s-master01 ~]# cat deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  name: nginxapp
  labels:
    app: nginx-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mynginx
  template:
    metadata:
      labels:
        app: mynginx
    spec:
      containers:
      - name: nginxweb1
        image: nginx:1.15-alpine
      nodeSelector:         #定义node标签调度
        itax: app             #标签名字和值

注意

  • 如果我们在其它的node上也定义了这个标签,这时调度器会根据一系列的调度算法选择最优的node将Pod调度上去
  • 如果资源清单里设置的node标签不存做,那么Pod就不会被创建成功一直处于Pending状态,找不到定义的标签

1.2 NodeAffinity节点亲和性

NodeAffinity称之为Node节点亲和性调度有两种调度策略

  • RequiredDuringSchedulingIgnoredDuringExecution
    称之为硬亲和,必须满足指定定义的规则才会将Pod调度到Node上

  • PreferredDuringSchedulingIgnoredDuringExecution
    软亲和,尽量将Pod调度到满足条件的Node上,如果没有满足的,调度器会根据算法选择一个最合适的节点

PreferredDuringSchedulingIgnoredDuringExecution实现方式

在template.spec下定义

[root@k8s-master01 ~]# cat deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  name: nginxapp
  labels:
    app: nginx-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mynginx
  template:
    metadata:
      labels:
        app: mynginx
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - preference:
              matchExpressions: 
              - key: zone             #标签名
                operator: In         #表示值在key的里面,下边可以定义多个key
                values:
                - foo                 #标签值
            weight: 1
      containers:
      - name: nginxweb
        image: nginx:1.15-alpine

此Pod定义的是软亲和,表示将此Pod尽量调度到node节点标签名为zone值是foo的节点上

RequiredDuringSchedulingIgnoredDuringExecution实现方式

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  name: nginxapp
  labels:
    app: nginx-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mynginx
  template:
    metadata:
      labels:
        app: mynginx
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - preference:
              matchExpressions:
              - key: zone
                operator: In
                values:
                - foo
            weight: 1
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: zone    
                operator: In 
                values:         
                - bar1       
      containers:
      - name: nginxweb
        image: nginx:1.15-alpine

如果两个同时使用那么先匹配硬亲和然后再从匹配到的硬亲和去匹配软亲和

1.2 PodAffinity节点亲和性

Pod的亲和性和反亲和性(互斥)

能让用户从另一个角度来限制Pod所能运行的节点,Pod的亲和和互斥是基于Pod标签进行判断的

注意Pod的亲和和互斥是基于namespace进行匹配的

podAffinity亲和性

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  name: nginxapp
  labels:
    app: nginx-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mynginx
  template:
    metadata:
      labels:
        app: mynginx
    spec:
      containers:
      - name: nginxweb1
        image: nginx:1.15-alpine
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - mynginx
            topologyKey: kubernetes.io/hostname       # 表示只要hostname值一样就说明是同一位置拓扑域

表示将Pod部署到Pod的标签名app值为mynginx的Pod所在节点的node上

podAntiAffinity亲和性

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  name: nginxapp
  labels:
    app: nginx-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mynginx
  template:
    metadata:
      labels:
        app: mynginx
    spec:
      containers:
      - name: nginxweb1
        image: nginx:1.15-alpine
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - mynginx
            topologyKey: kubernetes.io/hostname       # 表示只要hostname值一样就说明是同一位置拓扑域

1.3 NodeTaintTolerations

对于Node affinity,无论是强制约束(hard)或偏好(preference)方式,都是调度pod到预期节点上,而Taints恰好与之相反,如果一个节点标记为Taints,除非 Pod也被标识为可以耐受污点节点,否则该Taints节点不会被调度pod。Taints与tolerations当前处于beta阶段, Taints节点应用场景比如用户希望把Kubernetes Master节点保留给 Kubernetes 系统组件使用,或者把一组具有特殊资源预留给某些pod。pod不会再被调度到taint标记过的节点

如果想为特殊的用户指定一组node,可以添加一个污点到这组node上(运行命令: kubectl taint nodes nodename dedicated=groupName:NoSchedule)。然后添加对应的容忍到这个Pod上(这个最容易实现的方法是写一个客户端准入控制器)。带有相应容忍的Pod就可以像被调度到集群中其他node一样被调度到带有相应污点的node上。

污点是定义节点上的一种键值属性;主要用于让节点拒绝Pod的(拒绝那些不能容忍污点的Pod);所以说我们得在Pod建议能够容忍的污点

Taint的定义对Pod的排斥结果

  • NoSchedul
    只影像调度过程,如果不能容忍那么就不被调度上,对现在的Pod对象不产生影像
  • NoExecute
    即影像调度过程,也影响现在节点的Pod,不能容忍的Pod将会被驱逐
    可用于此node故障打上污点驱逐现有node的Pod

NodeTaint

设置node污点

[root@k8s-master01 ~]# kubectl taint node k8s-master01 node-type=production:NoSchedule #此处node现有的Pod不会被驱逐

[root@k8s-master01 ~]# kubectl taint node k8s-master01 node-type=production:NoExecute #此处node现有的Pod会被驱除

设置Pod的容忍

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  name: nginxapp
  labels:
    app: nginx-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mynginx
  template:
    metadata:
      labels:
        app: mynginx
    spec:
      containers:
      - name: nginxweb1
        image: nginx:1.15-alpine
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions: 
              - key: app
                operator: In
                values: 
                - mynginx
            topologyKey: kubernetes.io/hostname       # 表示只要hostname值一样就说明是同一位置拓扑域
      tolerations:
      - key: "node-type"      #      污点的key
        operator: "Equal"     #      容忍程度
        value: "producction"  #      污点的volue
        effect: "NoSchedule"

2. 调度器的过程

具体的调度过程,一般如下:首先,客户端通过API Server的REST API/kubectl/helm创建pod/service/deployment/job等,支持类型主要为JSON/YAML/helm tgz。 接下来,API Server收到用户请求,存储到相关数据到etcd。 调度器通过API Server查看未调度(bind)的Pod列表,循环遍历地为每个Pod分配节点,尝试为Pod分配节点。
调度过程分为2个阶段:

第一阶段:预选过程,过滤节点,调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。

第二阶段:优选过程,节点优先级打分,对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把容一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等。

选择主机:选择打分最高的节点,进行binding操作,结果存储到etcd中。 所选节点对于的kubelet根据调度结果执行Pod创建操作

posted @ 2020-11-30 23:47  刘新元  阅读(330)  评论(0编辑  收藏  举报