Kubernetes pod调度及精准调度策略

deployment或rc自动调度:

由master的Scheduler经过一系列的算法得出得分最高的节点。

NodeSelector定向调度

apiVersion: v1
kind: ReplicationController 
metadata:
  name: redis-master
  labels:	
    name: redis-master 
spec:
  replicas: 1
  selector:
    name: redis-master
  template:
    metadata:
      labels:
        name: redis-master
    spec:
      containers:
      - name: master
        image: kubeguide/redis-master
        ports:
        - containerPort: 6379
      nodeSelector:				#定向到拥有标签zone=north的节点,可以指定多个标签
        zone: north

NodeAffinity: node亲和性调度( pod与node之间的暧昧关系)

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution: #必须满足以下的要求(和nodeselect很像)
        nodeSelectorTerms:  #如果有多个,那么有一个满足就可以被调度(面向多个node)
        - matchExpressions:   #如果有多个,则一个节点需要满足所有要求才能被调度(对单个node的所有要求)
          - key: beta.kubernetes.io/arch
            operator: In   #其他参数还有In、NotIn、Exists、DoesNotExist、Gt、Lt(其中NotIn、DoesNotExist可以实现排斥的功能)
            values:
            - amd64
      preferredDuringSchedulingIgnoredDuringExecution:  #优先选择以下的要求 不强求,多个规则可以设置权重
      - weight: 1
        preference:
          matchExpressions:
          - key: disk-type
            operator: In
            values:
            - ssd
  containers:
 - name: with-node-affinity
    image: gcr.io/google_containers/pause:2.0

IgnoredDuringExecution的意思是:如果一个pod所在的节点在pod运行期间标签发生了变更,不再符合该pod的节点亲和性需求,则系统将忽略Node上label的变化,该pod能继续在该节点上运行。

注意事项:

  • 如果nodeselect和NodeAffinity同时定义,那么必须两个条件同时得到满足,pod才会运行在指定的node上。
  • 如果NodeAffinity指定了多个nodeSelectorTerms,那么其中一个能够匹配成功即可。
  • 如果在nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有matchExpressions才能运行该pod。

PodAffinity:Pod亲和与互斥调度策略(pod与pod之间的暧昧关系)

条件设置也是使用requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution

  • 判断亲和与互斥的依据是某个命名空间下的pod标签。
  • PodAffinity定义的位置是PodSpace的affinity字段下的podAffinity子字段中。Pod间的互斥性则被定义于同一层次的PodAntiAffinity子字段中。

其中topologyKey字段的值可以为:
kubernetes.io/hostname
failure-domain.beta.kebernetes.io/zone
failure-domain.beta.kubernetes.io/region

参照pod,下面的案例以此pod为参照:
名字为pod-flag,带有标签 security=S1、app=nginx

apiVersion: v1
kind: Pod
metadata:
  name: pod-flag
  labels:
    security: "S1"
    app: "nginx"
spec:
  containers:
  - name: nginx
    image: nginx

亲和性调度案例:创建后,该pod就会和参照pod运行在同一个节点上。

apiVersion: v1
kind: Pod
metadata:
  name: pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:#亲和性
      - labelSelector:
          matchExpressions:	#如果有多个,需要所有条件全部满足,才能调度到某个node上
          - key: security	#与拥有标签security=S1的pod在同一个节点
            operator: In	#其他参数还有In、NotIn、Exists、DoesNotExist、Gt、Lt(其中NotIn、DoesNotExist可以实现排斥的功能)
            values:
            - S1
        #namespaces:	#指定亲和性对象是哪个namespace下的,如果不指定就是所有namespace下的。
        topologyKey: kubernetes.io/hostname	#对node的label选择
  containers:
  - name: with-pod-affinity
    image: gcr.io/google_containers/pause:2.0

pod的互斥调度案例:创建之后的新Pod与security=S1的pod为同一个zone,但是不与app=nginx的pod为同一个Node。

apiVersion: v1
kind: Pod
metadata:
  name: anti-affinity
spec:
  affinity:
    podAffinity:	#亲和性
      requiredDuringSchedulingIgnoredDuringExecution:	#硬亲和性 。   也可以使用preferredDuringSchedulingIgnoredDuringExecution软亲和性,尽可能的和满足下面要求的pod调度到同一个节点。
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: failure-domain.beta.kubernetes.io/zone
    podAntiAffinity:	#反亲和性
      requiredDuringSchedulingIgnoredDuringExecution: #硬亲和性 。  也可以使用preferredDuringSchedulingIgnoredDuringExecution软亲和性,尽可能的和满足下面要求的pod调度到不同的节点。
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - nginx
        topologyKey: kubernetes.io/hostname
  containers:
 - name: anti-affinity
    image: gcr.io/google_containers/pause:2.0

注意事项:

  • 如果要使用Namespace列表进行限制,Namespace定义的位置与labelSelector、topologyKey同级。
  • 省略Namespace的设置,表示使用affinity/anti-affinity的pod所在的Namespace。如果namespace的值为空,则表示所有namespace。
  • requiredDuringSchedulingIgnoredDuringExecution的matchExpressions全部满足之后,系统才能将pod调度到某个Node上。

Taints(污点)和Tolerations(容忍)

场景:独占节点、具有特殊硬件设备的节点(GPU 、SSD)
污点可以让node拒绝pod的运行,与NodeAffinity相反。

用法:对node设置污点,然后在pod文件里面配置容忍属性,让pod能够(不是必须)运行在有污点的节点上。

对节点添加污点:

$ kubectl taint nodes node1 key=value:NoSchedule

Taint(污点)的键值分别为key、value,效果是:
NoSchedule - 强制不调度
PreferNoSchedule - 尽可能不调度

  • NoExecute生效的时候pod如果已经在污点节点上运行,则会被驱逐。
  • 可以对特殊的节点同时添加NoSchedule和PreferNoSchedule

pod配置文件添加Tolerations(容忍):

apiVersion: v1
kind: Pod
metadata:
  name: pod-toleration
spec:
  tolerations:			#容忍设置
 - key: "key"		#key和effect需要和Taint(污点)的设置一致
    operator: "Equal"	#operator的值为Equal,则value需要和污点标签相等
    value: "value"	
    effect: "NoSchedule" #key和effect需要和Taint(污点)的设置一致
#NoSchedule的取值还可以设置为PreferNoSchedule,尽可能的避免调度到污点的节点
  containers:
 - name: pod-toleration
    image: gcr.io/google_containers/pause:2.0

容忍的第二种写法:

tolerations:
 - key: "key"	         #key和effect需要和Taint(污点)的设置一致
  operator: "Exists"    #operator的值为Exists,则无需指定value
  effect: "NoSchedule"	 #key和effect需要和Taint(污点)的设置一致

注意:

  • 空的key配合Exists操作符可以匹配所有的键和值
  • 空的effect匹配所有的effect

一个node拥有多个污点的时候,k8s调度器会忽略pod配置中容忍的污点,其他不能容忍的就是最终的效果。

Pod Priority Preemption: Pod优先级调度

场景:节点因为负载过高导致节点上的pod驱逐(Eviction),那么pod就会抢占(preemption)资源不被驱逐。设置优先级会使优先级高的pod不被驱逐,只会驱逐优先级低的pod,来保全优先级高的pod。

首先创建PriorityClass(优先级类别),且PriorityClass不属于任何namespace。

apiVersion: scheduling.k8s.io/v1beta1
kind: PriorityClass
metadata:
  name: high-priority	#优先级类别的名字为high-priority
value: 1000000		#优先级为1000000,数字越大,优先级越高,十亿以上的为系统保留。
globalDefault: false
description: "This priority class should be used for XYZ service pods only."

pod配置文件引用优先级类别:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  priorityClassName: high-priority	#引用优先级类别名字为high-priority

DaemonSet:在每个Node上都调度一个Pod

场景案例:

  • 每个node上都要运行一个Ceph存储进程
  • 每个node上都要运行一个日志采集程序,例如Logstach。
  • 每个node上都要运行一个性能监控程序,例如prometheus。

pod案例:在每个节点都启动一个fluentd容器

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: fluentd-cloud-logging
  namespace: kube-system
  labels:
    k8s-app: fluentd-cloud-logging
spec:
  template:
    metadata:
      namespace: kube-system
      labels:
        k8s-app: fluentd-cloud-logging
    spec:
      containers:
      - name: fluentd-cloud-logging
        image: gcr.io/google_containers/fluentd-elasticsearch:1.17
        resources:
          limits:
            cpu: 100m
            memory: 200Mi
        env:
        - name: FLUENTD_ARGS
          value: -q
        volumeMounts:
        - name: varlog
          mountPath: /var/log
          readOnly: false
        - name: containers
          mountPath: /var/lib/docker/containers
          readOnly: false
      volumes:
      - name: containers
        hostPath:
          path: /var/lib/docker/containers
      - name: varlog
        hostPath:
          path: /var/log

你可能感兴趣的:(kubernetes,docker,运维,linux,devops)