Mesos+Marathon+zk+docker構建PaaS平臺

參考文檔:

  1. mesos:http://mesos.apache.org/documentation/latest/

  2. mesosphere社區版:https://github.com/mesosphere/open-docs

  3. mesosphere倉庫:https://github.com/mesosphere/open-docs/blob/master/downloads/mesos.md

  4. marathon: https://mesosphere.github.io/marathon/docs/

  5. chronos: https://mesos.github.io/chronos/docs/

  6. consul:https://www.consul.io/ https://releases.hashicorp.com/consul/

  7. docker安裝:https://docs.docker.com/engine/installation/linux/docker-ce/centos/

一、系統說明

mesos 集羣資源管理框架(以集羣的形式出現,主決定資源的分配,從負責執行executor),分配資源,提供offer給framework,不負責調度資源,千言萬語都在這裏了mesos的設計結構


marathon 是mesos的framework,容器編排系統,保證長時間的運行任務,類似後臺執行或者supervisor。


zooKeeper是一個分佈式的,開放源碼的分佈式應用程序協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要組件。它是一個爲分佈式應用提供一致性服務的軟件,提供的功能包括:配置管理維護、域名服務、分佈式同步、組服務、健康檢查,HA等。


Chronos是一個運行在Mesos之上的具有分佈式容錯特性的作業調度器。在Airbnb公司,它是cron的替代品。與cron相比,Chronos在很多方面具備優勢。比如,它支持ISO8601標準,允許更靈活地定義調度時間;Chronos也支持任務依賴,即一個作業的開始依賴於一些任務的完成,和marathon一樣都是聽從mesos的指令,給mesos搬磚的。


consul經常拿來和etcd、 zookeeper來對比,他有和etcd一樣的服務發現、服務註冊功能,也有和etcd、zookeeper一樣的配置存儲功能,詳細的對比在此不再列出。


Registrator是一個獨立於服務註冊表的自動服務註冊/註銷組件,一般以容器的方式進行部署。會自動偵測它所在的宿主機上的所有 容器狀態(啓用/銷燬),並根據容器狀態到對應的服務註冊列表註冊/註銷服務。去除了需要手動管理Consul服務條目的複雜性,它監視容器的啓動和停止,根據容器暴露的端口和環境變量自動註冊服務。


事實上, 通過讀取同一臺宿主機的其他容器 的環境變量進行服務註冊、健康檢查定義等操作,支持可插拔式的服務註冊表配置。

架構圖看起來像這樣:

clip_image002


mesos架構:

clip_image004

架構圖可以看出mesos主要兩部分主和從 ,主集羣依靠zookeeper

架構圖展示了Mesos的重要組成部分,Mesos由一個master進程管理運行着每個客戶端節點的slave進程和跑任務的Mesos計算框架。

Mesos進程通過計算框架可以很細緻的管理cpu和內存等,從而提供資源。每個資源提供都包含了一個清單(slave ID,resource1:amount1,resource2,amount2,…)master會根據現有的資源決定提供每個計算框架多少資源。例如公平分享或者根據優先級分享。

爲了支持不同種的政策,master通過插件機制新增額一個allocation模塊使之分配資源更簡單方便。

一個計算框架運行在兩個組建之上,一個是Scheduler,他是master提供資源的註冊中心,另一個是Executor程序,用來發起在slave節點上運行計算框架的任務。master決定給每個計算框架提供多少計算資源,計算框架的調度去選擇使用哪種資源。當一個計算框架接受了提供的資源,他會通過Mesos的任務描述運行程序。Mesos也會在相應的slave上發起任務。

Mesos是Apache下的開源分佈式資源管理框架,它被稱爲分佈式系統的內核。Mesos最初是由加州大學伯克利分校的AMPLab開發,後在Twitter得到廣泛使用。

Mesos-Master:主要負責管理各個framework和slave,並將slave上的資源分配給各個framework。

Mesos-Slave:負責管理本節點上的各個mesos-task,比如:爲各個executor分配資源。

Framework:計算框架,如:Hadoop、Spark、Kafaka、ElasticSerach等,通過MesosSchedulerDiver接入Mesos

Executor:執行器,就是安裝到每個機器節點的軟件,這裏就是利用docker的容器來擔任執行器的角色。具有啓動銷燬快,隔離性高,環境一致等特點。

Mesos-Master是整個系統的核心,負責管理接入Mesos的各個framework(由frameworks_manager管理)和slave(由slaves_manager管理),並將slave上的資源按照某種策略分配給framework(由獨立插拔模塊Allocator管理)。

Mesos-Slave負責接受並執行來自Mesos-master的命令、管理節點上的mesos-task,併爲各個task分配資源。Mesos-slave將自己的資源量發送給mesos-master,由mesos-master中的Allocator模塊決定將資源分配給哪個framework,當前考慮的資源有CPU和內存兩種,也就是說,Mesos-slave會將CPU個數的內存量發送給mesos-master,而用戶提交作業時,需要指定每個任務需要的CPU個數和內存。這樣:當任務運行時,mesos-slave會將任務放導包含固定資源Linux container中運行,以達到資源隔離的效果。很明顯,master存在單點故障問題,爲此:Mesos採用了Zookeeper解決該問題。

Framework是指外部的計算框架,如果Hadoop、Mesos等,這些計算框架可通過註冊的方式接入Mesos,以便Mesos進行統一管理和資源分配。Mesos要求可接入的框架必須有一個調度模塊,該調度器負責框架內部的任務調度。當一個framework想要接入Mesos時,需要修改自己的調度器,以便向Mesos註冊,並獲取Mesos分配給自己的資源,這樣再由自己的調度器將這些資源分配給框架中的任務,也就是說,整個Mesos系統採用了雙層調度框架:第一層,由Mesos將資源分配給框架。第二層,框架自己的調度器將資源分配給自己內部的任務。當前Mesos支持三中語言編寫的調度器,分別是C++、Java、Python。爲了向各種調度器提供統一的接入方式,Mesos內部採用C++實現了一個MesosSchedulerDriver(調度驅動器),framework的調度器可調用該driver中的接口與Mesos-master交互,完成一系列功能(如註冊,資源分配等。)

Executor主要用於啓動框架內部的task。由於不同的框架,啓動task的接口或者方式不同,當一個新的框架要接入mesos時,需要編寫一個Executor,告訴Mesos如何啓動該框架中的task。爲了向各種框架提供統一的執行器編寫方式,Mesos內部採用C++實現了一個MesosExecutorDiver(執行器驅動器),framework可通過該驅動器的相關接口告訴Mesos啓動task的方式。

mesos運行流程:

clip_image006

流程步驟:

1、slave1報告給master他擁有4核cpu和4G剩餘內存,Marathon調用allocation政策模塊,告訴slave1計算框架1應該被提供可用的資源。

2、master給計算框架1發送一個在slave上可用的資源描述。

3、計算框架的調度器回覆給master運行在slave上兩個任務相關信息,任務1需要使用2個CPU,內存1G,任務2需使用1個CPU,2G內存。

4、最後,master發送任務給slave,分配適當的給計算框架執行器,繼續發起兩個任務(圖1.1-2虛線處),因爲任有1個CPU和1G內存未分配,allocation模塊現在或許提供剩下的資源給計算框架2。

除此之外,當任務完成,新的資源成爲空閒時,這個資源提供程序將會重複

二、環境

說明:

主機名

IP

OS

安裝服務

mesos-master1

192.168.8.131

CentOS-7.5

mesos-master, marathon,zookeeper, consul-server, chronos, consul-template

mesos-master2

192.168.8.132

CentOS-7.5

mesos-master, marathon,zookeeper, consul-server, chronos

mesos-master3

192.168.8.133

CentOS-7.5

mesos-master, marathon,zookeeper, consul-server, chronos

mesos-slave1

192.168.8.134

CentOS-7.5

mesos-slave, docker, registrator

mesos-slave2

192.168.8.135

CentOS-7.5

mesos-slave, docker, registrator

軟件版本:

服務

版本

作用

zookeeper

3.4.12

保持各master之間的通信,選舉leader、HA

mesos-master

1.6.0

管理接入mesos的各個framework & slave,並將slave上的資源按照相應策略分配給framework

mesos-slave

1.6.0

任務執行節點

marathon

1.6.352

調度器,用於下發任務,可保持長應用

docker

1.13.1

具體執行docker下發任務

chronos

3.0+

cron-on-mesos,用來運行基於容器的定時任務的Mesos框架

consul/ registrator

1.1.0/ latest

提供服務自動註冊、發現功能

consul-template

0.19.4

Consul template 搭配consul使用,支持多種負載均衡接入層,如Nginx、Haproxy,LVS

三、Master節點部署

以節點zk-node1爲例,zk-node2/3根據情況調整。

1、準備工作

# systemctl stop firewalld

# setenforce 0

# systemctl disable firewalld

# cat /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4

::1      localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.8.131  mesos-master1

192.168.8.132  mesos-master2

192.168.8.133  mesos-master3

192.168.8.134  mesos-slave1

192.168.8.135  mesos-slave2

# yum groupinstall -y "Development Tools"

# yum install -y tar wget git lrzsz lsof

 

2、zookeeper安裝及HA

ZooKeeper運行在java環境下,文檔中建議安裝jdk 1.7以上版本(含)。

# yum -y install java java-devel

# java -version

openjdk version "1.8.0_171"

OpenJDK Runtime Environment (build 1.8.0_171-b10)

OpenJDK 64-Bit Server VM (build 25.171-b10, mixed mode)

# tar xf zookeeper-3.4.12.tar.gz -C /usr/local

# chown -R root.root /usr/local/zookeeper-3.4.12

# ln -s /usr/local/zookeeper-3.4.12/ /usr/local/zk

# cp /usr/local/zk/conf/zoo_sample.cfg /usr/local/zk/conf/zoo.cfg


zookeeper配置文件詳解

下面就是zoo.cfg配置文件的修改了,那麼我們首先要熟悉下zookeeper配置文件。
# cat /usr/local/zk/conf/zoo.cfg
dataDir:數據目錄
dataLogDir:日誌目錄
clientPort:客戶端連接端口
tickTime:Zookeeper 服務器之間或客戶端與服務器之間維持心跳的時間間隔,也就是每隔tickTime 時間就會發送一個心跳。
initLimit:Zookeeper的Leader 接受客戶端(Follower)初始化連接時最長能忍受多少個心跳時間間隔數。當已經超過 5個心跳的時間(也就是tickTime)長度後 Zookeeper 服務器還沒有收到客戶端的返回信息,那麼表明這個客戶端連接失敗。總的時間長度就是 5*2000=10 秒
syncLimit:表示 Leader 與 Follower 之間發送消息時請求和應答時間長度,最長不能超過多少個tickTime 的時間長度,總的時間長度就是 2*2000=4 秒。
server.A=B:C:D:
A 是一個數字,表示這個是第幾號服務器;
B 是這個服務器的 ip 地址;
C 表示的是這個服務器與集羣中的 Leader 服務器交換信息的端口;
D 表示的是萬一集羣中的 Leader 服務器掛了,需要一個端口來重新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時服務器相互通信的端口。

# grep -Ev "#|^$" /usr/local/zk/conf/zoo.cfg

tickTime=2000

initLimit=10

syncLimit=5

dataDir=/usr/local/zk/data/zk1

dataLogDir=/usr/local/zk/logs

clientPort=2181

maxClientCnxns=60

server.1=192.168.8.131:2888:3888

server.2=192.168.8.132:2888:3888

server.3=192.168.8.133:2888:3888

# mkdir /usr/local/zk/data/zk1 -p

# mkdir /usr/local/zk/logs -p

# echo "1" > /usr/local/zk/data/zk1/myid

# scp -p /usr/local/zk/conf/zoo.cfg [email protected]:/usr/local/zk/conf/zoo.cfg

# scp -p /usr/local/zk/conf/zoo.cfg [email protected]:/usr/local/zk/conf/zoo.cfg

# mesos-master2的zk配置,同樣需要創建dataDir,dataLogDir目錄和myid文件,文件內容2

# sed -i 's/zk1/zk2/g' /usr/local/zk/conf/zoo.cfg
# mkdir /usr/local/zk/data/zk2 -p

# mkdir /usr/local/zk/logs -p

# echo "2" > /usr/local/zk/data/zk2/myid

# grep -Ev "#|^$" /usr/local/zk/conf/zoo.cfg

tickTime=2000

initLimit=10

syncLimit=5

dataDir=/usr/local/zk/data/zk2

dataLogDir=/usr/local/zk/logs

clientPort=2181

maxClientCnxns=60

server.1=192.168.8.131:2888:3888

server.2=192.168.8.132:2888:3888

server.3=192.168.8.133:2888:3888

# mesos-master3的zk配置,同樣需要創建dataDir,dataLogDir目錄和myid文件,文件內容3

# sed -i 's/zk1/zk3/g' /usr/local/zk/conf/zoo.cfg
# mkdir /usr/local/zk/data/zk3 -p

# mkdir /usr/local/zk/logs -p

# echo "3" > /usr/local/zk/data/zk3/myid

# grep -Ev "#|^$" /usr/local/zk/conf/zoo.cfg

tickTime=2000

initLimit=10

syncLimit=5

dataDir=/usr/local/zk/data/zk3

dataLogDir=/usr/local/zk/logs

clientPort=2181

maxClientCnxns=60

server.1=192.168.8.131:2888:3888

server.2=192.168.8.132:2888:3888

server.3=192.168.8.133:2888:3888

啓動zk服務,查看狀態:

# /usr/local/zk/bin/zkServer.sh start

# /usr/local/zk/bin/zkServer.sh status

zk集羣各節點狀態:

clip_image007

clip_image008

clip_image009

zk各節點端口:

clip_image011

clip_image013

clip_image015

由此可見,集羣已經正常運行。

clip_image016

客戶端可以通過nc或telnet連接ZooKeeper Server提交指令。

ZooKeeper Client 簡單操作:

9個基本操作指令:

clip_image017

3、安裝mesos-master&marathon

Mesos 集羣部署
Mesos集羣有MesosMaster和Mesos Slave兩個角色。

mesosphere倉庫
需要在Mesos Master和MesosSlave節點均安裝。

# 添加mesosphere repository,根據github mesosphere社區版獲取最新repository

# rpm -Uvh http://repos.mesosphere.io/el/7/noarch/RPMS/mesosphere-el-repo-7-2.noarch.rpm

# hostnamectl --static set-hostname mesos-master1 //修改主機名

# yum -y install mesos marathon

4、mesos-master&marathon配置

mesos-master增加zookeeper配置,選主並增加HA:

# vi /etc/mesos/zk

zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/mesos

# scp /etc/mesos/zk [email protected]:/etc/mesos/zk

# scp /etc/mesos/zk [email protected]:/etc/mesos/zk

設置文件/etc/master-/quorum內容爲一個大於(master節點數除以2)的整數。即採用四捨五入,比如這裏有3master節點,那麼3/2=1.5,四捨五入爲2

# echo "2" >/etc/mesos-master/quorum

# cat /etc/mesos-master/quorum

2

# scp /etc/mesos-master/quorum [email protected]:/etc/mesos-master/quorum

# scp /etc/mesos-master/quorum [email protected]:/etc/mesos-master/quorum

#主機名和ip要在hosts中寫入,最好不要使用localhost,否則會出現slave不能識別,以及marathon任務下發不正常等現象。

# 默認marathon無相關配置目錄/文件

# mkdir -p /etc/marathon/conf

mesos-master1:

# echo "192.168.8.131" >/etc/mesos-master/hostname

# echo "192.168.8.131" >/etc/mesos-master/ip

# echo "192.168.8.131" >/etc/marathon/conf/hostname

# echo "192.168.8.131" >/etc/marathon/conf/ip

mesos-master2:

# echo "192.168.8.132" >/etc/mesos-master/hostname

# echo "192.168.8.132" >/etc/mesos-master/ip

# echo "192.168.8.132" >/etc/marathon/conf/hostname

# echo "192.168.8.132" >/etc/marathon/conf/ip

mesos-master3:

# echo "192.168.8.133" >/etc/mesos-master/hostname

# echo "192.168.8.133" >/etc/mesos-master/ip

# echo "192.168.8.133" >/etc/marathon/conf/hostname

# echo "192.168.8.133" >/etc/marathon/conf/ip

marathon連接mesos-masterHA

# cp /etc/mesos/zk /etc/marathon/conf/master

# cp /etc/mesos/zk /etc/marathon/conf/zk

# sed -i 's|mesos|marathon|g' /etc/marathon/conf/zk

# cat /etc/marathon/conf/master

zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/mesos

# cat /etc/marathon/conf/zk

zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/marathon

# scp /etc/marathon/conf/master [email protected]:/etc/marathon/conf/

# scp /etc/marathon/conf/master [email protected]:/etc/marathon/conf/

# scp /etc/marathon/conf/zk [email protected]:/etc/marathon/conf/

# scp /etc/marathon/conf/zk [email protected]:/etc/marathon/conf/

5、啓動mesos,marathon

# systemctl enable mesos-master marathon

# systemctl start mesos-master marathon

# systemctl disable mesos-slave

# systemctl status mesos-master marathon

# systemctl status marathon #marathon啓動報錯

● marathon.service - Scheduler for Apache Mesos

Loaded: loaded (/usr/lib/systemd/system/marathon.service; enabled; vendor preset: disabled)

Active: activating (auto-restart) (Result: exit-code) since Mon 2018-05-14 21:13:32 CST; 37s ago

Process: 25368 ExecStart=/usr/share/marathon/bin/marathon (code=exited, status=1/FAILURE)

……

Main PID: 25368 (code=exited, status=1/FAILURE)

May 14 21:13:32 mesos-master1 systemd[1]: marathon.service: main process exited, code=exited, status=1...LURE

……

Hint: Some lines were ellipsized, use -l to show in full.

用以下命令 [journalctl -o verbose _PID=24962] 查看marathon進程的詳細信息。

# journalctl -o verbose _PID=25368

-- Logs begin at Sun 2018-05-13 03:47:48 CST, end at Mon 2018-05-14 21:08:12 CST. --

Mon 2018-05-14 21:07:04.849490 CST [s=2f8e0393e2dc4d639f4d5bf76a4e9b6f;i=ec5;b=4a9ee33c3e074eb987230b0202c47a

PRIORITY=6

_SYSTEMD_SLICE=system.slice

_BOOT_ID=4a9ee33c3e074eb987230b0202c47a39

_MACHINE_ID=74bb4614536844d798b123d0cc927d4e

SYSLOG_FACILITY=3

_TRANSPORT=stdout

_SELINUX_CONTEXT=system_u:system_r:init_t:s0

_EXE=/usr/bin/bash

_CAP_EFFECTIVE=0

_COMM=bash

_HOSTNAME=mesos-master1

SYSLOG_IDENTIFIER=marathon

MESSAGE=No start hook file found ($HOOK_MARATHON_START). Proceeding with the start script.

_UID=998

_GID=996

_CMDLINE=bash /usr/share/marathon/bin/marathon

_SYSTEMD_CGROUP=/system.slice/marathon.service

_SYSTEMD_UNIT=marathon.service

_STREAM_ID=bd3ee42018a94236baeab1e5f653171f

_PID=24962

Mon 2018-05-14 21:07:08.496043 CST [s=2f8e0393e2dc4d639f4d5bf76a4e9b6f;i=ec6;b=4a9ee33c3e074eb987230b0202c47a

PRIORITY=6

_SYSTEMD_SLICE=system.slice

_BOOT_ID=4a9ee33c3e074eb987230b0202c47a39

_MACHINE_ID=74bb4614536844d798b123d0cc927d4e

SYSLOG_FACILITY=3

_TRANSPORT=stdout

_SELINUX_CONTEXT=system_u:system_r:init_t:s0

_CAP_EFFECTIVE=0

_HOSTNAME=mesos-master1

SYSLOG_IDENTIFIER=marathon

_UID=998

_GID=996

_SYSTEMD_CGROUP=/system.slice/marathon.service

_SYSTEMD_UNIT=marathon.service

MESSAGE=[scallop] Error: Required option 'master' not found

_COMM=java

_EXE=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.171-7.b10.el7.x86_64/jre/bin/java

_CMDLINE=java -cp /usr/share/marathon/lib/mesosphere.marathon.marathon-1.6.352.jar:/usr/share/marathon/li

_STREAM_ID=bd3ee42018a94236baeab1e5f653171f

_PID=24962

通過上述日誌可以看出,是找不到master導致啓動失敗。檢查了下以上關於marathon的所有配置,確認沒有問題。可以根據如下辦法直接帶master參數啓動marathon,最終成功!

# which marathon

/usr/bin/marathon

# nohup marathon --master zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/mesos --zk zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/marathon & >>nohup.out

# ss -tunlp|grep 8080 #8080端口爲marathon的進程監聽端口

tcp LISTEN 0 50 :::8080 :::* users:(("java",pid=17946,fd=179))

6、查看mesos application的信息

查看application的metric

# curl http://192.168.8.131:8080/metrics | python -m json.tool | less

查看運行的app

# curl http://192.168.8.131:8080/v2/apps | python -m json.tool

查看ID爲nginx-test的app

# curl http://192.168.8.131:8080/v2/apps/nginx-test | python -m json.tool

刪除ID爲nginx-test的app

# curl -X DELETE http://192.168.8.131:8080/v2/apps/nginx-test | python -m json.tool

四、Slave節點部署

以slave-node1爲例,slave-node2配置根據環境微調。

1、安裝mesos-slave

# yum install mesos docker –y

2、mesos-slave關聯zookeeper

# vi /etc/mesos/zk

zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/mesos

3、配置marathon調用mesos運行docker

# echo "docker,mesos" >/etc/mesos-slave/containerizers

4、mesos-slave配置ip&hostname

# echo "192.168.8.134">/etc/mesos-slave/ip

# echo "192.168.8.134" >/etc/mesos-slave/hostname

5、啓動服務並增加開機啓動

# systemctl stop mesos-master

# systemctl disable mesos-master

# systemctl enable mesos-slave docker

# systemctl start mesos-slave docker

# systemctl status docker

報錯:Unit dockergetenforce.service could not be found.

解決方法:

重啓服務

# systemctl status mesos-slave

五、驗證

登陸mesos web:http://192.168.8.131:5050/#/

1、mesos-homepage

clip_image019

1. 從首頁可以看到mesos-agent:activated狀態的agent有2個;

2. mesos-master管理的2個agent的資源已彙總。

2、mesos-Frameworks

clip_image021

1. 在mesos框架中,marathon框架已經被識別,marathon的leader是:mesos-master2;

2. 雖然mesos-master與marathon的leader相同,但兩者的leader是zookeeper獨立選舉的,並沒有直接關係,是可以不同的。

3、mesos-Agents

clip_image023

1.在Agnets中能看到2個agent;

2.同時能看到每個agent的資源;

點擊上面2個slave中的任意一個,也能看出它的master是mesos-master2

clip_image025

訪問marathon的管理頁面,http://master_ip:8080

這裏的master_ip就是在上面訪問mesos頁面Frameworks中識別出的marathon,即192.168.8.132:8080
或者直接點擊mesos訪問頁面Frameworks中識別出的marathon也可以。

clip_image027

4、mesos state

瀏覽器訪問:http://192.168.8.132:5050/master/state

clip_image029

clip_image031

5、通過Mesos調度,使用marathon來創建容器

比如創建一個nginx鏡像的Docker容器,Marathon啓動時會讀取/etc/mesos/zk配置文件,Marathon通過Zookeeper來找到Mesos Master。
1)Marathon有自己的REST API,我們通過API的方式來創建一個 tomcat 的Docker容器

首先創建一個json文件(這個要在master節點機器上創建,任意一臺master節點機上都可以):

# docker pull nginx

# docker pull tomcat

nginx-example:

{

"id":"nginx", #容器名,只在marathon生效

"cpus":0.2, #cpu用量

"mem":32.0, #mem用量

"instances": 1, #容器數量

"constraints": [["hostname", "UNIQUE",""]], #限制

"container": {

"type":"DOCKER", #應用類型

"docker": { #docker具體配置

"image": "docker.io/nginx", #採用的image

"network": "BRIDGE", #網絡模式

"portMappings": [

{"containerPort": 80, "hostPort": 0,"servicePort": 0, "protocol": "tcp" }

] #端口映射,”0”表示任意端口,"servicePort"服務端口

}

}

}

# vi tomcat.json # tomcat的docker鏡像要提前創建或下載

{

"id":"tomcat-1",

"cpus":0.5,

"mem":64,

"instances": 1,

"constraints": [["hostname", "CLUSTER",""]],

"container": {

"type":"DOCKER",

"docker": {

"image": "docker.io/tomcat",

"network": "BRIDGE",

"portMappings": [

{"containerPort": 8080, "hostPort": 0,"servicePort": 0, "protocol": "tcp" }

]

}

}

}

注意:json文件中的每一行內容的開頭和結尾一定不能有空格,但可以有空行,否則手動通過curl的方式創建容器實例,會有各種各樣的報錯!!!

接着使用curl的方式調用,注意上面的tomcat.json文件是在/root路徑下的(注意下面命令中json文件路徑)。

# curl -X POST http://192.168.8.131:8080/v2/apps -d @/root/tomcat.json -H "Content-type: application/json"

{"id":"/tomcat-1","backoffFactor":1.15,"backoffSeconds":1,"constraints":[["hostname","CLUSTER",""]],"container":{"type":"DOCKER","docker":{"forcePullImage":false,"image":"docker.io/tomcat","parameters":[],"privileged":false},"volumes":[],"portMappings":[{"containerPort":8080,"hostPort":0,"labels":{},"protocol":"tcp","servicePort":0}]},"cpus":0.5,"disk":0,"executor":"","instances":1,"labels":{},"maxLaunchDelaySeconds":3600,"mem":64,"gpus":0,"networks":[{"mode":"container/bridge"}],"requirePorts":false,"upgradeStrategy":{"maximumOverCapacity":1,"minimumHealthCapacity":1},"version":"2018-05-20T09:20:37.589Z","killSelection":"YOUNGEST_FIRST","unreachableStrategy":{"inactiveAfterSeconds":0,"expungeAfterSeconds":0},"tasksStaged":0,"tasksRunning":0,"tasksHealthy":0,"tasksUnhealthy":0,"deployments":[{"id":"8035fe3f-44a7-4c8d-9f8f-22ecf66ea24f"}],"tasks":[]}

也可以將上面的tomcat.json文件內容直接複製到marathon創建應用容器的"JSON Mode"模式裏,然後直接點擊創建。

clip_image033

登陸marathon界面查看是在哪一臺slave機器上創建的docker容器實例(這個是隨機的),點擊"running"。(如果容器創建失敗,即非"running"狀態,可以嘗試重啓slave節點的docker服務)

clip_image035

然後登陸mesos-slave1機器,發現在服務器上,這個容器只是被關閉了(docker ps -a),可以選擇刪除。如果再次在機器上啓動這個nginx容器,那麼在marathon上是不會顯示的。

注意:在節點機器上手動創建的docker容器,這些容器信息是不會在marathon和mesos裏展示的。

在marathon界面裏"Destory"刪除對應的application後,在mesos界面的"Active Tasks"裏的對應任務也會刪除。

另外要注意:在marathon界面裏通過調用mesos創建docker容器,只能創建應用容器(Application),如nginx、tomcat、mysql、redis等,需要映射端口,這裏是映射的是宿主機的隨機端口。不能創建基本centos,ubuntu的系統容器!

2)nginx實例擴容

點擊marathon首頁正在運行的nginx實例最後面的"…",選擇"Scale",在彈出來的實例擴容對話框中,輸入所要擴容的實例個數,確定後進行擴容。很快會看到原來正在運行的nginx單實例由一個變爲多個。Marathon的實例擴容同時也有相應的API,也可以在bash下通過api進行擴容。

訪問所創建的nginx容器。(marathon ui界面裏創建的docker容器映射到宿主機的訪問端口默認都是隨機分配的(BRIDGE模式))、可以自己製作應用的docker鏡像,或者自定義構建容器並提交爲新鏡像(自己設定應用容器結構),然後根據自己製作的鏡像在Marathon上創建應用。

clip_image039

clip_image041

如以上截圖中可知,這個nginx容器是在mesos-slave1節點機(192.168.8.134)上創建的

注意:如果mesos-slave1節點機宕機或docker服務重啓,那麼這個nginx容器就會自動漂移到其他的slave節點機上;另外,通過上面方式創建好的容器,在單個slave節點機上刪除後,容器也會自動轉移到其他slave節點機器上,這樣就實現了在slave節點出現故障時容器自動轉移的高可用功能。

可以登陸mesos-slave1機器查看所創建的容器,如上可知:訪問Docker隨機啓動的端口是31725。

接着訪問mesos頁面,可以看到"Active Tasks"有剛纔創建的nginx任務了。(注意:只有當mesos訪問界面"Active Tasks"裏有容器創建任務時,才說明此容器真正創建成功了)

clip_image043

3)圖形化創建並運行容器

clip_image045

然後填寫創建容器的配置信息,如下圖,可以點擊"New Application"創建頁面右上角的"JSON Mode"模式,將上面創建nginx容器的json文件複製到這裏。

clip_image047

clip_image049

clip_image051

clip_image053

clip_image055

剩下以上紅框中的配置選項暫時先不配置,待以後測試。

clip_image057

4)刪除marathon創建的docker實例。如下圖,點擊"Destory"即可刪除

Marathon還可以對App應用實現手動擴縮的功能,選擇"Scale Application"進行快速擴容。如下圖,對上面已創建的tomcat應用容器進行擴展到2個Task(注意:這裏有2個slave節點,那麼擴展的Task實例最好是2個,即2個Instances;如果擴展多個Task,會發現多餘的創建失敗,這時候可以點擊"Configuration"修改,修改成2個)。

clip_image059

clip_image061

點擊下面的日誌"stderr"和"stdout"就會下載到本地。

clip_image063

也可以到mesos頁面查看或下載。點擊下面mesos頁面對應容器任務後面的"Sandbox"

clip_image065

clip_image067

clip_image069

具體配置可以參考marathon官方文檔:https://mesosphere.github.io/marathon/docs/persistent-volumes.html裏面有關於json文件的配置

6、marathon創建應用使用volumes

在marathon界面裏創建應用,可以使用volumes,即映射容器目錄到宿主機上,JSON文件內容如下:

{

"id": "nginx-1",

"cmd": null,

"cpus": 0.5,

"mem": 32,

"disk": 2048,

"instances": 1,

"container": {

"docker": {

"image": "docker.io/nginx",

"network": "BRIDGE",

"portMappings": [

{

"containerPort": 80,

"protocol": "tcp",

"name": null,

"labels": null

}

]

},

"type": "DOCKER",

"volumes": [

{

"containerPath": "/usr/share/nginx/html",

"hostPath": "/opt/web/www",

"mode": "RW"

}

]

}

}

clip_image071

clip_image073

clip_image075

# mkdir -p /opt/web/www //如上圖在192.168.8.135(mesos-slave2)節點上創建使用的卷目錄(volumes,即映射的宿主機目錄)

# echo "test" > /opt/web/www/index.html //映射的宿主機目錄下創建測試文件

clip_image076

注意事項:

 

1)映射到宿主機的目錄/opt/web/www要在每個slave節點機器上都要創建,並且裏面的文件要在每個slave節點機上都有,因爲容器重啓後會在各個slave節點之間隨機漂移。

2)上面映射的是nginx容器應用的站點目錄,默認創建後,/usr/share/nginx/html是空的(/opt/web/www目錄也是空的),所以容器默認訪問會出現403報錯。只需在slave節點的/opt/web/www目錄下編寫html文件(如index.html)即可訪問。

3)marathon裏創建好的容器應用,你可以在對應的slave機器上登陸容器內修改,但是這個容器應用一旦在marathon界面裏restart,那麼你之前的修改就沒有了。因爲重啓應用,就是再次使用初始鏡像進行構建了。

4)可以自己製作應用鏡像,在鏡像裏設定好應用的配置文件;或者將自己創建的容器提交爲新的鏡像。然後在marathon界面里根據自己定義的鏡像創建應用。

7、marathon創建應用指定訪問端口

默認情況下,marathon創建的應用訪問端口是隨機分配的,因爲hostPort默認配置的是0,具體看下面說明:

marathon創建應用後,會涉及到三個端口:containerPort:、hostPort、servicePort,其中:

1)containerPort:用來指定容器內部的一個端口。當使用BRIDGE或USER網絡模式連接Docker容器時,必須將這個屬性設置爲port mapping的一部分。

2)hostPort:用來指定綁定到主機上的一個端口。當使用BRIDGE或USER網絡模式,你可以指定一個port mapping將一個主機端口映射到容器端口。在HOST網絡模式下,默認的請求端口就是主機的端口。

請注意,主機端口只可以通過環境變量提供給一個任務。

3)servicePort:當您在Marathon上(不管是通過REST API或界面)創建一個新的應用程序,你可以指定一個或多個服務端口給它。

可以指定所有有效的端口號爲服務端口,也可以用0表示Marathon應該自動分配的可用服務端口給應用程序使用。如果你選擇自己的服務端口,你必須自己確保,這個端口在所有應用程序中是唯一的。

portMapping:在Docker BRIDGE模式下,在容器外部可被訪問到的端口都需要做端口映射。端口映射是一個包含host port, container port, service port和協議的元組。可以爲Marathon應用指定多個端口映射; 未指定hostPort,則其默認值爲0(意味着Marathon將隨機分配一個)。在Docker USER模式下,hostPort的語義爲稍有點變化:USER模式不需要指定hostPort,如果未指定Marathon不會自動分配一個隨機的。這允許在USER網絡模式下部署容器,包括containerPort和發現信息,但不暴露主機網絡上的這些端口(意味着將不消耗主機端口資源)。

marathon創建應用的網絡模式介紹:

1)BRIDGE網絡模式:指定Docker應用程序使用BRIDGE網絡模式。在這種模式下,容器端口(容器內部的端口)被映射到主機端口(宿主機上的端口)。在這種模式下,應用程序被綁定到容器內的指定端口,容器的端口被綁定到宿主機上的指定端口。

2)USER網絡模式:指定Docker應用程序使用USER網絡模式。在這種模式下,容器端口(容器內部的端口)被映射到主機端口(宿主機上的端口)。在這種模式下,應用程序被綁定到容器內的指定端口,容器的端口被綁定到宿主機上的指定端口。在與“用戶自定義”Docker網絡集成時,USER網絡模式將會非常有用。在Mesos世界,這種網絡通常是通過使用與Mesos CNI網絡隔離的 CNI 插件訪問。

3)HOST網絡模式:該種模式在Marathon應用爲非容器化而其它應用爲容器化的情況下使用。在這種模式下,應用程序直接綁定到宿主機上的一個或多個端口。

如下JSON文件內容,注意一下:如果hostport端口指定了,那麼serviceport端口也要指定(最好使用大端口),否則會導致應用容器創建失敗。

{

"id":"nginx-2",

"cpus":0.2,

"mem":32.0,

"instances": 1,

"constraints": [["hostname", "CLUSTER",""]],

"container": {

"type":"DOCKER",

"docker": {

"image": "docker.io/nginx",

"network": "BRIDGE",

"portMappings": [

{"containerPort": 80, "hostPort": 31030,"servicePort": 33180, "protocol": "tcp" }

]

}

}

}

在marathon界面裏創建應用,將上面的JSON文件內容複製到"JSON Mode"模式下。構建成功後,就會發現該應用容器的訪問端口就是上面自己定義的31030端口了(如下)

clip_image078

8、其他

在marathon中,應用是一個完整的概念。每個應用是一個典型的長運行的服務,這個服務有很多實例,並且是運行在多個slave節點機上。下面通過一個小示例說明下:

一個內嵌的shell腳步:
如下通過內嵌的shell腳步,編寫一個簡單的app,即:
打印Hello world到slave節點的/mnt/test文件中,然後sleep 5秒,周而復始。可以使用下面的應用定義文件(json格式)來描述應用(注意:cmd是要執行的命令。它的值會以/bin/sh -c ${cmd}的方式執行。):

 

{

    "id": "basic-0",

    "cmd": "while [ true ] ; do echo 'Hello world' >> /mnt/test ; sleep 5 ; done",

    "cpus": 0.1,

    "mem": 10.0,

    "instances": 1

}

在marathon界面裏添加應用,採用"JSON Mode "模式,如下:

clip_image080

不採用"JSON Mode"模式,即將上面的json文件內容粘貼進去後,去掉右上方的"JSON Mode"模式,也就是隻配置"General"選向,其他選項都不配置。注意:marathon裏的應用是一個長運行服務,所以shell腳本里要配置長運行動作。

clip_image082

然後到192.168.8.135這臺slave節點機上檢查,發現每隔5秒鐘,就會輸出"hello world"到/mnt/test文件中。如果這臺節點機出現故障,就會輸出到其他節點機上。

# tail -f /mnt/test

Hello world

Hello world

Hello world

Hello world

***************當你發現自己的才華撐不起野心時,就請安靜下來學習吧!**************

六、分佈式作業調度chronos

下圖是chronos任務調度系統的基本結構圖:

clip_image084

整體上來看,該系統由業務隊列、業務調度器、Chronos和Mesos組成。每個組成部分的說明如下:

  • 業務隊列:實際存放任務的隊列,隊列中的任務可以是按照優先級排序,也可以是FIFO. 多個業務隊列表示不同的業務,或者同一業務的不同隊列。

  • 業務調度器:根據一定的調度算法從多個業務隊列中選擇任務來調度。業務調度器接受Chronos的資源彙報,然後給這些資源分配任務。

  • Chronos:向業務調度器彙報剩餘資源,接受業務調度器提交的任務然後在Mesos集羣上面運行。

  • Mesos:運行各個Docker容器的載體。每個任務都在Docker容器中執行。

有一點需要解釋的是,在這個任務調度系統中,存在多個調度器:

  • Mesos中的調度器:一種通用的集羣資源分配算法,也就是DRF

  • Chronos中的調度器:在我們這個場景中,不需要定時調度任務。我們只需使用Chronos的Rest API提交一個Docker任務就可以了,這個Docker任務然後由Chronos調度到Mesos集羣上面運行。爲什麼不繞過Chronos直接提交任務到Mesos呢?Mesos本身是個兩級調度架構,如果繞過Chronos,那麼業務調度器就需要實現Mesos的上級調度接口,增加了複雜性。

  • 業務調度器:這就是和業務聯繫最緊密的地方了,此處必須考慮各種業務特性,比如各個業務隊列的任務總量、到達速率、優先級等等。

系統的核心在於業務調度器。經過調研各種調度算法,覺得YARN資源管理系統中的容量調度(Capacity Scheduler)適合多業務多隊列的場景。

以兩級隊列爲例來說明容量調度算法。下圖是Chronos資源的容量配置示例:

clip_image086

在該示意圖中,Chronos資源容量的20%分配給了業務1,80%分配給了業務2. 接着,20%容量中的40%分配給了業務隊列11,60%分配給了業務隊列12. 業務1和業務2是業務層次的隊列,業務隊列11、業務隊列12和業務隊列21是具體業務下的子隊列。

1、master節點上安裝配置chronos

拉取docker官方chronos鏡像

# docker pull mesosphere/chronos

# docker images

REPOSITORY TAG IMAGE ID CREATED SIZE

docker.io/mesosphere/chronos latest ec8accd8eb53 15 months ago 511 MB

# docker run -itd --net=host -e PORT0=18080 -e PORT1=8081 docker.io/mesosphere/chronos:latest --zk_hosts zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181 --master zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/mesos

# docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

a6f9ecd25d38 docker.io/mesosphere/chronos:latest "/chronos/bin/star..." 2 minutes ago Up 2 minutes gallant_wescoff

2、登錄chronos的web管理頁面

http://192.168.8.131:18080

clip_image088

3、在Chronos頁面,點擊“ADD JOB”創建任務

注意:時間是UTC時間

clip_image090

Name: 作業名稱

Command: 實際需要執行的命令

Schedule: 作業的調度規則,遵循ISO8601規範。由三部分組成,通過”/“符號分割。例如”R10/2012-10-01T05:52:00Z/PT2S”的三部分內容如下:

1> 重複執行作業務次數,如果只有一個R,則代表無限次執行。

2> 開始啓動作業的時間,如果爲空,則表示立即執行,其遵循ISO8601規範。

3> 執行頻率(即間隔多長時間執行一次),其定義方式如下:

P10M=10 months

PT10M=10 minutes

P1Y12M12D=1 years plus 12 months plus 12 days

P12DT12M=12 days plus 12 minutes

P1Y2M3DT4H5M6S=P(eriod) 1Y(ear) 2M(onth) 3D(ay) T(ime) 4H(our) 5M(inute) 6S(econd)

其中,P是必選字段,T是可選字段,用來區分M(inute)和M(onth)。

ScheduleTimeZone: 用來設置作業調度的時區。

Epsilon: 指因某些原因Chronos丟失了運行作業的下一次時間時,採用的固定運行週期。

Owner: 作業責任人的郵件地址。

Async: 作業是否在後臺運行。

clip_image092

clip_image094

clip_image096

chronos任務如果正常調度並執行的話,在mesos的web頁面上的“Active Tasks”下會有任務執行相關的信息,如下圖:

clip_image098

也可以在Chronos的任務頁面,點擊「Run」強制執行。

clip_image100

4、測試通過Chronos執行Docker任務

啓動Docker,抓取nginx鏡像,啓動chronos-nginx容器

A、創建json文件

# vi chronos-test.json

{

"container": {

"type": "DOCKER",

"image": "docker.io/nginx",

"network": "HOST"

},

"schedule": "R/2018-05-30T14:00:00.000Z/PT24H",

"name": "chronos-nginx",

"cpus": "0.3",

"mem": "32",

"uris": [],

"command": "/usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf"

}

network": "BRIDGE",因爲Docker默認的網絡模式是橋接,不指定默認也是BRIDGE,此處指定爲“HOST”。

B、通過BASH調用chronos的RestfulAPI調度接口運行並啓動chronos-nginx容器

# curl -L -H 'Content-Type: application/json' -X POST -d @/root/chronos-test.json http://192.168.8.131:18080/v1/scheduler/iso8601

在chronos的web管理界面上查看chronos-nginx容器運行的狀態如下圖:

clip_image102

在Mesos頁面確認任務的詳細信息,如下圖:

clip_image104

在節點上確認容器啓動,如下圖:

# docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

db3165da2284 docker.io/nginx "/bin/sh -c '/usr/..." 9 minutes ago Up 9 minutes 80/tcp mesos-97cce9bb-a884-454e-aed7-dea10d68737e

5、確認nginx網頁可以訪問

clip_image106

七、服務自動註冊與發現consul

consul的架構圖如下所示:

clip_image108

啓動consul後默認會監聽5個端口:
8300: replication、leader farwarding的端口
8301: lan gossip的端口
8302: wan gossip的端口
8500: web ui界面的端口
8600: 使用dns協議查看節點信息的端口

集羣角色:

上圖是官方的consul cluster的架構,Consul Cluster有Server和Client兩種角色。不管是Server還是Client,統稱爲Agent,Consul Client是相對無狀態的,只負責轉發RPC到Server,資源開銷很少。Server是一個有一組擴展功能的代理,這些功能包括參與Raft選舉,維護集羣狀態,響應RPC查詢,與其他數據中心交互WAN gossip和轉發查詢給leader或者遠程數據中心。

在每個數據中心,client和server是混合的。一般建議有3-5臺server。這是基於有故障情況下的可用性和性能之間的權衡結果,因爲越多的機器加入達成共識越慢,Server之間會選舉出一個leader。然而,並不限制client的數量,它們可以很容易的擴展到數千或者數萬臺。

consul更像一個“全棧”解決方案,內置了服務註冊與發現,具有健康檢查、Key/Value存儲、多數據中心的功能。個人比較偏愛他有三點:

1、開箱即用,方便運維:安裝包僅包含一個可執行文件,方便部署,無需其他依賴,與Docker等輕量級容器可無縫配合;

2、自帶ui界面,可以通過web界面直接看到註冊的服務,更新K/V;

3、採用GOSSIP協議進行集羣內成員的管理和消息的傳播,使用和etcd一樣的raft協議保證數據的一致性。

Consul提供的四個關鍵特性:

1、服務發現:提供HTTP和DNS兩種發現方式。

2、健康監測: 支持多種方式,HTTP、TCP、Docker、Shell腳本定製化監控。

3、K/V存儲: Key、Value的存儲方式。

4、多數據中心:Consul支持多數據中心。

當然Consul還有很多錦上添花的特性,比如:可視化Web界面配置模板“consul-template”等。

clip_image110

通過registrator的服務自動註冊,配合consul服務,在docker容器中能夠自動識別服務的域名,以便在mesos+marathon中部署docker實例能夠通過域名互通,也就是consul在docker容器中的自動發現。如果是線上consul server最少3臺做集羣,consul client是每個mesos-slave上跑一個,mesos-master也最少3臺集羣,marathon和zookeeper都應該是集羣的模式。

consul經常拿來和etcd、zookeeper來對比,他有和etcd一樣的服務發現、服務註冊功能,也有和etcd、zookeeper一樣的配置存儲功能,詳細的比對這裏就不描述了。下面是consul集羣的服務註冊,服務發現,健康檢查,和模板使用。

registrator服務註冊         | | consul服務端                     | |nginx代理                  | |應用服務

做健康檢查                      | |接收客戶端發送的健康         | | 如果nginx的模板       | |

確定本地服務是否正常     | |檢查信息做服務的註冊         | |更改,則                    | |

通報給consul服務端        | |如果客戶端有變動,則         | |nginx reload              | |

                                       | |更新代理的配置                   | |                                  | |

1、consul集羣服務安裝配置

# unzip consul_1.1.0_linux_amd64.zip -d /usr/local

# ln -s /usr/local/consul /usr/local/bin/consul

# mkdir -p /etc/consul.d //在每個consul節點上配置

command方式創建consul集羣:

# consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=192.168.8.131 -config-dir=/etc/consul.d -client 0.0.0.0

==> Multiple private IPv4 addresses found. Please configure one with 'bind' and/or 'advertise'.

報錯:Multiple private IPv4 addresses found. Please configure one with 'bind' and/or 'advertise'.

意思是:找到多個私有IPv4地址。請用“bind”綁定配置一個,就可以解決,根據提示.

[root@mesos-master1 ~]# nohup consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=mesos-master1 -config-dir=/etc/consul.d -bind=192.168.8.131 -client 0.0.0.0 -ui &

bootstrap_expect > 0: expecting 3 servers

==> Starting Consul agent...

==> Consul agent running!

Version: 'v1.1.0'

Node ID: 'cc8eebd0-6f84-6eee-f8cc-92ae7bf44494'

Node name: 'mesos-master1'

。。。。。。

2018/06/03 15:00:21 [INFO] agent: Started DNS server 0.0.0.0:8600 (tcp)

2018/06/03 15:00:21 [INFO] agent: Started HTTP server on [::]:8500 (tcp)

2018/06/03 15:00:21 [INFO] agent: started state syncer

2018/06/03 15:00:28 [ERR] agent: failed to sync remote state: No cluster leader

2018/06/03 15:00:30 [WARN] raft: no known peers, aborting election

2018/06/03 15:00:51 [ERR] agent: Coordinate update error: No cluster leader

2018/06/03 15:00:54 [ERR] agent: failed to sync remote state: No cluster leader

報錯:No cluster leader,是因爲其它兩臺consul的server端還沒有啓動!

啓動參數說明:
agent: 運行一個consul代理。
-server: 切換代理到服務器模式。
-bootstrap: 當consulserver-node1節點啓動之後,等待另外兩個節點的加入,3個節點聚齊後,之後纔開始選舉leader。
-ui: 啓用內置的靜態web UI服務器。
-data-dir: 路徑到數據目錄存儲代理狀態。
-bind: 設置集羣通信的綁定地址。
-client: 設置用於綁定客戶端訪問的地址。這包括RPC、DNS、HTTP和HTTPS(如果配置)。
-node: 此節點的名稱。 在集羣中必須是唯一的,如果你運行第2臺consul,可以寫server02、server03等。

-advertise:如果要讓節點在WAN網絡中被發現,就要配置這個參數,暴露出外網ip

[root@mesos-master2 ~]# nohup consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=mesos-master2 -config-dir=/etc/consul.d -bind=192.168.8.132 -client 0.0.0.0 -join 192.168.8.131 & //注意:此處的-join啓動選項,後面跟mesos-master1IP地址,或者也可以在mesos-master1上執行consul join 192.168.8.132/133,否則同樣還是會報以上錯誤!

[root@mesos-master3 ~]# nohup consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=mesos-master3 -config-dir=/etc/consul.d -bind=192.168.8.133 -client 0.0.0.0 -join 192.168.8.131 &

很快三臺mesos-master上的consul都會打印:

consul: New leader elected: mesos-master1

證明此時leader已經選出,集羣可以正常工作。

[root@mesos-slave1 ~]# nohup consul agent -client 192.168.8.134 -data-dir=/tmp/consul -config-dir=/etc/consul.d -node=mesos-slave1 -bind=192.168.8.134 -join 192.168.8.131 &

[root@mesos-slave2 ~]# nohup consul agent -client 192.168.8.135 -data-dir=/tmp/consul -config-dir=/etc/consul.d -node=mesos-slave2 -bind=192.168.8.135 -join 192.168.8.131 &

[root@mesos-master1 ~]# consul info consul

集羣參數put/get測試:

[root@mesos-slave1 ~]# consul kv put key value

Success! Data written to: key

[root@mesos-master2 ~]# consul kv get key

value

5臺機器獲取key的值均爲value,如此可知key的值已經在集羣中同步。

[root@mesos-master1 ~]# consul members

Node Address Status Type Build Protocol DC Segment

mesos-master1 192.168.8.131:8301 alive server 1.1.0 2 dc <all>

mesos-master2 192.168.8.132:8301 alive server 1.1.0 2 dc <all>

mesos-master3 192.168.8.133:8301 alive server 1.1.0 2 dc <all>

mesos-slave1 192.168.8.134:8301 alive client 1.1.0 2 dc <default>

mesos-slave2 192.168.8.135:8301 alive client 1.1.0 2 dc <default>

[root@mesos-master1 ~]# consul operator raft list-peers

Node ID Address State Voter RaftProtocol

mesos-master1 f0522384-3554-61e7-57ce-607a583a179f 192.168.8.131:8300 leader true 3

mesos-master2 b5ffff40-f993-0f9e-7877-4e0bffdabb3d 192.168.8.132:8300 follower true 3

mesos-master3 fc42ff3f-617f-9524-090b-b8c5584b3cac 192.168.8.133:8300 follower true 3

可以看出集羣中mesos-master1是leader,mesos-master2和mesos-master3都是follower

[root@mesos-master1 ~]# consul info |grep leader

leader = false

leader_addr = 192.168.8.132:8300

[root@mesos-master1 ~]# consul catalog services

consul

mesos

配置文件方式創建consul集羣:

在其中一個mesos master節點上配置bootstrap配置,該節點就是consul集羣中的bootstrap節點(192.168.8.131)。

# cat > /etc/consul.d/bootstrap/config.json <<EOF

{

"bootstrap": true,

"server": true,

"datacenter": "dc",

"data_dir": "/var/consul",

"log_level": "INFO",

"enable_syslog": true,

"disable_update_check": true,

"ui": true

}

EOF

在其他的mesos master 節點上配置server配置,這些節點就是consul集羣中的server節點(192.168.8.132/192.168.8.133)。

# cat > /etc/consul.d/server/config.json <<EOF

{

"bootstrap": false,

"server": true,

"datacenter": "dc",

"data_dir": "/var/consul",

"log_level": "INFO",

"enable_syslog": true,

"disable_update_check": true,

"start_join": ["192.168.8.131", "192.168.8.133"],

"ui": true

}

EOF

注意: start_join: 記錄了其他consul server節點的IP。
在所有的mesos agent 節點上配置client配置,這些節點也就是consul集羣中的client節點

# cat > /etc/consul.d/client/config.json <<EOF

{

"server": false,

"datacenter": "dc",

"data_dir": "/var/consul",

"log_level": "INFO",

"enable_syslog": true,

"disable_update_check": true,

"start_join": ["192.168.8.131", "192.168.8.132", "192.168.8.133"],

"ui": true

}

EOF

注意:start_join: 記錄了所有的consul server的IP。
啓動Consul集羣
在consul bootstrap節點啓動:

# consul agent -config-dir /etc/consul.d/bootstrap/ -bind=192.168.8.131 -client=0.0.0.0 >> /var/log/consul.log 2>&1 &

在所有consul server節點啓動:

# consul agent -config-dir /etc/consul.d/server/ -bind=192.168.8.132 -client=0.0.0.0 >> /var/log/consul.log 2>&1 &

在所有consul client節點啓動:

consul agent -config-dir /etc/consul.d/client/ -bind=192.168.8.134 -client=0.0.0.0 >> /var/log/consul.log 2>&1 &

注意: self_ip是本機的IP。
檢查consul集羣狀態:
在consul集羣中任意一個節點執行

2、consul的DNS服務發現

consul支持dns的服務註冊:

# dig @127.0.0.1 8600 mesos-master1.node.consul +short
192.168.8.131
# dig @127.0.0.1 8600 mesos-master2.node.consul +short
192.168.8.132
# dig @127.0.0.1 8600 mesos-master3.node.consul +short
192.168.8.133
3、consul的常用http api

對consul來說一個重要的接口就是RESTful HTTP API,http api可用於操作nodes, services, checks, configuration等等的CRUD(create, read, update and delete)詳見Consul Http Api,下面是幾個例子?說明

http api可以通過鏈接請求:

查看當前consul節點的服務

# curl mesos-master1:8500/v1/agent/checks |python -m json.tool

查看當前consul集羣的leader

# curl mesos-master1:8500/v1/status/leader

查看當前節點的信息

# curl mesos-master1:8500/v1/operator/raft/configuration |python -m json.tool

查看mesos-slave1節點的健康檢查信息

# curl mesos-master1:8500/v1/health/node/mesos-slave1 |python -m json.tool

查看webserver服務的信息

# curl -s http://mesos-master1:8500/v1/catalog/service/webserver | python -m json.tool

# 集羣server成員

#curl 127.0.0.1:8500/v1/status/peers

# 集羣Raft leader

#curl 127.0.0.1:8500/v1/status/leader

# 註冊的所有服務

#curl 127.0.0.1:8500/v1/catalog/services

# 服務信息

#curl 127.0.0.1:8500/v1/catalog/services/nginx

# 集羣節點詳細信息

#curl 127.0.0.1:8500/v1/catalog/nodes

4、registrator容器實現服務自動註冊

服務發現與註冊

1. 具體流程

服務註冊中心:作爲整個架構中的核心,要支持分佈式持久化存儲註冊信息變動實時通知消費者。

服務提供者:服務以容器化方式部署(實現服務端口動態生成),可以通過 的方式來管理。通過 檢測到 進程信息以完成服務的自動註冊

服務消費者:要使用服務提供者提供的服務,和服務提供者往往是動態相互轉位置的。

一個較爲完整的服務註冊與發現流程如下:

clip_image111

註冊服務:服務提供者到註冊中心註冊

訂閱服務:服務消費者到註冊中心訂閱服務信息,對其進行監聽

緩存服務列表:本地緩存服務列表,減少與註冊中心的網絡通信;

調用服務:查找本地緩存,找不到再去註冊中心拉取服務地址,然後發送服務請求;

變更通知:服務節點變動時 (新增刪除等),註冊中心將通知監聽節點,更新服務信息。

2. 相關組件

一個服務發現系統主要由三部分組成:

註冊器(registrator):根據服務運行狀態,註冊/註銷服務。主要要解決的問題是,何時發起註冊/註銷動作。

註冊表(registry):存儲服務信息。常見的解決方案有zookeeper、etcd、cousul等。

發現機制(discovery):從註冊表讀取服務信息,給用戶封裝訪問接口。

通過Registrator收集需要註冊到Consul作爲Nginx後端服務器信息然後註冊到Consul key/value.Consul-template去Consul key/value中讀取信息,然後自動修改Nginx配置文件並平滑重啓Nginx,不需要修改nginx.conf。

分別在mesos-slave1 和mesos-slave2 上都創建:

利用chronos任務調度下載registrator

clip_image113

clip_image115

利用chronos任務調度在所有的mesos-slave上運行registrator

clip_image117

Command: docker run -d --name registrator --network=host -v /var/run/docker.sock:/tmp/docker.sock --restart=always gliderlabs/registrator:latest --ip 192.168.8.134 consul://192.168.8.131:8500

參數說明:
--network:把運行的docker容器設定爲host網絡模式;
-v /var/run/docker.sock:把宿主機的Docker守護進程(Docker daemon)默認監聽的Unix域套接字掛載到容器中;
--ip : 剛纔把network指定了host模式,所以我們指定下IP爲宿主機的IP;
consul: 最後這個選項是配置consul服務器的IP和端口。

服務註冊前:

clip_image119

通過marathon啓動tomcat服務:

[root@mesos-master1 ~]# curl -X POST http://192.168.8.131:8080/v2/apps -d @/root/tomcat.json -H "Content-type: application/json"

{"id":"/tomcat-1","backoffFactor":1.15,"backoffSeconds":1,"constraints":[["hostname","CLUSTER",""]],"container":{"type":"DOCKER","docker":{"forcePullImage":false,"image":"docker.io/tomcat","parameters":[],"privileged":false},"volumes":[],"portMappings":[{"containerPort":8080,"hostPort":0,"labels":{},"protocol":"tcp","servicePort":0}]},"cpus":0.5,"disk":0,"executor":"","instances":1,"labels":{},"maxLaunchDelaySeconds":3600,"mem":64,"gpus":0,"networks":[{"mode":"container/bridge"}],"requirePorts":false,"upgradeStrategy":{"maximumOverCapacity":1,"minimumHealthCapacity":1},"version":"2018-06-10T08:34:47.600Z","killSelection":"YOUNGEST_FIRST","unreachableStrategy":{"inactiveAfterSeconds":0,"expungeAfterSeconds":0},"tasksStaged":0,"tasksRunning":0,"tasksHealthy":0,"tasksUnhealthy":0,"deployments":[{"id":"346444ac-978b-42d6-8975-6b01fd6869ab"}],"tasks":[]}

clip_image121

服務註冊後:

clip_image123

clip_image125

從上圖可以看出,剛纔創建的marathon應用tomcat容器服務已經註冊到了 consul中。

[root@mesos-master1 ~]# curl 127.0.0.1:8500/v1/catalog/services

{"consul":[],"mesos":["master","leader"],"tomcat":[]}

八、負載均衡

服務被調整後,負載均衡要想動態重新分配負載,就需要修改相應的配置文件,consul-template就是解決這個問題的應用,通過監聽consul的註冊信息,來自動完成負載均衡相應的配置更新。

安裝nginx,此處略過。。。

安裝配置consul-template

安裝consul-template非常簡單,下載二進制包即可使用。

1、下載consul-template
下載地址:https://releases.hashicorp.com/consul-template/0.19.4/consul-template_0.19.4_linux_amd64.zip

# wget https://releases.hashicorp.com/consul-template/0.19.4/consul-template_0.19.4_linux_amd64.zip

2、解壓並安裝到/usr/bin目錄

# unzip consul-template_0.19.4_linux_amd64.zip

# mv consul-template /usr/bin/

# consul-template -v

consul-template v0.19.4 (68b1da2)

3、創建nginx模板

# cd /usr/local/nginx

# mkdir consul

# cd consul/

# vi nginx.ctmpl

upstream http_backend {

{{range service "nginx"}}

server {{ .Address }}:{{ .Port }} max_fails=3 fail_timeout=90;

{{ end }}

}

server {

listen 8085;

server_name localhost;

location / {

proxy_pass http://http_backend;

}

}

4、修改nginx.conf

# grep "consul" nginx.conf

include /usr/local/nginx/consul/*.conf; //添加這一行在http模塊

# /usr/local/nginx/sbin/nginx //啓動nginx服務

5、啓動consul-template

# ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx

# cd /usr/local/nginx/consul/

# consul-template --consul-addr 192.168.8.131:8500 --template /usr/local/nginx/consul/nginx.ctmpl:/usr/local/nginx/consul/vhost.conf:"nginx -s reload" --log-level=info
2018/06/18 13:15:45.719503 [INFO] consul-template v0.19.4 (68b1da2)
2018/06/18 13:15:45.720675 [INFO] (runner) creating new runner (dry: false, once: false)
2018/06/18 13:15:45.721967 [INFO] (runner) creating watcher
2018/06/18 13:15:45.723542 [INFO] (runner) starting
2018/06/18 13:15:45.724051 [INFO] (runner) initiating run
2018/06/18 13:15:45.728395 [INFO] (runner) initiating run
2018/06/18 13:15:45.731084 [INFO] (runner) rendered "/usr/local/nginx/consul/nginx.ctmpl" => "/usr/local/nginx/consul/vhost.conf"
2018/06/18 13:15:45.732215 [INFO] (runner) executing command "nginx -s reload" from "/usr/local/nginx/consul/nginx.ctmpl" => "/usr/local/nginx/consul/vhost.conf"
2018/06/18 13:15:45.733669 [INFO] (child) spawning: nginx -s reload
 
--consul-addr:指定consul服務的ip和端口;
./nginx.ctmpl:這是用nginx.ctmpl這個模板來啓動進程,這是寫的相對路徑,也可以寫絕對路徑;
vhost.conf:nginx.ctmpl模板生成後的文件名,這也可以寫絕對路徑,如果不寫絕對路徑,這個文件就在當前目錄生成(/usr/local/nginx/consul/)
 
由於consul-template在前臺運行,所以我們在打開一個終端驗證。

[root@mesos-master1 ~]# ps -ef | grep consul-template

root 41543 16705 0 19:33 pts/2 00:00:00 consul-template --consul-addr 192.168.8.131:8500 --template ./nginx.ctmpl:vhost.conf --log-level=info

root 41758 38089 0 19:35 pts/1 00:00:00 grep --color=auto consul-template

[root@mesos-master1 ~]# ll /usr/local/nginx/consul/

total 8

-rw-r--r-- 1 root root 333 Jun 10 18:26 nginx.ctmpl

-rw-r--r-- 1 root root 255 Jun 10 19:33 vhost.conf

在consul目錄下,是不是發現多了一個文件vhost.conf,就是剛纔啓consul-template時生成的。查看下vhost.conf的內容,目前upstraem的server配置爲空,還沒有docker主機加入進來:

[root@mesos-master1 ~]# cat /usr/local/nginx/consul/vhost.conf

upstream http_backend {

server {{ .Address }}:{{ .Port }} max_fails=3 fail_timeout=90;

}

server {

listen 8085;

server_name localhost;

location / {

proxy_pass http://http_backend;

}

}

通過marathon創建nginx容器實例:

[root@mesos-master1 ~]# curl -X POST http://192.168.8.132:8080/v2/apps -d @/root/nginx.json -H "Content-type: application/json"

{"id":"/nginx-1","backoffFactor":1.15,"backoffSeconds":1,"container":{"type":"DOCKER","docker":{"forcePullImage":false,"image":"docker.io/nginx","parameters":[],"privileged":false},"volumes":[{"containerPath":"/usr/share/nginx/html","hostPath":"/opt/web/www","mode":"RW"}],"portMappings":[{"containerPort":80,"hostPort":0,"labels":{},"protocol":"tcp","servicePort":0}]},"cpus":0.5,"disk":2048,"executor":"","instances":1,"labels":{},"maxLaunchDelaySeconds":3600,"mem":32,"gpus":0,"networks":[{"mode":"container/bridge"}],"requirePorts":false,"upgradeStrategy":{"maximumOverCapacity":1,"minimumHealthCapacity":1},"version":"2018-06-18T13:12:27.037Z","killSelection":"YOUNGEST_FIRST","unreachableStrategy":{"inactiveAfterSeconds":0,"expungeAfterSeconds":0},"tasksStaged":0,"tasksRunning":0,"tasksHealthy":0,"tasksUnhealthy":0,"deployments":[{"id":"0b2969ac-a65d-4ff9-b7b9-f2c5cc29312f"}],"tasks":[]}

clip_image127

[root@mesos-master1 ~]# cat /usr/local/nginx/consul/vhost.conf

upstream http_backend {

server 192.168.8.134:31581 max_fails=3 fail_timeout=90;

server 192.168.8.134:31818 max_fails=3 fail_timeout=90;

server 192.168.8.135:31814 max_fails=3 fail_timeout=90;

}

server {

listen 8085;

server_name localhost;

location / {

proxy_pass http://http_backend;

}

}

clip_image129

[root@mesos-slave1 ~]# echo "mesos-slave1" >/opt/web/www/index.html

[root@mesos-slave2 ~]# echo "mesos-slave2" >/opt/web/www/index.html

可以看到,在通過marathon創建了3個nginx的容器實例後,nginx的虛擬主機配置文件已經被consul-template動態修改。然後訪問一下nginx服務器的IP地址,http://192.168.8.131:8085,從下圖可以看出是可以訪問的:

clip_image131

clip_image133

可以看到nginx的8085負載均衡是可以正常輪詢的!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章