Kubernetes Scheduler 的作用是将待调度的 Pod 按照一定的调度算法和策略绑定到集群中一个合适的 Worker Node(以下简称 Node) 上,并将绑定信息写入到 etcd 中,之后目标 Node 中 kubelet 服务通过 API Server 监听到 Scheduler 产生的 Pod 绑定事件获取 Pod 信息,然后下载镜像启动容器
从步骤上分为两步:
- 预选,K8S会遍历当前集群中的所有 Node,筛选出其中符合要求的 Node 作为候选
- 优选,K8S将对候选的 Node 进行打分
当我在试着理解这两个步骤的过程中,我不禁问了自己一个问题:如果没有k8s这种容器编排系统,也没有docker, 同样也面临着大规模服务部署,应该怎么做?
假设开发使用java完成了服务fun开发工作,然后将fun打成jar包扔给我部署(传统部署常规操作),我只有有限的物理机,这些物理机上也零散的部署了其它服务,这个时候我会想一个问题:我应该将这个服务部署在哪台机器上?
首先能想到的是找资源最空闲的机器,资源包括:
- CPU
- 内存
- 硬盘
...
也就是收集各物理机的可用资源进行编译,如(cpu+内存+硬盘)
- s1: 2cpu+2G+20G
- s2: 1cpu+3G+10G
- s3: 5cpu+1G+200G
...
假设服务fun需要的资源是:0.2cpu+0.5G+1G,很显然,前3台机器都可以满足需求,那为了保险起见,剩余可用资源当然是越多越好,那现在这种看似都可选的情况该如何是好呢?我能想的是排序,根据什么排序?权重,fun对资源的依赖也有权重的,比如权重由大到小的排序是 cpu->内存->硬盘, 权值分别为:3,2,1
根据加权得到的结果是:
- s1: 2cpu+2G+20G -> 23+22+20=30
- s2: 1cpu+3G+10G -> 13+32+10=19
- s3: 5cpu+1G+200G -> 53+12+200=217
...
从我们定义的权重规则计算得到的结果看s3得分最高,所以目前s3是最佳选择
这里可能存在一个问题,就是比如我有1w台机器,那就需要获取这1w台机器的可用cpu、可用内存、可用硬盘,然后加权,排序,取得分最高的机器,假设每台机器获取可用资源用时:1ms,那1w台就需要10s, 这是相当可观的时间,假如最后的结果只有s1,s2,s3满足条件,也就是说剩余的9997台机器是不符合需求的,这基本上最差的情况的,此时应该如何?寻求局部最优解
- 全局最优: 1w台机器里面加权后得分最高的机器
- 局部最优: 前10台机器里面加权后得分最高的机器
如果需要高可用部署,我们往往需要部署多个服务实例,比如说3个fun,高可用是为了避免其中某个实例因意外比如宕机而引起服务不可用,那显然最好的方式是fun服务分别部署在三台不同的物理机上,也就是说fun服务的三个实例在物理机上部署是互斥的。
再比如:fun服务需要强依赖服务dp,从通信角度讲,本机通信显然要比跨主机通讯要快也更稳定,所以此时我更倾向于将fun与dp部署在一台主机上。
在了解k8s的调度器之前我不会想到这些问题,初步了解之后,就有些先入为主了,k8s的调度所做的事情,在传统运维部署的过程中,同样也会遇到,或许也是这样做的,所以会想到一个问题?k8s到底解决了什么问题?
首先k8s肯定解决了调度问题?上述的fun服务往往不是孤单的,它需要依赖服务dp,同样其它服务也需要依赖fun,就依赖就需要知道服务地址,那就需要服务发现了?k8s有coredns;需要将fun服务暴露到k8s集群外?没问题,k8s有ingress,在k8s之前,nginx在做着同样的事情; 需要统一日志进行分析?可以接入nfs/ceph (当然,用没用k8s都可以接入这两个文件系统)......
乍一看,k8s似乎没有解决新的问题?我的感觉,k8s解决的最大问题是:物理无关(怎么想起与女无瓜这个梗)。就是说我不需要关注物理机器了,我不需要关心我的服务部署在哪台真实的物理机器/ecs上,我的部署与调度都是基于资源来进行的,我只知道有这个集群可以部署服务即可,至于这个集群是怎么保持可用性的、怎么扩展的、机器状况如何,我不关心,当然这需要云计算的支持,我认为这也是为什么k8s会与云原生紧密结合的原因,没有了云计算,k8s的威力会大打折扣。
经过这一番自我解读,我好像有点了解到IAAS,k8s是作为基础设施存在的,为了用好这个基础设施,我们还需要搭建一个PAAS,比如Rancher在这块就做的很好。
通过调度功能来思考k8s设计的原因,当然我理解的并非全部,过程相当有意思,谈不上抽丝剥茧,不过k8s确实做了很多事情,目前看做的还很好。
Refer: