mesos上负责长任务处理的Framework,也就是所谓的服务调度框架。
marathon设计之初的目标是让shell命令都能通过marathon远程调度,并保存长任务进程持续进行。
有web界面
# 重要概念
Application definition 长服务的定义,规定了APP启动和运行时的所有行为。Marathon提供了两种方式让你来定义你的长服务,
1、通过Portal来定义,它方便通过终端用户的理解和使用,
2、通过json格式的文件来定义,并通过restapi的方式来创建和管理这个app,两种方式方便和第三方的系统进行集成,提供了再次的可编程接口
Application instance
app的实例,也称作mesos的一个task,marathon可以为一个APP创建和管理多个实例,并可以动态的增大和减小某个APP实例的个数
并且通过marathon-lb实现服务发现和负载均衡 Application 一个长服务,例如(批处理、docker ) Deployments
对APP或者group的definition的一次修改的提交称为一次deployment. 他包括创建、销毁、扩容缩容APP或者group等。多个deployments可以是同时进行。
但是对于一个应用的deployments必须是串行的,如果前一个deployment没有结束就执行下一个deployment,那么它将会被拒绝。
Application Group ,同一group中APP可以被marathon统一管理
# 生命周期
Running
Deploying
应用程序的每一次改变操作没完成之前,我们的应用都属于一个deploying的状态
Suspended
把这个应用的所有正在运行的实例杀掉,并把这个应用的实例的数量减为0,这时这个应用只保留了定义,
并没有正在运行的实例。
Waiting
等待mesos进行下一资源的分配
Delayed
短时间内,失败次数过多。
# 应用操作
scale
为某个应用增加或减少指定数量的实例
restart
重启应用
suspend
杀死这个应用正在运行的实例,并把应用任务定义的数量减为0,
destory
实例和定义全部删除
http://mesosphere.github.io/marathon/docs/
前提是已经安装好Mesos,见我的系列文章。 Marathon安装也有两种方式:官网手动安装;使用yum安装。> 这里我们使用yum的简单安装。 Note:使用yum安装Marathon时不需要任何必要的配置,在哪个节点上安装,Marathon就会在哪个节点上启动,建议安装到master节点上 sudo yum -y install marathon(就这么简单) 其实这个设置和安装Mesos时配置mesos的hostname效果一样,不配置会显示默认的localhost,不影响使用>
mkdir -p /etc/marathon/conf/;touch hostname echo 192.168.1.24 /etc/marathon/conf/hostname systemctl start marathon.service
vi /etc/default/marathon export HTTP_PORT=8181 export MARATHON_HTTP_PORT=8181
MESOS_NATIVE_JAVA_LIBRARY=/usr/local/lib/libmesos.so /app/marathon-1.5.1/bin/marathon \ --master local \ --zk zk://localhost:2181/marathon
curl -X POST http://192.168.9.61:8080/v2/apps -d @basic-3.json -H "Content-type:application/json"

import requests import json headers = {'Content-type': 'application/json'} class MarathonApi(): def test_ping(self): url = "http://192.168.9.61:8080/v2/info" r = requests.get(url, headers=headers) print(r.status_code) print(json.dumps(r.json(), indent=4)) def test_create_docker_app(self): url = "http://192.168.9.62:8080/v2/apps" app = { "id": "ch5", "cmd": "python app.py", "cpus": 0.1, "mem": 32.0, "instances": 10, "upgradeStrategy": { "maximumOverCapacity": 1, "minimumHealthCapacity": 0.5 }, "constraints": [["hostname", "GROUP_BY"]], "networks": [{"mode": "container/bridge"}], "container": { "type": "DOCKER", "docker": {"image": "192.168.9.69:5000/imooc:v1.0.6"}, "portMappings": [{"containerPort": 5000, "hostPort": 0}] # 0是指随机端口 }, "healthChecks": [ # 200-399 { "path": "/", "portIndex": 0, "protocol": "HTTP", "gracePeriodSeconds": 300, # 忽略时间,一般启动的时候用到 "intervalSeconds": 60,# 检查时间 "timeoutSeconds": 20,#超时时间 "maxConsecutiveFailures": 3,#最大失败次数 "ignoreHttp1xx": False } ] } r = requests.post(url, headers=headers, json=app) print(r.status_code) print(json.dumps(r.json(), indent=4)) def test_scale_app(self): url = "http://192.168.9.62:8080/v2/groups/product" # 当当前应用处于一个锁定状态时,在url后添加 ?force=true,强制进行当前操作 app = { "instances": 1, } r = requests.put(url, headers=headers, json=app) print(r.status_code) print(json.dumps(r.json(), indent=4)) def test_group_app(self): url = "http://192.168.9.62:8080/v2/apps" group = { "id": "/product", "groups": [ { "id": "/product/database", "apps": [ {"id": "/product/database/mongo", "cpus": 1, "mem": 32.0, "cmd": "mongod", "networks": [{"mode": "container/bridge"}], "container": { "type": "DOCKER", "docker": {"image": "mongo:3.0"}, "portMappings": [{"containerPort": 8081, "hostPort": 0}] } }, { "id": "/product/database/mysql", "cpus": 1, "mem": 32.0, "cmd": "mysqld", "networks": [{"mode": "container/bridge"}], "container": { "type": "DOCKER", "docker": {"image": "mysql:5.6"}, "portMappings": [{"containerPort": 3306, "hostPort": 0}] } } ] }, { "id": "/product/service", "dependencies": ["/product/database"], "apps": [ {"id": "/product/service/app", "cpus": 1, "mem": 32.0, "cmd": "python app.py", "networks": [{"mode": "container/bridge"}], "container": { "type": "DOCKER", "docker": {"image": "192.168.9.69:5000/imooc:v1.0.1"}, "portMappings": [{"containerPort": 5000, "hostPort": 0}] } } ] } ] } r = requests.post(url, headers=headers, json=group) print(r.status_code) print(json.dumps(r.json(), indent=4)) def test_update_group(self): url = "http://192.168.9.62:8080/v2/groups/product" app = { "id": "/product", "dependencies": [], "apps": [ { "id": "/product/db", "instances": 10, "cpus": 0.1, "mem": 32, "upgradeStrategy": { "maximumOverCapacity": 1, "minimumHealthCapacity": 0.6 }, "container": { "type": "DOCKER", "docker": { "image": "mongo:3.4", }, "portMappings": [ { "containerPort": 27017, "hostPort": 0, "protocol": "tcp", "servicePort": 10001 } ] }, "healthChecks": [ { "gracePeriodSeconds": 300, "intervalSeconds": 60, "maxConsecutiveFailures": 0, "portIndex": 0, "protocol": "TCP", "timeoutSeconds": 20, "delaySeconds": 15 } ], "networks": [ { "mode": "container/bridge" } ] }, { "id": "/product/service", "cmd": "python app.py", "cpus": 0.1, "mem": 128, "instances": 10, "dependencies": [ "/product/db" ], "upgradeStrategy": { "maximumOverCapacity": 1, "minimumHealthCapacity": 0.8 ,# 在新实例启动前,讲旧实例删除到原80% }, "container": { "type": "DOCKER", "docker": { "image": "192.168.9.69:5000/imooc:v1.0.7", }, "portMappings": [ { "containerPort": 5000, "hostPort": 0, "labels": {}, "protocol": "tcp", "servicePort": 10002 } ] }, "healthChecks": [ { "gracePeriodSeconds": 300, "ignoreHttp1xx": False, "intervalSeconds": 60, "maxConsecutiveFailures": 3, "path": "/", "portIndex": 0, "protocol": "HTTP", "timeoutSeconds": 20, "delaySeconds": 15 } ], "networks": [ { "mode": "container/bridge" } ] } ], "groups": [], "pods": [] } r = requests.put(url, headers=headers, json=app) print(r.status_code) print(json.dumps(r.json(), indent=4))
滚动升级
marathon允许用户执行滚动升级来部署一个新的版本,具体操作如下: 1、删除部分旧版本的实例,保留另外一部分的旧版本实例 2、启动新版本的实例,健康检查通过 3、删除剩下的旧版本实例
minimumHealehCapacity == 0 在新实例启动后,再删除掉就实例 1、删除全部旧实例 2、启动新实例,健康检查通过 3、pass
minimumHealehCapacity == 1 在新实例启动后,再删除掉就实例 1、删除0个旧版本实例(启动n个新的实例) 2、启动新实例,健康检查通过 3、删除剩下的全部旧版本实例
minimumHealehCapacity == 0.5 按比例删除,旧版本
策略约束定义
用来约束控制程序运行的位置,实现优化容错。 分散容器运行在不同的节点上 [hostname,cluster,mesos-node1]
字段名称 操作符 可选参数
hostname;rack_id 机架ID
操作符
UNIQUE
CLUSTER // 与unique相反,允许你将任务运行在同一个资源中 --->同一台机器
//【hostname ,cluster,node2】
LIKE
// [hostname ,like ,mesos-node[1-2]]
UNLIKE
GROUP_BY // 将任务均匀地分散到机架或数据中心,提高可用性
服务注册、服务发现 1:n 将路由分配后多个docker当中 marathon中实例对外提供服务需解决的两个问题: 1、集群中实例的网络地址 是动态分配 2、marathon自动扩缩容,滚动升级等因素随时改变实例服务器端口 解决思路: 1、需要一个列表,随时记录应用的IP和端口情况(服务注册) 2、需要一个负载均衡,并能根据端口情况随时修改配置,实现转发 (负载均衡)
服务注册中心保存了各个服务可用的实例的相关信息。
服务注册中心提供了管理API和查询API。使用管理API进行服务注册、注销。
系统的其他组件可以通过查询API来获得可用的服务实例信息
负载均衡是一种服务器或网络设备的集群技术。负载均衡将特定的业务分担给多个服务器或网
络设备,从而提高了业务处理能力,保证了业务的高可用性。

# marathon-lb import requests import json headers = {'Content-type': 'application/json'} class ServiceDiscoveryApi(): def test_create_marathon_lb(self): """安装marathon-lb""" url = "http://192.168.9.62:8080/v2/apps" app = { "id": "/marathon-lb", "cmd": None, "cpus": 1, "mem": 128, "disk": 0, "instances": 1, "container": { "type": "DOCKER", "volumes": [], "docker": { "image": "docker.io/mesosphere/marathon-lb", "network": "HOST", "portMappings": [], "privileged": True } }, "healthChecks": [ { "gracePeriodSeconds": 30, "intervalSeconds": 5, "timeoutSeconds": 5, "maxConsecutiveFailures": 5, "port": 9090, "path": "/_haproxy_health_check", "protocol": "HTTP", "ignoreHttp1xx": False } ], "args": ["sse", "-m", "http://192.168.9.62:8080", "--group", "external"] } r = requests.post(url, headers=headers, json=app) print(json.dumps(r.json(), indent=4)) def test_create_app(self): url = "http://192.168.9.62:8080/v2/apps" app = { "id": "ch6-green", "cmd": "python app.py", "cpus": 0.1, "mem": 32.0, "instances": 1, "upgradeStrategy": { "maximumOverCapacity": 1, "minimumHealthCapacity": 0.5 }, "networks": [ {"mode": "container/bridge"}], "container": { "type": "DOCKER", "docker": {"image": "192.168.9.69:5000/imooc:v1.0.7"}, "portMappings": [ { "containerPort": 5000, "hostPort": 0, "labels": {}, "protocol": "tcp", "servicePort": 10001 } ] }, "healthChecks": [ { "path": "/", "portIndex": 0, "protocol": "HTTP", "gracePeriodSeconds": 300, "intervalSeconds": 60, "timeoutSeconds": 20, "maxConsecutiveFailures": 3, "ignoreHttp1xx": False } ], "labels": { "HAPROXY_GROUP": "external" } } r = requests.put(url, headers=headers, json=app) print(json.dumps(r.json(), indent=4))
# 1、创建
"args": ["sse", "-m", "http://192.168.9.62:8080", "--group", "external"]
# 2、注册
"portMappings": [ { "containerPort": 5000, "hostPort": 0, "labels": {}, "protocol": "tcp", "servicePort": 10001 # 集群分配给APP的一个端口,对于每个应用来说是唯一的,对外暴露的端口, ip是lb这个容器运行的机器地址。 } ]
"labels": { "HAPROXY_GROUP": "external" }
负载均衡实现-HAProxy
HAProxy是一款提高高可用性、负载均衡以及基于TCP和HTTP应用的代理软件,HAProxy特别适用于那些负载特大的web站点
,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单、安全的整合进您当前的架构中,
同时可以保护你的web服务器不被暴露到网络中。
运行在了9090端口上
lb容器机器IP:9090/haproxy?stat;csv