吾家Swan初长成|数人云Mesos开源调度器
去年11月,数人云发布并开源了Mesos调度器Swan。Swan是基于Mesos HTTP API编写的基于Docker的long running应用调度框架,针对企业IT环境设计,同时解决应用调度、服务发现和负载均衡等生产环境运行时的核心问题。让我们来看看近期Swan的动态吧:)
关 于“调 度”
“调度”这个词近两年被提到的比较多。“调度”产品五花八门,主流第一个是Mesos,第二个是K8S,当然新兴的Swarmkit也非常好用、非常流行。这些调度产品各具特色,也有共通之处:
1. 对硬件资源的抽象
以前关注硬件资源,比如部署应用,需要找运维要机器,机器配置和型号列出来,但是现在有了调度平台,可能更关注的是应用实际需要的资源比如CPU和内存,硬件资源应该由调度器去管而不是应用程序去管,应用程序只负责申请和使用资源,调度平台会处理应用故障后的重新调度。
2. 对软件上层应用生命周期的管理
资源调度器把应用发下去,管理应用生命周期,检查应用是否健康以及应用的动态更新,以上都是调度需要做的事情。
关 于“初 衷”
为什么要选择自研调度器组件?实践容器技术对容器编排调度的要求很高,数人云希望帮助企业统一管理资源和应用,而应用全生命周期管理中的重中之重就是应用调度。
众所周知,在Google的云计算IT架构体系中,PaaS平台非常强大,其管理了Google内部数十亿应用程序,并运行在上百万台服务器上。Google PaaS的工具层,即数据中心操作系统,包括应用调度、日志检索、监控报警、测试打包、应用发布、镜像仓库等等。其中的核心就是调度器Borg,所有的业务应用程序都被Borg统一调度统一运行在Google所有的数据中心里,并实现应用的全生命周期管理。因此,在深入研究了Google Borg之后,我们决定做一款轻量级容器编排调度引擎。
Swan的设计目标主要有几点,可以跑长服务任务,重新设计容器编排,实现滚动更新和升级等。通过GitHub,Swan在过去的四个月中,收到了很多朋友对此项目的技术探讨和反馈。
最 初 功 能
Swan最初实现的功能,包括:
应用增删改查、自动恢复,兼容Marathon API;
实现应用与实例的统一命名并保持应用的实例名称恒定不变;
实现健康检查;
保存配置文件以支持回滚;
可配置优雅终止;
自动滚动更新策略;
应用状态历史记录。
最 新 功 能
Swan增加了很多新的功能,包括:
7层服务发现、负载均衡;
一容器一固定IP;
启动时手动指定容器IP;
7层应用基于Mesos做健康检查;
基于Mesos标签支持Constrains;
调度器高可用;
与数人云PaaS平台对接;
各核心模块只读UI。
未来还会加入抢占、配额、网络分流限流等高级功能,敬请期待。
动 手 写 Mesos Framework
简单讲讲如何写一个Mesos Framework:
第一步:注册
作为一个Mesos Framework首先要做的第一件事就是向Mesos Master注册自己,只有完成了注册,才能使用Mesos的资源。可以通过mesos-go包来写调度器,也可以自己写,这里采用第二种方式。
首先定义一个调度器结构体,包含一些必要的参数(属性):
type Scheduler struct {
master string
framework *mesos.FrameworkInfo
client *client.Client
doneChan chan struct{}
events Events
// Status indicated scheduler's state is idle or busy.
Status string
}
Master需要连接的Mesos Master地址,包括IP和端口,例如:192.168.1.118:5050
Framework是一个Mesos自定义的结构体。
f := &mesos.FrameworkInfo{
User: proto.String(user),
Name: proto.String("swan"),
Hostname: proto.String(hostname),
FailoverTimeout: proto.Float64(60 * 60 * 24 * 7),
}
client是一个http client,通过它向Mesos发送消息。
doneChan通过一个channel来控制调度器退出。
events是一个map,收集Mesos回传给调度器的事件。
status标示调度器是繁忙还是空闲状态。
讲完了定义再讲如何初始化一个调度器,示例代码如下:
// NewScheduler returns a pointer to new Scheduler
func NewScheduler(master string, fw *mesos.FrameworkInfo) *Scheduler {
return &Scheduler{
master: master,
client: client.New(master, "/api/v1/scheduler"),
framework: fw,
doneChan: make(chan struct{}),
events: Events{
sched.Event_OFFERS: make(chan *sched.Event, 64),
},
Status: "idle",
}
}
有了调度器对象,接下来看它如何去Mesos注册,示例代码如下:
// Subscribe subscribes the scheduler to the Mesos cluster.
// It keeps the http connection opens with the Master to stream
// subsequent events.
func (s *Scheduler) subscribe() error {
logrus.Infof("Subscribe with mesos master %s", s.master)
call := &sched.Call{
Type: sched.Call_SUBSCRIBE.Enum(),
Subscribe: &sched.Call_Subscribe{
FrameworkInfo: s.framework,
},
}
if s.framework.Id != nil {
call.FrameworkId = &mesos.FrameworkID{
Value: proto.String(s.framework.Id.GetValue()),
}
}
resp, err := s.send(call)、
if err != nil {
return err
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("Subscribe with unexpected response status: %d", resp.StatusCode)
}
logrus.Info(s.client.StreamID)
go s.handleEvents(resp)
return nil
}
调度器的subscribe()方法用来向Mesos注册,可以看到它是通过向Mesos Master的/api/v1/scheduler发送一个Call_SUBSCRIBE类型的Call来完成注册。
注册成功后会返回一个http长连接的resp,后续调取器和Mesos的通信都是通过这个长连接来进行的。
第一小节到此结束,后续会分享如何通过Mesos的资源offer来launch task,敬请期待。以上所讲的代码,可以在这里找到:https://github.com/Dataman-Cloud/swan.< 欢迎“阅读原文”Star&Fork >
相关阅读推荐:
由浅入深 | 如何优雅地写一个Mesos Framework
徐磊 | 从运维角度思考Mesos Framework的部署方式