最简单的启动Docker实例Mesos Golang Framework
工作了很长时间最近有时间第一次写,希望支持
如果大家了解Mesos,就知道Mesos是经典的两层调度,官网的架构图(http://mesos.apache.org/documentation/latest/mesos-architectur
大致的流程:
Mesos slave会向Mesos master汇报自己的空闲资源(CPU和Mem),
Mesos master作为全局资源调度器,将Mesos slave上的空闲资源通知给Framework, Framework可以分为scheduler和executor,scheduler向Mesos master注册以接入集群, Framework的scheduler回复Mesos master其所要调度的task及相应需要的资源,
Mesos slave在收到Mesos master分配的task后,则启动Framework的executor执行task。Mesos在0.20版本之后,对Docker提供了原生支持,Mesosslave可直接调度Docker实例。 Mesos的Framework已经很丰富了,参见http://mesos.apache.org/documentation/latest/mesos-frameworks/ 现在,Mesos也支持用Golang来开发自己的Framework了。
这里写个最简的Framework,使用Mesos slave来启动Docker实例,所以就省去了Framework的executor部分,只需写个scheduler就可以了。(代码已放置于https://github.com/chend h521/mesos-go/)
mesos-go(https://github.com/mesos/mesos-go)里提供了一个example,这里忽略executor,直接来看scheduler,我们主要需要完成sched uler的两个函数:
```
ResourceOffers(driver sched.SchedulerDriver, offers []*mesos.Offer) StatusUpdate(driver sched.SchedulerDriver, status *mesos.TaskStatus)
```
在ResourceOffers中,scheduler获取slave上的空闲资源,然后进行task调度。
在StatusUpdate中,会通知scheduler所调度的task的状态,并可相应地做出处理。
在ResourceOffers函数中,如果要调度Docker实例,需要指定容器类型、image、及网络模式, 可以在mesos-go/mesosproto/mesos.pb.go中看到相应容器类型及网络模式的类型定义:
```
// All container implementation types. type ContainerInfo_Type int32
const (
ContainerInfo_DOCKER ContainerInfo_Type = 1 ContainerInfo_MESOS ContainerInfo_Type = 2
)
```
```
// Network options.
type ContainerInfo_DockerInfo_Network int32 const (
ContainerInfo_DockerInfo_HOST ContainerInfo_DockerInfo_Network = 1 ContainerInfo_DockerInfo_BRIDGE ContainerInfo_DockerInfo_Network = 2 ContainerInfo_DockerInfo_NONE ContainerInfo_DockerInfo_Network = 3
)
```
这样,我们便可指定容器信息,然后启动相应的task:
// container info
networkInfo := mesos.ContainerInfo_DockerInfo_BRIDGE dockerInfo := &mesos.ContainerInfo_DockerInfo{ Image: &sched.imageName,
Network: &networkInfo,
}
typeInfo := mesos.ContainerInfo_DOCKER container := &mesos.ContainerInfo{ Type: &typeInfo,
Docker: dockerInfo,
}
shellBool := false
command := &mesos.CommandInfo{ Shell: &shellBool,
}
// schedule task to run task := &mesos.TaskInfo{
Name: proto.String("go-task-" + taskId.GetValue()), TaskId: taskId,
SlaveId: offer.SlaveId, Resources: []*mesos.Resource{
util.NewScalarResource("cpus", CPUS_PER_TASK), util.NewScalarResource("mem", MEM_PER_TASK),
},
Container: container, Command: command,
}
```
在StatusUpdate函数中,当task出现异常时(TASK_LOST,TASK_KILLED或TASK_FAILED),即Docker实例异常时,重新进行task调度:
```
// re-schedule task to run when task lost, killed or failed if status.GetState() == mesos.TaskState_TASK_LOST || status.GetState() == mesos.TaskState_TASK_KILLED || status.GetState() == mesos.TaskState_TASK_FAILED { log.Errorln(
"Task", status.TaskId.GetValue(),
"is in unexpected state", status.State.String(), "with message", status.GetMessage(),
)
sched.tasksLaunched--
}
```
编译,并尝试启动3个centos6:latest的Docker实例(需要提前部署Mesos), 并可尝试杀掉某个Docker实例进程,检查scheduler会重新进行调度:
```
cd $GOPATH/src/github.com/mesos/mesos-go/examples
go build -tags=example-sched -o example-scheduler example_scheduler.go
./example-scheduler --master=127.0.0.1:5050 --image=centos6:latest --task-count=3 --logtostderr=true
```
OK,到此就完成了这个最简单的启动Docker实例的MesosGolang Framework, 当然,你可能还想:
1) 让它支持弹性调度
2) 常驻侦听请求
3) 支持更丰富的调度策略
...
如果要用到生产环境,可能还要
1) 选择合适的网络模式(可能就需要为Framework写executor了)
2) 增加健康检查
...
Anyway,相信这些你都可以来实现。
如有需要,Marathon和Aurora是很好的参考 :) 参考:
http://java.dzone.com/articles/building-massively-scalable http://codefutures.com/mesos-docker-tutorial-how-to-build-your-own-framework/