乐趣区

关于kubernetes:Kubernetes集群调度

简介

Scheduler 是 kubernetes 的调度器,次要的工作是把定义的 pod 调配到集群的节点上。听起来非常简单,但有很多要思考的问题:

  • 偏心:如何保障每个节点都能被分配资源
  • 资源高效利用:集群所有资源最大化被应用
  • 效率:调度的性能要好,可能尽快地对大批量的 pod 实现调度工作
  • 灵便:容许用户依据本人的需要管制调度的逻辑

Sheduler 是作为独自的程序运行的,启动之后会始终坚挺 API Server,获取 PodSpec.NodeName 为空的 pod,对每个 pod 都会创立一个 binding,表明该 pod 应该放到哪个节点上

调度过程

调度分为几个局部:首先是过滤掉不满足条件的节点,这个过程称为 predicate;而后对通过的节点依照优先级排序,这个是 priority;最初从中抉择优先级最高的节点。如果两头任何一步骤有谬误,就间接返回谬误

Predicate 有一系列的算法能够应用:

  • PodFitsResources:节点上残余的资源是否大于 pod 申请的资源
  • PodFitsHost:如果 pod 指定了 NodeName,查看节点名称是否和 NodeName 匹配
  • PodFitsHostPorts:节点上曾经应用的 port 是否和 pod 申请的 port 抵触
  • PodSelectorMatches:过滤掉和 pod 指定的 label 不匹配的节点
  • NoDiskConflict:曾经 mount 的 volume 和 pod 指定的 volume 不抵触,除非它们都是只读

如果在 predicate 过程中没有适合的节点,pod 会始终在 pending 状态,一直重试调度,直到有节点满足条件。通过这个步骤,如果有多个节点满足条件,就持续 priorities 过程:依照优先级大小对节点排序

优先级由一系列键值对组成,键是该优先级项的名称,值是它的权重(该项的重要性)。这些优先级选项包含:

  • LeastRequestedPriority:通过计算 CPU 和 Memory 的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标偏向于资源应用比例更低的节点
  • BalancedResourceAllocation:节点上 CPU 和 Memory 使用率越靠近,权重越高。这个应该和下面的一起应用,不应该独自应用
  • ImageLocalityPriority:偏向于曾经有要应用镜像的节点,镜像总大小值越大,权重越高

通过算法对所有的优先级我的项目和权重进行计算,得出最终的后果

自定义调度器

除了 kubernetes 自带的调度器,你也能够编写本人的调度器。通过 spec:schedulername 参数指定调度器的名字,能够为 pod 抉择某个调度器进行调度。比方上面的 pod 抉择 my-scheduler 进行调度,而不是默认的 default-scheduler:

apiVersion: v1
kind: Pod
metadata:
  name: annotation-second-scheduler
  labels: 
    name: multischeduler-example
spec:
  schedulername: my-scheduler
  containers:
  - name: pod-with-second-annotation-container
    image: gcr.io/google_containers/pause:2.0

Node 亲和性

pod.spec.nodeAfinity

  • preferredDuringSchedulingIgnoredDuringExecution:软策略
  • requiredDuringSchedulingIgnoredDuringExecution:硬策略

requiredDuringSchedulingIgnoredDuringExecution

apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels: 
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: NotIn
            values:
            - k8s-node02

preferredDuringSchedulingIgnoredDuringExecution

apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: myapp:v1
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: source
            operator: In
            values: 
            - qikqiak

混合应用

apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
          - key: kubernetes.io/hostname
            operator: NotIn
            values:
            - k8s-node02
      preferredDuringSchedulingIgnoredDuringExecution:
      -  weight: 1
         preference:
           matchExpressions:
           - key: source
             operator: In
             values:
             - qikqiak

键值运算关系

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Gt:label 的值大于某个值
  • Lt:label 的值小于某个值
  • Exists:某个 label 存在
  • DoesNotExist:某个 label 不存在

Pod 亲和性

pod.spec.afinity.podAfinity/podAntiAfinity

  • preferredDuringSchedulingIgnoredDuringExecution:软策略
  • requiredDuringSchedulingIgnoredDuringExecution:硬策略
apiVersion: v1
kind: Pod
metadata:
  name: pod-3
  labels:
    app: pod-3
spec:
  containers:
  - name: pod-3
    image: myapp:v1
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
        matchExpressions:
        - key: app
          operator: In
          values: 
          - pod-1
        topologyKey: kubernetes.io/hostname
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values: 
              - pod-2
          topologyKey: kubernetes.io/hostname

亲和性 / 反亲和性调度策略比拟如下:

调度策略 匹配标签 操作符 拓扑域反对 调度指标
nodeAfinity 主机 In, NotIn, Exists,DoesNotExist, Gt, Lt 指定主机
podAfinity POD In, NotIn, Exists,DoesNotExist POD 与指定 POD 同一拓扑域
podAnitAfinity POD In, NotIn, Exists,DoesNotExist POD 与指定 POD 不在同一拓扑域

Taint 和 Toleration

节点亲和性,是 pod 的一种属性(偏好或硬性要求),它使 pod 被吸引到一类特定的节点。Taint 则相同,它使节点可能排挤一类特定的 pod

Taint 和 toleration 相互配合,能够用来防止 pod 被调配到不适合的节点上。每个节点上都能够利用一个或多个 taint,这示意对于那些不能容忍这些 taint 的 pod,是不会被该节点承受的。如果将 toleration 利用于 pod 上,则示意这些 pod 能够(但不要求)被调度到具备匹配 taint 的节点上

污点(Taint)

Ⅰ、污点 (Taint) 的组成

应用 kubectltaint 命令能够给某个 Node 节点设置污点,Node 被设置上污点之后就和 Pod 之间存在了一种相斥的关系,能够让 Node 回绝 Pod 的调度执行,甚至将 Node 曾经存在的 Pod 驱赶进来

每个污点的组成如下:

key=value:effect

每个污点有一个 key 和 value 作为污点的标签,其中 value 能够为空,efect 形容污点的作用。以后 taintefect 反对如下三个选项:

  • NoSchedule:示意 k8s 将不会将 Pod 调度到具备该污点的 Node 上
  • PreferNoSchedule:示意 k8s 将尽量避免将 Pod 调度到具备该污点的 Node 上
  • NoExecute:示意 k8s 将不会将 Pod 调度到具备该污点的 Node 上,同时会将 Node 上曾经存在的 Pod 驱赶进来

Ⅱ、污点的设置、查看和去除

# 设置污点
kubectl taint nodes node1 key1=value1:NoSchedule
#节点阐明中,查找 Taints 字段
kubectl describe pod pod-name
#去除污点
kubectl taint nodes node1 key1:NoSchedule-

容忍(Tolerations)

设置了污点的 Node 将依据 taint 的 efect:NoSchedule、PreferNoSchedule、NoExecute 和 Pod 之间产生互斥的关系,Pod 将在肯定水平上不会被调度到 Node 上。但咱们能够在 Pod 上设置容忍(Toleration),意思是设置了容忍的 Pod 将能够容忍污点的存在,能够被调度到存在污点的 Node 上

pod.spec.tolerations

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
  tolerationSeconds: 3600
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
- key: "key2"
  operator: "Exists"
  effect: "NoSchedule"
  • 其中 key, vaule, efect 要与 Node 上设置的 taint 保持一致
  • operator 的值为 Exists 将会疏忽 value 值
  • tolerationSeconds 用于形容当 Pod 须要被驱赶时能够在 Pod 上持续保留运行的工夫

Ⅰ、当不指定 key 值时,示意容忍所有的污点 key:

tolerations:
- operator: "Exists"

Ⅱ、当不指定 efect 值时,示意容忍所有的污点作用

tolerations:
- key: "key"
  operator: "Exists"

Ⅲ、有多个 Master 存在时,避免资源节约,能够如下设置

kubectl taint nodes Node-Name node-role.kubernetes.io/master=:PreferNoSchedule

指定调度节点

Ⅰ、Pod.spec.nodeName 将 Pod 间接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该匹配规定是强制匹配

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: myweb
spec:
  replicas: 7
  template:
    metadata: 
      labels:
        app: myweb
    spec:
      nodeName: k8s-node01
      containers:
      - name: myweb
        image: myapp:v1
        ports:
        - containerPort: 80

Ⅱ、Pod.spec.nodeSelector:通过 kubernetes 的 label-selector 机制抉择节点,由调度器调度策略匹配 label,而后调度 Pod 到指标节点,该匹配规定属于强制束缚

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: myweb
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: myweb
    spec:
      nodeSelector:
        type: backEndNode1
      containers:
      - name: myweb
        image: harbor/tomcat:8.5-jre8
        ports:
        - containerPort: 80
退出移动版