Quantcast
Channel: CodeSection,代码区,数据库(综合) - CodeSec
Viewing all articles
Browse latest Browse all 6262

mesos + marathon集群搭建(2)

$
0
0
本地存储卷

前面示例已经启动了redis镜像,然后为了验证marathon的资源隔离(主要是内存)特性,做了以下尝试:

将redis容器的内存限制为32M; 通过脚本循环向redis写入长字符串; 发现当任务资源监控超过16M的时候,内存占用又会重新清零。

这个过程我们可以知道,将数据写入redis之后,任务监控到redis实例的内存占用在不断增加。然后超过内存限制的一半之后,任务被kill,几秒钟之后marathon重新启动了任务,本地redis客户端重新可用。这里内存超过一半是因为默认redis开启了rdb文件保存(bgsave),redis需要新fork出进程进行rdb文件写入,导致此时虚拟内存翻倍,容器占用的内存超过了cgroup限制,被内核oom kill。我们可以通过内核日志发现一次oom kill的日志。最后marathon虽然重新启动了任务,但是由于docker容器的隔离性,之前写入硬盘的内容(rdb)文件都已经消失,导致内存清零,之前写入的大字符串消失。

如果我们希望redis任务重新启动之后能够保留数据(虽然对于测试场景无效,因为内存不足,如果数据恢复,进程也会立即被内核kill),就需要将容器中的redis工作目录持久化保存。

marathon文档中描述了两种持久化的方式,对于我们来说,最简单的就是使用本地卷进行持久化。本地卷的大致方式是向mesos master申请指定大小的卷,并将该卷和任务容器关联起来(对于docker容器使用volume-from参数关联即可)。

启动redis任务,其中和卷相关的配置为:

"volumes": [ { "containerPath": "/data", "hostPath": "redis", "mode": "RW" }, { "containerPath": "redis", "mode": "RW", "persistent": { "size": 1024 } } ]

该配置表示在slave机器上申请名为redis的卷,大小为1024MB,权限为读写。同时设置将主机的redis卷挂载到容器的/data目录中,挂载权限为读写。

提交任务之后,发现使用了本地卷之后的任务一直在unsheduled状态,slave上没有任务分派的数据。查了半天文档也没有好的解释。于是重新按照 marathon文档 进行了设置,特别关注其中的Prerequisites章节。其中描述了marathon启动参数中 必须 设置 mesos_authentication_principal 和 mesos_role 两个参数。但是其中没有太明确描述需要设置什么值。

由于这两个参数主要作为在mesos master执行操作时后的标识,首先先在marathon机器上的/etc/marathon/conf/目录中分别创建mesos_authentication_principal和mesos_role两个文件:

echo 'marathon' > /etc/marathon/conf/mesos_authentication_principal echo 'marathon' > /etc/marathon/conf/mesos_role

重启marathon服务之后,在任务详情中就可以看见新增的volume标签页。但情况并没有好转,任务长时间处于waiting状态,卷的状态一直为detached。最终在mesos master(leader那台)上找到了一些错误日志:

Dropping RESERVE offer operation from framework … A reserve operation was attempted with no principal, but there is a reserved resource in the request with principal ‘marathon’ set in ReservationInfo

紧接着一条错误:

Dropping CREATE offer operation from framework…Invalid CREATE Operation: Insufficient disk resources

查询了文档之后大概知道,由于principal设置的问题,mesos master没有认可marathon发起的RESERVE指令(既让slave预留一部分资源,这里是硬盘空间),随后由于没有预留足够的硬盘空间,发送的创建指令由于没有剩余空间而失败。

从错误日志基本可以断定是由于principal设置问题导致的,从 marathon任务相关文档 中,终于了解了mesos master acl相关的配置,,以及这些配置对frameworks的影响。直接抄文档中的acls内容会有问题,因为其中只是指定了run_tasks和register_frameworks两个操作的acl,通过 mesos文档 ,我们可以查阅到mesos master支持的所有acl项。对于我们的需求,需要授权marathon支持reserve_resources操作,最终将acls参数内容更新为:

{ "run_tasks": [ { "principals": { "type": "ANY" }, "users": { "type": "ANY" } } ], "register_frameworks": [ { "principals": { "type": "ANY" }, "roles": { "type": "ANY" } } ], "reserve_resources": [ { "principals": { "type": "ANY" }, "roles": { "type": "ANY" }, "resources": { "type": "ANY" } } ], "unreserve_resources": [ { "principals": { "type": "ANY" }, "roles": { "type": "ANY" }, "reserver_principals": { "type": "ANY" } } ], "create_volumes": [ { "principals": { "type": "ANY" }, "roles": { "type": "ANY" } } ], "destroy_volumes": [ { "principals": { "type": "ANY" }, "roles": { "type": "ANY" }, "creator_principals": { "type": "ANY" } } ] }

这里只是为了能够正常分配,没有做任何访问控制。将上述内容保存到文件(/etc/mesos-acls)然后添加到mesos-master的参数:

echo 'file:///etc/mesos-acls' > /etc/mesos-master/acls

重启所有mesos master,之前一直在waiting状态的任务,已经可以正常申请卷,并启动容器。进入分配到的slave服务器,我们可以看见多了一个挂载点:

/dev/vda1 on /var/lib/mesos/slaves/fb9d0623-c0bf-402e-9288-06206b30ea54-S4/frameworks/487f9562-5998-4cfb-bc92-bbc3a441c69c-0000/executors/redis_single.bd21b767-41b8-11e6-9d7a-024259ae7178/runs/8c9304a1-b960-4aa0-a169-f368a4d77ed9/redis type xfs (rw,relatime,attr2,inode64,noquota)

同时通过docker inspect命令查看redis容器的参数,可以发现其中卷挂载有如下配置:

"Mounts": [ { "Source": "/var/lib/mesos/slaves/fb9d0623-c0bf-402e-9288-06206b30ea54-S4/frameworks/487f9562-5998-4cfb-bc92-bbc3a441c69c-0000/executors/redis_single.bd21b767-41b8-11e6-9d7a-024259ae7178/runs/8c9304a1-b960-4aa0-a169-f368a4d77ed9/redis", "Destination": "/data", "Mode": "rw", "RW": true, "Propagation": "rprivate" }, { "Source": "/var/lib/mesos/slaves/fb9d0623-c0bf-402e-9288-06206b30ea54-S4/frameworks/487f9562-5998-4cfb-bc92-bbc3a441c69c-0000/executors/redis_single.bd21b767-41b8-11e6-9d7a-024259ae7178/runs/8c9304a1-b960-4aa0-a169-f368a4d77ed9", "Destination": "/mnt/mesos/sandbox", "Mode": "", "RW": true, "Propagation": "rprivate" } ]

既创建的挂载点已经被挂到容器的指定路径了。

然后我们进行验证:首先通过redis客户端连接到redis上,然后设置工作路径为我们挂载的路径:

redis-cli -h 1.1.1.1 CONFIG SET dir /data

然后写入数据:

redis-cli -h 1.1.1.1 set a b

为了确保能够正常持久化,执行:

redis-cli -h 1.1.1.1 bgsave

查看挂载卷路径,可以发现已经有dump.rdb文件产生。此时kill掉redis任务,等待marathon重新启动。再次启动之后,通过redis-cli连接进入redis之后,可以看见之前设置的key仍然存在:

> redis-cli -h 1.1.1.1 keys * 1) "a"

然后获取这个key的值:

> redis-cli -h 1.1.1.1 get a 1) "b"

从这个实验可以看出,marathon的本地存储卷可以确保服务重新启动之后原来的数据仍然存在,对于存储类的应用(如redis、mysql等)非常有用。


Viewing all articles
Browse latest Browse all 6262

Trending Articles