kubernetes云原生纪元:一次性搞懂Scheduler 服务调度(上)


kubenetes通过我们定义的Deployment 配置文件把我们的服务运行在合适的节点上,kubenetes有很多个work节点他是如何选中其中的一个,把我们的pod调度到上面的呢?

这就我们就主要说下pod的调度策略,预选,优选等等…

scheduler 架构

首先从scheduler 架构说起…

前奏

首先有一个etcd 原数据存放中心,然后还有一个apiServer (中枢)跟etcd 交互,获取元数据信息。大框框就是scheduler,首先来说scheduler来调度哪个pod,pod 信息那里来?scheduler里面有一个优先级队列,优先级高的就会提前出队,提前被调度。

虽然有了队列但是谁往里放消息呢,那就是informer通知者,他会 通过apiServer 监听ETCD的数据变化。比如说他会发现有个新增的pod,新增的pod和原有的pod的会少spec: nodeName一个节点的名字。查看下就知道了image-20200120105522229

image-20200120105611015

下有个

image-20200120105648667

他只有被scheduler 调度之后才会在哪个节点上才会把这个字段加上去

这informer就一直在持续监听,然后把pod 信息放到优先级队列里面。

​ 然后scheduler 从优先级队列里面拿去pod 信息调度到对应节点,但是想要调度还得知道节点信息,scheduler里面还有一个模块就是cache缓存 他会从apiServer 拿到想要的数据(节点列表信息、对应每个节点的详细信息cpu、磁盘空间、内存、节点镜像、运行pod,pod详细信息)缓存到cache。

​ pod数据和节点数据都有了,下面就可以进行调度了。调度过程分为两部分,

调度过程
  • 预选策略(Predicate)

第一步初步过滤不符合需求的节点----预选策略(Predicate)包括剩余的内存、CPU、端口检查、挂在的数据卷类型必须匹配、nodeSeletor规则匹配、节点状态pod亲和性反亲和性、污点都要满足需求等等…总之预选就是找到不满足要求的节点把它们统统排除掉,剩下都是可以的调度的节点 。

  • 优选策略(Priority)

进入第二步优选策略(Priority)对我们上一步筛选的node节点进行评分,评分要各个项,CPU 内存,Deployment下pod是否调度等等…对每个进行计算最终会对每个节点进行评分,选出最高分的node,作为我们最终要调度的节点。

最后scheduler要把pod和node做banging绑定关系,然后把绑定信息告诉apiServer,apiServer更新spec:nodeName字段,然后指派给具体节点的kubelet,就会把这个服务调度起来了。大致调度流程就是这样。

image-20200120112613979

之前我们在节点定义标签disktype=ssd 就是在预选策略这里完成的。

自定义配置

1. 节点亲和性

节点亲和性很容易理解,意思就是根据亲和性策略选着出合适的节点,在对应的节点上进行创建服务调度

配置
  • affinity: #亲和性

  • nodeAffinity: #节点亲和性 pod 跟节点亲和性的关系

  • requiredDuringSchedulingIgnoredDuringExecution: #必须 满足下面的条件才能满足

  • nodeSelectorTerms: #

  • matchExpressions: #匹配表达式

  • key: beta.kubernetes.o/arch # 节点label的名字
    operator: In #操作
    values: #匹配的值可以是数组

    ​ amd64 #也就是所这个pod需要运行在CPU架构所amd64的架构上

  • preferredDuringSchedulingIgnoredDuringExecution: #最好可以满足下面条件,不是必须👆上面的所必须

  • weight: 1 # 权重 这里也是可以配置多个

  • preference:
    matchExpressions: #匹配表达式 下面条件的意思disktype 不包括 ssd的
    - key: disktype
    operator: NotIn
    values:

             ssd
    

    注意:这里可以有多个matchExpressions ,多个存在是并且的关系,同时都要满足。如果要或的关系我就要定义多个nodeSelectorTerms

基本配置:

 affinity: #亲和性
        nodeAffinity: #节点亲和性  pod 跟节点亲和性的关系
         	 requiredDuringSchedulingIgnoredDuringExecution: #必须 满足下面的条件才能满足
            nodeSelectorTerms: #
              - matchExpressions: #匹配表达式 这里可以有多个matchExpressions ,如果多个存在是并且的关系同时都要满足,如果要或的关系我就要定义多个nodeSelectorTerms
                  - key: beta.kubernetes.io/arch # 节点label的名字
                    operator: In #操作
                    values: #匹配的值可以是数组
                      - amd64  #也就是所这个pod需要运行在CPU架构所amd64的架构上
          preferredDuringSchedulingIgnoredDuringExecution: # 最好可以满足下面条件,不是必须👆上面的所必须
            - weight: 1 # 权重 这里也是可以配置多个
              preference:
                matchExpressions: #匹配表达式 下面条件的意思disktype 不包括 ssd的
                  - key: disktype
                    operator: NotIn
                    values:
                      - ssd

查看下我们node节点的标签是否有beta.kubernetes.io/arch:amd64

[root@master-001 ~]# kubectl get nodes node-001 -o yaml
image-20200120141000610

在配置中使用:

Web-dev-node.yaml

#deploy
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-demo
  namespace: dev
spec:
  selector:
    matchLabels:
      app: web-demo
  replicas: 1
  template:
    metadata:
      labels:
        app: web-demo
    spec:
      containers:
        - name: web-demo
          image: hub.zhang.com/kubernetes/demo:2020011512381579063123
          ports:
            - containerPort: 8080
      # 使用如下
      affinity:
        nodeAffinity: 
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms: 
              - matchExpressions: 
                  - key: beta.kubernetes.io/arch 
                    operator: In 
                    values: 
                      - amd64  
          preferredDuringSchedulingIgnoredDuringExecution: 
            - weight: 1 
              preference:
                matchExpressions: 
                  - key: disktype
                    operator: NotIn
                    values:
                      - ssd
            #end
---
#service
apiVersion: v1
kind: Service
metadata:
  name: web-demo
  namespace: dev
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 8080
  selector:
    app: web-demo
  type: ClusterIP

---
#ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: web-demo
  namespace: dev
spec:
  rules:
    - host: web.demo.com
      http:
        paths:
          - path: /
            backend:
              serviceName: web-demo
              servicePort: 80

创建下

[root@master-001 ~]# kubectl apply -f web-dev-node.yaml -n dev

查看下 他被创建在120上,因为121有个标签是disktype=ssd ,而我们定义的配置有``disktype Not In ssd`条件,所以它被创建到120上了

image-20200120143948044

而且我们把必须满足matchExpressions: key: beta.kubernetes.io/arch operator: In values:amd64 改成values:amd那就创建不成功了,因为没有满足这个条件的节点

image-20200120144344173

image-20200120144428965

把最好preferred 条件改成

image-20200120144628872

发现依然可以创建成功,由此看出没有满足preferred的条件也是没关系。

image-20200120144651067

未完结…

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐