阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

为Docker Swarm添加调度策略

156次阅读
没有评论

共计 4905 个字符,预计需要花费 13 分钟才能阅读完成。

Swarm 简介

Swarm 是 Docker 的一个集群管理工具,最开始仅仅是用作集群管理以及简单的调度,就像下面的图所示的,为 Docker Client 提供与 Docker Engine 一样的 Docker API,客户端操作 Swarm 就好像在操作一台机器,实际上后面连了好多 Docker Engine,容器都跑在后面的 Docker Engine 上。Swarm 负责将客户端的请求分配到后端的 Docker Engine,比如客户端要求启动一个容器,Swarm 找一个目前资源使用最少的 Docker Engine。

为 Docker Swarm 添加调度策略

因此早期的 Swarm 比较底层,有点像虚拟机管理器,抽象程度低。而 Kubernetes(Google 开源的容器管理工具)抽象了很多概念,比如 Service,Pod 等,更上层,稍微一封装就可以做成一个 PaaS 了。为了对抗 Kubernetes,Docker 也对 Swarm 做了升级改造,先是 SwarmKit,抽象了 Service,Task 等,然后又把 Swarmkit 集成到了 Docker Engine 中,可以使用 docker 命令把一个结点设为 swarm mode,然后这个结点就成了 swarm 集群的一个结点。因此最新的 Swarm 不再是一个工具,而是一个集群,我们把集群称作 Swarm,然后这个集群里面有 manager 和 worker 两种角色,manager 中有一个 leader,通过 Raft 算法实现数据一致性。总之很多方面都抄了 Kubernetes。

为 Docker Swarm 添加调度策略

可以在 Swarm 集群中创建 Service,而一个 Service 有多个实例,比如我创建一个 tomcat 的 Service,名字是 tomcat_service,使用的镜像是 tomcat,然后创建 3 个实例,也就是启动 3 个容器,用下面的命令:

docker service create –name tomcat_service  –replicas 3 tomcat

在 manager 上执行这个命令,manager 会把 3 个容器按调度策略分配到不同的 worker 上(manager 也可以当做 worker)。

swarm 的调度策略是:在满足 constraint 的 worker 中找一个 task(也就是容器数)最少的结点,这种策略叫做 spread 策略,就是尽可能的把 task 平均分布到不同结点。constraint 是指一些必须满足的条件,比如某个 task 要求分配 2G 内存。

spread 策略是没问题的,但是 swarm 在调度的时候没有把一项很重要的内容加进去,那就是实例的容灾。

我搭了一个 3 个结点的 Swarm 集群,manager1,worker1 和 worker2,创建了一个 hello 服务,有 4 个 replica,一个 world 服务,有 2 个 replica,如下:

为 Docker Swarm 添加调度策略

看上去 3 个结点每个结点两个 replica,挺好的,但是有一个严重的问题,world 服务的两个 replica 被调度到同一台主机上,那么这台主机挂了,整个服务就挂了。其实 replica 的概念就是要在多个地方存放,以防止单主机出现问题导致服务不可用。比如 HDFS 的 3 个 replica 一般要放到不同机器上,甚至还要考虑不同机柜,不同机房。Kubernetes 在调度的时候也考虑了多个 replica 放到多台主机上的策略。docker 的开发人员目前只忙着出产品,没功夫去精雕细琢细节到地方,不过多个 replica 放到不同主机之后肯定是会加进去的。

本文介绍如何修改 Docker 1.12 的代码把 replica 容灾的策略加到 Swarm 调度策略中。

Swarm 调度算法介绍

老的 Swarm 调度算法可以用下面的图表示:

为 Docker Swarm 添加调度策略

1. 一个调度请求过来,里面包含很多 constraint,比如需要分配 4G 内存,或者要求必须调度上含有 production 标签的结点上,或者要求某个结点没有被占用。

2. 所有的结点作为一个 List 传到一个 filter 链里,这个 filter 会过滤掉不符合条件的结点,比如内存不够,输出一个符合条件的结点 List

3. 按照策略进行排序,排名最高的就是要调度的结点

策略有三个:

spread: 默认策略,尽量均匀分布,找容器数少的结点调度

binpack: 和 spread 相反,尽量把一个结点占满再用其他结点

random: 随机

老的 Swarm 没有 replica 的概念,每个实例都是独立的个体,所以不需要在调度的时候考虑多副本部署到不同主机。新的 Swarm 调度算法和老 Swarm 差不多,不过不再提供策略选择,只提供了 spread 策略。

新的 Swarm 把结点信息放到一个堆里(堆排序的堆),以当前结点上的容器数为建堆的标准建一个最小堆,这样查找起来就特别快了。

为 Docker Swarm 添加调度策略

代码改造

改造策略

最优解:对于一个 task,找到的结点应该不含与这个 task 属于同一个 service 的 task,同时这个结点在符合这个条件的结点中 task 数最少。

次优解:所有满足硬性 constraint 的结点都启动了与这个 task 属于同一个 service 的 task,只能在这其中找一个 task 数最少的了。

代码修改

修改两个源文件就可以

修改代码 docker/vendor/src/github.com/docker/swarmkit/manager/scheduler/indexed_node_heap.go

1. 添加一个函数,定义一个 constraint 称为 multihostConstraint,意思是同一个 service 的不同副本要落到不同主机上,与其它强制性的 constraint 不一样,这个是尽量满足的 constraint

// 检查某个结点是否已经存在属于同一个 service 的 task
func meetMultihosConstraint(nodeInfo *NodeInfo, serviceID string) bool {
    for _, task := range nodeInfo.Tasks {
        sID = task.ServiceID
        if sID == serviceID {
            return false
        }
    }
    return true
}

2. 修改搜索 nodeHeap 的函数 searchHeapToFindMin,加一个参数 serviceID

func (nh *nodeHeap) searchHeapToFindMin(
    meetsConstraints func(*NodeInfo) bool,
    serviceID string)
            (*api.Node, int) {
    var bestNode *api.Node  // 满足 multihostConstraint 同时 task 最少的结点
    var secondBestNode *api.Node // 没有满足 multihostConstraint 的,只能选一个 task 最少的结点
    minTasks := int(^uint(0) >> 1) // max int
    secondMinTasks := minTasks
 
    if nh == nil || len(nh.heap) == 0 {
        return bestNode, minTasks
    }
 
    // push root to stack for search
    stack := []int{0}
 
    for len(stack) != 0 {
        // pop an element
        idx := stack[len(stack)-1]
        stack = stack[0 : len(stack)-1]
        heapEntry := &nh.heap[idx]
        if len(heapEntry.Tasks) >= minTasks {
            continue
        }
 
        if meetsConstraints(heapEntry) {
 
            // 满足强制性 constraint,再检查是否满足 multihostConstraint
            if meetMultihosConstraint(heapEntry, serviceID) == true {
                bestNode = heapEntry.Node
                minTasks = len(heapEntry.Tasks)
            } else {
                if(len(heapEntry.Tasks) < secondMinTasks) {
                    secondBestNode = heapEntry.Node
                    secondMinTasks = len(heapEntry.Tasks)
                }
            }
        } else {
            // otherwise, push 2 children to stack for further search
            if 2*idx+1 < len(nh.heap) {
                stack = append(stack, 2*idx+1)
            }
            if 2*idx+2 < len(nh.heap) {
                stack = append(stack, 2*idx+2)
            }
        }
    }
 
    if bestNode == nil {
        bestNode = secondBestNode
        minTasks = secondMinTasks
    }
 
    return bestNode, minTasks
 
}

修改代码 docker/vendor/src/github.com/docker/swarmkit/manager/scheduler/scheduler.go 里的 scheduleTask 函数

// scheduleTask schedules a single task.
func (s *Scheduler) scheduleTask(ctx context.Context, t *api.Task) *api.Task {
 s.pipeline.SetTask(t)
 // 这个函数直接改成 searchHeapToFindMin
 //s.scanAllNodes 是是否扫描全部结点的标志,直接改成 false
 //n, _ := s.nodeHeap.findMin(s.pipeline.Process, s.scanAllNodes)
 n,_  := s.nodeHeap.searchHeapToFindMin(s.pipeline.Process, false, t.ServiceID)

更多 Docker 相关教程见以下内容

Docker 安装应用(CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm

Ubuntu 14.04 安装 Docker  http://www.linuxidc.com/linux/2014-08/105656.htm

Ubuntu 使用 VNC 运行基于 Docker 的桌面系统  http://www.linuxidc.com/Linux/2015-08/121170.htm

Docker 开发平台的构建  http://www.linuxidc.com/Linux/2017-03/141592.htm

Ubuntu 15.04 下安装 Docker  http://www.linuxidc.com/Linux/2015-07/120444.htm

在 Ubuntu Trusty 14.04 (LTS) (64-bit)安装 Docker http://www.linuxidc.com/Linux/2014-10/108184.htm

在 Ubuntu 15.04 上如何安装 Docker 及基本用法 http://www.linuxidc.com/Linux/2015-09/122885.htm

Ubuntu 16.04 上 Docker 使用手记 http://www.linuxidc.com/Linux/2016-12/138490.htm

Docker 的详细介绍:请点这里
Docker 的下载地址:请点这里

本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-03/141721.htm

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-21发表,共计4905字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中