利用 Docker 搭建多节点 Mesos 集群

Posted on 2016-3-9 in Others

在上一篇文章中我们已经简单介绍了 Mesos 的背景,那么为了更好的学习 Mesos,我们需要搭建一个测试环境。我选择搭建一个三节点的 Mesos 集群,这样也能顺便测试一下 leader 选举以及容错情况。

准备工作

  • 三台 server
  • Docker(版本>1.10,不然之后测试在mesos-slave中运行 Docker 容器会有问题)

开始部署

设置环境变量

我们需要在每台 server 上设定好有关 IP 的环境变量,提供给后续步骤使用。假定我们三台 server 的 IP 分别是 192.168.85.109,192.168.85.115 和 192.168.85.119。

HOST_IP_1=192.168.85.109
HOST_IP_2=192.168.85.115
HOST_IP_3=192.168.85.119

启动 Zookeeper

在每一台 server 上启动 zookeeper Docker 容器,我们需要为每一个 zookeeper 指定一个 id。另外,在我部署的过程中碰到一个 zookeeper 的 bind 错误,因此建议在哪台 server 启动,就将对应的 IP 设置为 0.0.0.0。

第一台 server 上执行

docker run -d \
--net host \
-p 2181:2181 \
-p 2888:2888 \
-p 3888:3888
-e MYID=1 \
-e SERVERS=0.0.0.0,${HOST_IP_2},${HOST_IP_3} \ --name=zookeeper \
mesoscloud/zookeeper

第二台 server 上执行

docker run -d \
--net host \
-p 2181:2181 \
-p 2888:2888 \
-p 3888:3888
-e MYID=1 \
-e SERVERS=${HOST_IP_1},0.0.0.0,${HOST_IP_3} \ --name=zookeeper \
mesoscloud/zookeeper

第三台 server 上执行

docker run -d \
--net host \
-p 2181:2181 \
-p 2888:2888 \
-p 3888:3888
-e MYID=1 \
-e SERVERS=${HOST_IP_1},${HOST_IP_2},0.0.0.0 \ --name=zookeeper \
mesoscloud/zookeeper

启动 Mesos Master

注意 MESOS_QUORUM 的值应大于等于 nodes / 2。

第一台 server 运行

docker run -d \
--net=host \
-e MESOS_HOSTNAME=${HOST_IP_1} \
-e MESOS_IP=${HOST_IP_1} \
-e MESOS_QUORUM=2 \
-e MESOS_ZK=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/mesos \
--name mesos-master  \
--restart always \
mesoscloud/mesos-master:centos7

第二台 server 运行

docker run -d \
--net=host \
-e MESOS_HOSTNAME=${HOST_IP_2} \
-e MESOS_IP=${HOST_IP_2} \
-e MESOS_QUORUM=2 \
-e MESOS_ZK=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/mesos \
--name mesos-master  \
--restart always \
mesoscloud/mesos-master:centos7

第三台 server 运行

docker run -d \
--net=host \
-e MESOS_HOSTNAME=${HOST_IP_3} \
-e MESOS_IP=${HOST_IP_3} \
-e MESOS_QUORUM=2 \
-e MESOS_ZK=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/mesos \
--name mesos-master  \
--restart always \
mesoscloud/mesos-master:centos7

启动 Marathon

Marathon 是 Mesos 生态系统中一个用于启动和控制服务的 Framework,用来运行一些会长时间运行的应用,甚至可以用来启动 Docker 容器。

我们也可以在三台 server 上都启动 Marathon Docker 容器来启用容错性。

第一台 server 运行

docker run -d \
--net host \
-e MARATHON_HOSTNAME=${HOST_IP_1} \
-e MARATHON_HTTPS_ADDRESS=${HOST_IP_1} \
-e MARATHON_HTTP_ADDRESS=${HOST_IP_1} \
-e MARATHON_MASTER=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/mesos \
-e MARATHON_ZK=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/marathon \
--name marathon \
--restart always \
mesoscloud/marathon:centos7

第二台 server 运行

docker run -d \
--net host \
-e MARATHON_HOSTNAME=${HOST_IP_2} \
-e MARATHON_HTTPS_ADDRESS=${HOST_IP_2} \
-e MARATHON_HTTP_ADDRESS=${HOST_IP_2} \
-e MARATHON_MASTER=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/mesos \
-e MARATHON_ZK=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/marathon \
--name marathon \
--restart always \
mesoscloud/marathon:centos7

第三台 server 运行

docker run -d \
--net host \
-e MARATHON_HOSTNAME=${HOST_IP_3} \
-e MARATHON_HTTPS_ADDRESS=${HOST_IP_3} \
-e MARATHON_HTTP_ADDRESS=${HOST_IP_3} \
-e MARATHON_MASTER=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/mesos \
-e MARATHON_ZK=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/marathon \
--name marathon \
--restart always \
mesoscloud/marathon:centos7

启动 Mesos Slaves

在第一台 server 执行

docker run -d \
--net host \
-e MESOS_HOSTNAME=${HOST_IP_1} \
-e MESOS_IP=${HOST_IP_1} \
-e MESOS_MASTER=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/mesos \
-v /sys/fs/cgroup:/sys/fs/cgroup \
-v /var/run/docker.sock:/var/run/docker.sock \
--name mesos-slave \
--restart always \
--privileged \
mesoscloud/mesos-slave:centos7

在第二台 server 执行

docker run -d \
--net host \
-e MESOS_HOSTNAME=${HOST_IP_2} \
-e MESOS_IP=${HOST_IP_2} \
-e MESOS_MASTER=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/mesos \
-v /sys/fs/cgroup:/sys/fs/cgroup \
-v /var/run/docker.sock:/var/run/docker.sock \
--name mesos-slave \
--restart always \
--privileged \
mesoscloud/mesos-slave:centos7

在第三台 server 执行

docker run -d \
--net host \
-e MESOS_HOSTNAME=${HOST_IP_3} \
-e MESOS_IP=${HOST_IP_3} \
-e MESOS_MASTER=zk://${HOST_IP_1}:2181,${HOST_IP_2}:2181,${HOST_IP_3}:2181/mesos \
-v /sys/fs/cgroup:/sys/fs/cgroup \
-v /var/run/docker.sock:/var/run/docker.sock \
--name mesos-slave \
--restart always \
--privileged \
mesoscloud/mesos-slave:centos7

检查 mesos 是否启动

打开浏览器,访问 http://192.168.85.109:5050,可以看到服务能正常访问,并且如果被访问的 mesos-master 不是 leader,页面将重定向到 leader master。

mesos master ui

通过 Marathon 启动一个 Nginx 服务器

Marathon 提供了 RestfulAPI 的方式来下发任务,我感觉比 ui 界面上的选项要多些,并且配置项看起来会更直观,因此这里的例子将采用 RestfulAPI 的方式。

POST http://192.168.85.109:8081/v2/apps

{
  "id": "nginx",
  "container": {
    "type": "DOCKER",
    "docker": {
      "image": "nginx:1.7.7",
      "network": "HOST"
    }
  },
  "instances": 1,
  "cpus": 1,
  "mem": 640,
  "constraints": [
    [
      "hostname",
      "UNIQUE"
    ]
  ]
}

这段 JSON 大概的意思是告诉 Marathon,我需要部署一个应用,id 是 nginx,请采用 Docker 容器的方式,镜像请使用 DockerHub 的 nginx:1.7.7,容器网络请用 HOST,然后这个应用需要 1 个CPU,640MB 的内存,并且只需要运行一个实例。

当 Mesos-master 分配好资源并且将任务下发给 Mesos-slave 后,就可以在 Marathon 的界面上会有一个 id 为 /nginx 的任务出现,在成功部署后,该任务将处于 Running 的状态。

marathon nginx application

应用被分配给 slave 192.168.85.115 执行了。

检查应用运行情况

因为我们采用 HOST 方式启动的 nginx 容器,那么访问 192.168.85.115 应该就能拿到 nginx 的欢迎页面。

$ curl http://192.168.85.115
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

验证通过!

参考资料

Deploy a Mesos Cluster with 7 Commands Using Docker

mesoscloud - DockerHub