Kubernetes(k8s) + Docker
, 跑起来如清风拂面, 顺畅无比。然而我们的业务机器大部分为centos 6.2, linux kernel 2.6的环境,而docker的运行需要Linux kernel的版本是 3.10+ (可参考: https://docs.docker.com/engine/faq/#how-do-i-connect-docker-containers)k8s
这条路走不通;Kubernetes(k8s) + Docker
, 我们还有mesos
;Mesos
就是用于整个计算中心的操作系统,它统一管理计算中心所有机器的cpu, memory, disk, network等计算资源,按任务所需分配资源,调度任务,支持故障转移等等;m2.png
Agent
上报自已的计算资源给Master
;Master
给各个二级调度框架Framework
发送resource offer
;Framework
将其上等待调度的task
与收到的resource offer
作匹配,反馈给Master
;Master
将相应Framework
反馈的task
和resource offer
发送到对应的Agent
;Agent
使用Executor
来运行task, 并限定资源使用;docker
容器技术,还提供了它自己的Mesos Containerizer, 这正是我们所需要的.其实Mesos Containerizer
目前也是利用Linux Cgroup
作资源限制, 用Linux namespace
作资源隔离.Mesos agent
在业务机器上需要非侵入式地部署,不能污染所部署的机器的环境;Mesos Agent
所能使用的计算资源;Task
的快速部署和资源隔离;mesos多任务调度.png
Mesos master
+ Mesos agent
;
1.2 二级调度框架使用的是Marathon;
1.3 在部署了Mesos agent
的机器上同时部署monitor
用于实时监控和调整Agent
的可用计算资源;Monitor
实时监控组件收集所在机器上的可用资源;Monitor
根据所在机器上的可用资源动态调整agent的保留资源;Agent
动态实时的将自已的保留资源上报到Mesos master
;Mesos Master
在resource offer发到Marathon
;Marathon
根据收到的resource offer和需要运行的task
作资源分配, 将分配结果反馈给Mesos Master
;Mesos Master
将task
分配到具体的Agent
上执行;Mesos agent
在业务机器上非侵入式部署C++11
编写,Mesos项目本身非常庞大,依赖库必然也很多,解决这些运行依赖问题首当其冲;/usr/local/lib
这样的系统目录, 而是在打包时采用动态更改可执行程序的rpath
的方法,使其运行时从我们的安装目录加载相应的so库, 具体作法就是 patchelf
这个工具可以在不影响可执行文件运行的前提下,修改其elf文件结构中的某些属性值,具体可参考:https://nixos.org/patchelf.html Mesos agent
只是一个单独的目录,卸载只需要停掉进程,删除目录就好;src/java/mesos.pom.in
,先找到 ``, 在它下面的 <configuration>
下添加 <skip>true</skip>
,这样不会编译这个 javdoc, 但不影响 java binding的使用Agent
一同部署在业务机器上,周期性的监测机器上可用资源和Agent
本身所用资源;Mesos
为我们提供了动态资源保留这个超实用的功能,可以限制Agent
当前针对某个Role
可以使用的计算资源:RESERVE_RESOURCES HTTP Request (JSON):
POST /api/v1 HTTP/1.1
Host: masterhost:5050
Content-Type: application/json
Accept: application/json
{
"type": "RESERVE_RESOURCES",
"reserve_resources": {
"agent_id": {
"value": "1557de7d-547c-48db-b5d3-6bef9c9640ef-S0"
},
"resources": [
{
"type": "SCALAR",
"name": "cpus",
"reservation": {
"principal": "my-principal"
},
"role": "role",
"scalar": {
"value": 1.0
}
}
]
}
}
RESERVE_RESOURCES HTTP Response:
HTTP/1.1 202 Accepted
Monitor
的监控评估结果就是当前Agent
可以使用的计算资源;Agent
并不能在线实时调整这个动态资源保留,需要在配置文件时更新好当前能够使用的动态资源,然后重启Agent
;Agent
是我们不能忍受的,因此我们修改了源码,通过http接口在线调整动态资源保留, 这部分其实不难,mesos http接口定义十分清晰,依葫芦画瓢就好了.task
的部署目前我们采用Marathon,上手简单,功能够用; 如果需要更灵活的调整策略,可能就需要自己开采框架或基于某一框架二次开发了;task
其实是有重要,紧急之分,占用资源也不尽相同。对于重要紧急任务,为了保障任务的更好运行,我们会利用Mesos attribute,在调度任务时让特定任务只跑在具有特定attributes
的agent
上, 这就需要为每个mesos agent
设置相应的attributes
;attributes
:-(, 其实也比较简单,稍微梳理下mesos源码结构,改起来不难;attributes
是动态调整的,agent
如果重启了怎么办?我们为此部署了etcd集群来管理,每台agent都是etcd上的一个node, 通过etcd
提供的http接口更新其attribrtes
, agent
会周期性的从etcd
上同步;同时各agent
上的attributes
信息也很容易从etcd
上获得;agent
上的attribute
, 那依赖于这种attribute
部署的任务会自动别调度走,不再在这台agent
上运行;cfs
方式,前提是需要判断当前kernel是否支持.对于disk的限制,目前mesos使用的是du
命令周期性检测的方式;rootfs + chroot
的方式来作简单的资源隔离;rootfs
, 任务打包就是将任务本身的依赖和相应rootfs
结合的过程, 打包好可以放到s3等存储上,供marathon部署任务时调用。{
"id": "/test_task", //在marathon上的任务id
"fetch": [
{
//每个任务都会打包成一个rootfs, mesos agent在运行时会从这个uri下载,然后自动解压缩
"uri": "http://xxx.xxx.xxx:8080/rootfs.tar.gz",
"extract": true,
"executable": false,
"cache": false
}
]
//上面下载的rootfs.tar.gz被解压成rootfs目录,执行任务时先chroot到此目录, 然后运行真正的/test这个任务
"cmd": "chroot ./rootfs /bin/bash -c \"/test > /dev/null \"",
"cpus": 2, //限定的cpu资源
"mem": 1024, //限定的memory资源
"disk": 2048, //限定的dist资源
"instances": 25, //当前任务一共运行多少个实例
"constraints": [ //限定当前任务只运行在有 "job=test_task"属性的agent上
[
"job",
"CLUSTER",
"test_task"
]
],
"acceptedResourceRoles": [
"test-role"
],
"portDefinitions": [
{
"port": 10005,
"name": "default",
"protocol": "tcp"
}
],
"user": "root"
}
chroot
, 大家可以参考这里: https://www.ibm.com/developerworks/cn/linux/l-cn-chroot/, 简单讲就是构造了一个沙箱,和已有的文件系统隔离;