Kubernetes NodeTaint PodAffinity NodeAffinity


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

简介

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

1. Scheduler

1.1 NodeScheduler

在实际状况下咱们可能须要将Pod调度到指定的一些Node节点上,能够经过Node的标签(Label)和Pod的NodeSelector属性相匹配,来达到上述目的。node

NodeScheduler实现方式

咱们能够经过在节点打上Label,经过定义Pod时,指定Label将Pod调度到指定的节点上linux

kubectl label node nodename label=labelnamenginx

[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标签web

[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节点亲和性调度有两种调度策略api

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

  • PreferredDuringSchedulingIgnoredDuringExecution
    软亲和,尽可能将Pod调度到知足条件的Node上,若是没有知足的,调度器会根据算法选择一个最合适的节点优化

PreferredDuringSchedulingIgnoredDuringExecution实现方式

在template.spec下定义ui

[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的节点上spa

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建立操做

相关文章
相关标签/搜索