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