kubernetes学习笔记-pod调度

一、Pod调度

1.1.调度的过程

kubernets是容器编排引擎,其中最主要的一个功能是容器的调度,通过kube-scheduler实现容器的完全自动化调度,pod调度就是指pod在哪个节点运行,这个调度的过程是如何进行的,其过程是这样的:
整个调度周期分为调度周期和绑定周期,调度周期又细分为filter和weigh称重,先根据调度策略过滤出满足pod运行的节点,然后对这些节点进行一个排序,绑定周期kube-scheduler调度优选的pod,由特定的node节点wantch后经kublet拉起

调度周期里的filter,该过滤阶段又包含两层,一是预选阶段,该阶段是筛选出满足pod运行的node,再一个是打分排序,给满足的pod运行的节点进行打分排序,这里面预选比较重要,预选的算法有以下一些:

  • CheckNodeConditionPred 节点是否Ready
    可以使用kubectl get nodes查看
  • MemoryPressure 节点内存是否足够
    kubectl describe node nodename查看Conditions字段下的信息
  • DiskPressure
  • PIDPressure
  • GeneralPred 匹配pod.spec.hostname字段
  • MatchNodeSelector 匹配pod.spec.bodeSelector标签
  • PodFitsResources 判断resource定义的资源是否满足
  • PodToleratesNodeTaints 能容忍的污点pod.spec.tolerations

以上是用来预选出节点的常用算法

选出满足的node后还需要进行进一步打分排序,看哪些节点更适合分配pod,这里所使用的算法有以下几种:

  • least_requested 资源消耗最少的节点
  • balanced_resource_allocation 各项资源消耗最均匀的节点
  • node_prefer_avoid_pods 节点倾向
  • taint_toleration 污点检测,检测到有污点条件的node,得分越低
  • selector_spreading 节点selector
  • interpod_affinity pod亲和力
  • most_requested 资源消耗最大节点
  • node_label node标签

1.2.通过nodeName来调度

通过nodeName调度pod的意思是分配指定的node给pod,这个是不需要经过kube-scheduler来调度的,不属于智能调度,直接跳过kube-scheduler在指定的节点上通过kubelet启动pod
cat nginx-nodeName.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx-run-on-nodename
  annotations:
    kubernetes.io/description: "Running the pod on specific nodeName"
spec:
  containers:
  - name: nginx-run-on-nodename
    image: nginx:1.7.9
    pors:
    - name: http-80-port
      protocol: TCP
      containerPort: 80
  nodeName: node-3 # 指定pod运行的节点   

kubectl apply -f nginx-nodeName.yaml
这里有一点需要注意,因为是指定调度,所以如果指定的节点上存在资源紧张,有可能造成pod被驱逐,因此这种调度的pod最好配置QOS类型为guaranteed,这种resources资源分配优先级别最高,可以防止因资源紧张pod被驱逐的风险

1.3.nodeSelector调度

这种方式是通过给节点创建一个key:value格式的label,然后在创建yaml的时候指定该label,这样就可以在调度的时候将pod分配给节点
比如给node-2添加一个label
kubectl label node node-2 app=web
kubectl get nodes --show-labels 验证
通过nodeSelector将pod调度到app=web所属的labels
cat nginx-nodeSelector.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx-run-on-nodeselector
  annotations: 
    kuberbetes.io/description: "Running the pod on specific by nodeSelector"
spec:
  containers:
  - name: nginx-run-on-nodeselector
    image: nginx:1.7.9
    ports:
    - name: http-80-port
      protocol: TCP
      containerPort: 80
  nodeSelector:
    app: web   # 通过nodeSelector将pod调度到特定的labels   

kubectl apply -f nginx-nodeSelector.yaml
除了自定义的标签需要手动创建外,还有一些内置的labels

  • kubernetes.io/os=linux
  • kubernetes.ip/hostname=node-3
  • kubernetes.io/arch=amd64
  • beta.kubernetes.io/arch=amd64
  • beta.kubernetes.io/os=linux

1.4.node Affinity与anti-affinity

affinity的功能其实和nodeSelector类似,把pod进行认为设置调度到想要去的node上,但是affinity功能更多,比如我们有多个节点具有相同的label,但是只需要将pod分配到其中某几个节点或者某一个节点,这个时候选择node affinity更适合
cat nginx-affinity.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx-run-node-affinity
  annotations:
    kubernetes.io/description: "Running the pod on specific node by node affinity"
spec:
  containers:
  - name: nginx-run-node-affinity
    image: nginx:1.7.9
    ports:
    - name: http-80-port
      protocol: TCP
      containerPort: 80
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - node-1
            - node-2
            - node-3
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: app
            operator: In
            values: ["web"]

kubect get pods -o wide
新创建的pod分配在node-2上,因为配置的affinity会调pod到有node-1、node-2、node-3上,但是从中会优选调度到有app=web标签的节点
除了node affinity外,还有node anti-affinity、pod affinity、pod anti-affinity

二、pod调度总结

kubernetes中的pod调度机制,默认创建的pod是全自动调度,由kube-scheduler实现,每一个pod的调度都分为调度阶段和绑定阶段,调度阶段有一个过滤和排序,但是有时候因为实际需求需要人为的去干预pod调度,这就需要以上介绍的几种调度方式了,主要有这四种:

  • nodeName
  • nodeSelector
  • node affinity与node anti-affinity
  • pod affinity与pod anti-affinity