隨著"網際網路+"時代的業務增長、變化速度及大規模計算的需求,廉價的、高可擴充套件的分散式x86叢集已成為標準解決方案,如Google已經在幾千萬臺伺服器上部署分散式系統。Docker及其相關技術的出現和發展,又給大規模叢集管理帶來了新的想象空間。如何將二者進行有效地結合?下面將記錄使用Mesos+Zookeeper+Marathon+Docker分散式部署Paas雲平臺環境,其中:
1)Mesos:Mesos採用與Linux kernerl相同的機制,只是執行在不同的抽象層次上。Mesos kernel利用資源管理和排程的API在整個資料中心或雲環境中執行和提供引用(例如,Hadoop,Spark,Kafaka,Elastic Search)。 2)Zookeeper:zooKeeper是一個分散式的,開放原始碼的分散式應用程式協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要元件。它是一個為分散式應用提供一致性服務的軟體,提供的功能包括:配置維護、名字服務、分散式同步、組服務等。 3)Marathon:marathon是一個mesos框架,能夠支援執行長服務,比如web應用等。是叢集的分散式Init.d,能夠原樣執行任何Linux二進位制釋出版本,如Tomcat Play等等,可以叢集的多程式管理。也是一種私有的Pass,實現服務的發現,為部署提供提供REST API服務,有授權和SSL、配置約束,通過HAProxy實現服務發現和負載平衡 4)Docker:Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的 Linux 機器上,也可以實現虛擬化。
一、Mesos是什麼?
Mesos是Apache下的開源分散式資源管理框架,它被稱為是分散式系統的核心。Mesos能夠在同樣的叢集機器上執行多種分散式系統型別,更加動態有效率低共享資源。提供失敗偵測,任務釋出,任務跟蹤,任務監控,低層次資源管理和細粒度的資源共享,可以擴充套件伸縮到數千個節點。Mesos已經被Twitter用來管理它們的資料中心。
Mesos中的基本術語解釋:
1)Mesos-master:主要負責管理各個framework和slave,並將slave上的資源分配給各個framework 2)Mesos-slave:負責管理本節點上的各個mesos-task,比如:為各個executor分配資源 3)Framework:計算框架,如:Hadoop,Spark等,通過MesosSchedulerDiver接入Mesos 4)Executor:執行器,安裝到mesos-slave上,用於啟動計算框架中的task。 其中: 1)Mesos-master是整個系統的核心,負責管理接入mesos的各個framework(由frameworks_manager管理)和 slave(由slaves_manager管理),並將slave上的資源按照某種策略分配給framework(由獨立插拔模組Allocator管 理)。 2)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解決該問題。 3)Framework是指外部的計算框架,如Hadoop,Mesos等,這些計算框架可通過註冊的方式接入mesos,以便mesos進行統一管理 和資源分配。Mesos要求可接入的框架必須有一個排程器模組,該排程器負責框架內部的任務排程。 當一個framework想要接入mesos時,需要修 改自己的排程器,以便向mesos註冊,並獲取mesos分配給自己的資源, 這樣再由自己的排程器將這些資源分配給框架中的任務,也就是說,整個mesos系統採用了雙層排程框架: 第一層,由mesos將資源分配給框架;第二層, 框架自己的排程器將資源分配給自己內部的任務。當前Mesos支援三種語言編寫的排程器,分別是C++,java和python,為了向各種排程器提供統 一的接入方式,Mesos內部採用 C++實現了一個MesosSchedulerDriver(排程器驅動器),framework的排程器可呼叫該 driver中的介面與Mesos-master互動,完成一系列功能(如註冊,資源分配等)。 4)Executor主要用於啟動框架內部的task。由於不同的框架,啟動task的介面或者方式不同,當一個新的框架要接入mesos時,需要編寫 一個executor,告訴mesos如何啟動該框架中的task。為了向各種框架提供統一的執行器編寫方式, Mesos內部採用C++實現了一個 MesosExecutorDiver(執行器驅動器),framework可通過該驅動器的相關介面告訴mesos啟動task的方法。
先來看下Mesos的基礎架構
首先Mesos是一個Master/Agent的架構方式,其中:
1)Master負責資源的統一管理跟任務的分發 2)Agent負責起停執行器,彙報主機資源、執行器狀態等資訊。 3)一般情況下,會啟動3個以上Master,以確保高可用,Master的狀態由Zookeeper維護。 4)Framework是Mesos上的排程框架,Marathon Hadoop Chonous都是比較常見的任務排程框架。 這樣的架構給人的整體感受就清晰明朗了。另外: 1)每臺機器上都會部署一個Mesos-Agent,Agent會把資訊彙報給Master。 2)排程器scheduler向Mesos-Master請求資源,Mesos-Master把所有可用的資源都反饋給Scheduler,Scheduler根據自己的規則決定該部署到哪一臺。大致就是這樣一個流程。
Mesos總體架構圖如下:
上圖展示了mesos的重要組成部分:
1)mesoso由一個master程式管理執行著每個客戶端節點的salve程式和跑任務的mesos計算框架。master程式通過計算框架可以很細緻的管理cpu和記憶體等,從而提供資源。 每個資源提供與包含了一個清單(slave ID, resource1: amount1, resource2, amount2, …),master會根據現有的政府決定提供每個計算框架多少資源,例如公平分享或者根據優先順序分享。 為了支援不同種的政策,master通過外掛機制新增了一個allocation模組使之分配資源更簡單方便。 2)一個計算框架執行在兩個元件之上,一個是scheduler,他是master提供資源的註冊中心,另一個是executor程式,用來發起在slave節點上執行計算框架的任務。 master決定給每個計算框架提供多少計算資源,計算框架的的排程去選擇使用哪個資源。當一個計算框架接受了提供的資源,他會通過mesos的任務描述執行程式,mesos也會在相應的slave上發起任務。
從上面圖中可以看到,Mesos有Framework(Framework裡面有Scheduler), Master(Master裡面有Allocator)、Agent、Executor、Task幾部分組成。
這裡面有兩層的Scheduler,一層在Master裡面,Allocator會將資源公平的分給每一個Framework,二層在Framework裡面,Framework的Scheduler將資源按規則分配給Task。
Mesos的這幾個角色在一個任務執行的生命週期中,相互關係如下:
Agent會將資源彙報給Master,Master會根據Allocator的策略將資源offer給Framework的Scheduler。Scheduler 可以accept這個資源,執行一個Task,Master將Task交給Agent,Agent交給Executor去真正的執行這個Task。
Mesos資源提供的例子
簡單梳理下以上圖中的流程步驟:
1)slave 1 報告給master他擁有4核cpu和4G剩餘記憶體,matser呼叫allocation政策模組,告訴salve 1 計算框架1應該被提供可用的資源。 2)master給計算框架1傳送一個在slave1上可用的資源描述。 3)計算框架的排程器回覆給master執行在slave上兩個任務的相關資訊,任務1需使用2個cpu,記憶體1G,任務2需使用1個cpu,2G記憶體。 4)最後,master傳送任務給slave,分配適當的給計算框架執行器,繼續發起兩個任務(圖上虛線處),因為仍有1個cpu和1G記憶體未分配,allocation模組現在或許提供剩下的資源給計算框架2。 除此之外,當任務完成,新的資源成為空閒時,這個資源提供程式將會重複。
Mesos框架是一個在Mesos上執行分散式應用的應用程式,它有兩個元件:
1)排程器 : 與Mesos互動,訂閱資源,然後在mesos從伺服器中載入任務。 2)執行器 : 從框架的環境變數 配置中獲得資訊,在mesos從伺服器中執行任務。
下面看看其是如何實現資源呼叫?Mesos通過"resources offers" 分配資源,資源其實是當前可用資源的一個快照,排程器將使用這些資源在mesos從伺服器上執行任務。
Mesos主從伺服器排程資源的順序圖如下:
首先由Mesos主伺服器查詢可用資源給排程器,第二步排程器向主伺服器發出載入任務,主伺服器再傳達給從伺服器,從伺服器向執行器命令載入任務執行,執行器執行任務以後,將狀態反饋上報給從伺服器,最終告知排程器 。
從伺服器下管理多個執行器,每個執行器是一個容器,以前可以使用Linux容器LXC,現在使用Docker容器。
Mesos失敗恢復和高可用性
Mesos主伺服器使用Zookeeper進行服務選舉和發現。它有一個註冊器記錄了所有執行任何和從伺服器資訊,使用MultiPaxos進行日誌複製實現一致性。 Mesos有一個從伺服器恢復機制,無論什麼時候一個從伺服器當機了,使用者的任務還是能夠繼續執行,從伺服器會將一些關鍵點資訊如任務資訊狀態更新持久化到本地磁碟上,重新啟動時可以從磁碟上恢復執行這些任務(類似Java中的鈍化和喚醒)
二、 Zookeeper是什麼?
ZooKeeper是用來給叢集服務維護配置資訊,域名服務,提供分散式同步和提供組服務。所有這些型別的服務都使用某種形式的分散式應用程式。ZooKeeper是一個分散式的,開放原始碼的協調服務,是的Chubby一個的實現,是Hadoop和Hbase的重要元件。
ZooKeeper角色
領導者(leader):領導者負責投票發起和決議,更新系統狀態 跟隨者(follwoer):follower用於接收客戶請求並向客戶端返回結果,在選主過程中參與投票 觀察者:ObServer可以接受客戶端連線,將寫請求轉發給leader節點,但ObServer不參加投票過程,只同步leader的狀態,ObServer的目的是為了擴充系統,提高讀取速度。 客戶端:請求發起方
ZooKeeper的工作原理
Zookeeper的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫做Zab協議。Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。當服務啟動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和leader的狀態同步以後,恢復模式就結束了。狀態同步保證了leader和Server具有相同的系統狀態。 為了保證事務的順序一致性,zookeeper採用了遞增的事務id號(zxid)來標識事務。所有的提議(proposal)都在被提出的時候加上了zxid。實現中zxid是一個64位的數字,它高32位是epoch用來標識leader關係是否改變,每次一個leader被選出來,它都會有一個新的epoch,標識當前屬於那個leader的統治時期。低32位用於遞增計數。 每個Server在工作過程中有三種狀態: 1)LOOKING:當前Server不知道leader是誰,正在搜尋 2)LEADING:當前Server即為選舉出來的leader 3)FOLLOWING:leader已經選舉出來,當前Server與之同步
ZooKeeper選主流程
當leader崩潰或者leader失去大多數的follower,這時候zk進入恢復模式,恢復模式需要重新選舉出一個新的leader,讓所有的Server都恢復到一個正確的狀態。Zk的選舉演算法有兩種:一種是基於basic paxos實現的,另外一種是基於fast paxos演算法實現的。系統預設的選舉演算法為fast paxos。先介紹basic paxos流程: 1)選舉執行緒由當前Server發起選舉的執行緒擔任,其主要功能是對投票結果進行統計,並選出推薦的Server; 2)選舉執行緒首先向所有Server發起一次詢問(包括自己); 3)選舉執行緒收到回覆後,驗證是否是自己發起的詢問(驗證zxid是否一致),然後獲取對方的id(myid),並儲存到當前詢問物件列表中,最後獲取對方提議的leader相關資訊(id,zxid),並將這些資訊儲存到當次選舉的投票記錄表中; 4)收到所有Server回覆以後,就計算出zxid最大的那個Server,並將這個Server相關資訊設定成下一次要投票的Server; 5)執行緒將當前zxid最大的Server設定為當前Server要推薦的Leader,如果此時獲勝的Server獲得n/2 + 1的Server票數, 設定當前推薦的leader為獲勝的Server,將根據獲勝的Server相關資訊設定自己的狀態,否則,繼續這個過程,直到leader被選舉出來。 通過流程分析我們可以得出:要使Leader獲得多數Server的支援,則Server總數必須是奇數2n+1,且存活的Server的數目不得少於n+1. 每個Server啟動後都會重複以上流程。在恢復模式下,如果是剛從崩潰狀態恢復的或者剛啟動的server還會從磁碟快照中恢復資料和會話資訊,zk會記錄事務日誌並定期進行快照,方便在恢復時進行狀態恢復。
選主的具體流程圖如下所示:
fast paxos(演算法優化)流程是在選舉過程中,某Server首先向所有Server提議自己要成為leader,當其它Server收到提議以後,解決epoch和zxid的衝突,並接受對方的提議,然後向對方傳送接受提議完成的訊息,重複這個流程,最後一定能選舉出Leader。其流程圖如下所示:
ZooKeeper同步流程
選完leader以後,zookeeper就進入狀態同步過程。 1)leader等待server連線; 2)Follower連線leader,將最大的zxid傳送給leader; 3)Leader根據follower的zxid確定同步點; 4)完成同步後通知follower 已經成為uptodate狀態; 5)Follower收到uptodate訊息後,又可以重新接受client的請求進行服務了。
流程圖如下所示:
ZooKeeper工作流程
1)Leader工作流程
Leader主要有三個功能: 1)恢復資料; 2)維持與Learner的心跳,接收Learner請求並判斷Learner的請求訊息型別; 3)Learner的訊息型別主要有PING訊息、REQUEST訊息、ACK訊息、REVALIDATE訊息,根據不同的訊息型別,進行不同的處理。 PING訊息是指Learner的心跳資訊;REQUEST訊息是Follower傳送的提議資訊,包括寫請求及同步請求;ACK訊息是Follower的對提議的回覆,超過半數的Follower通過,則commit該提議;REVALIDATE訊息是用來延長SESSION有效時間。
Leader的工作流程簡圖如下所示,在實際實現中,流程要比下圖複雜得多,啟動了三個執行緒來實現功能。
2)Follower工作流程
Follower主要有四個功能: 1)向Leader傳送請求(PING訊息、REQUEST訊息、ACK訊息、REVALIDATE訊息); 2)接收Leader訊息並進行處理; 3)接收Client的請求,如果為寫請求,傳送給Leader進行投票; 4)返回Client結果。 Follower的訊息迴圈處理如下幾種來自Leader的訊息: 1)PING訊息: 心跳訊息; 2)PROPOSAL訊息:Leader發起的提案,要求Follower投票; 3)COMMIT訊息:伺服器端最新一次提案的資訊; 4)UPTODATE訊息:表明同步完成; 5)REVALIDATE訊息:根據Leader的REVALIDATE結果,關閉待revalidate的session還是允許其接受訊息; 6)SYNC訊息:返回SYNC結果到客戶端,這個訊息最初由客戶端發起,用來強制得到最新的更新。
Follower的工作流程簡圖如下所示,在實際實現中,Follower是通過5個執行緒來實現功能的。
三、搞懂marathon
Marathon是一個成熟的,輕量級的,擴充套件性很強的Apache Mesos的容器編排框架,它主要用來排程和執行常駐服務(long-running service),提供了友好的介面和Rest API來建立和管理應用。marathon是一個mesos框架,能夠支援執行長服務,比如web應用等,它是叢集的分散式Init.d,能夠原樣執行任何Linux二進位制釋出版本,如Tomcat Play等等,可以叢集的多程式管理。也是一種私有的Pass,實現服務的發現,為部署提供提供REST API服務,有授權和SSL、配置約束,通過HAProxy實現服務發現和負載平衡。
這樣,我們可以如同一臺Linux主機一樣管理數千臺伺服器,它們的對應原理如下圖,使用Marathon類似Linux主機內的init Systemd等外殼管理,而Mesos則不只包含一個Linux核,可以排程數千臺伺服器的Linux核,實際是一個資料中心的核心:
Marathon中重要的概念介紹
1)Application是Marathon中一個重要的核心概念,它代表了一個長服務。
2)Application definition表示一個長服務的定義,規定了一個Application啟動和執行時的所有行為。Marathon提供了兩種方式讓你來定義你的長服務,第一種通過Portal來定義,它方便終端使用者的理解和使用,另一種是通過JSON格式的檔案來定義,並通過RestAPI的方式來建立和管理這個Application,這種方式方便和第三方的系統進行整合,提供了再次的可程式設計介面。
3)Application instance表示一個Application的例項,也稱作Mesos的一個task。Marathon可以為一個Application建立和管理多個例項,並可以動態的增大和減小某個Application例項的個數,並且通過Marathon-lb實現服務發現和負載均衡。
4)Application Group:Marathon可以把多個Application組織成一棵樹的結構,Group稱為這個樹的樹枝,Application稱為這個樹的葉子。同一個Group中的Application可以被Marathon統一管理。
5)Deployments:對Application或者Group的definition的一次修改的提交稱為一次deployment。它包括建立,銷燬,擴容縮容Application或者Group等。多個deployments可以同時進行,但是對於一個應用的deployments必須是序列的,如果前一個deployment沒有結束就執行下一個deployment,那麼它將會被拒絕。
--------------------------------------------------------------------------------------------------------------------------------------
四、Mesos+Zookeeper+Marathon的Docker管理平臺部署過程記錄
1)伺服器架構
機器資訊如下:
這裡部署的機器為3個Mastser控制節點,3個Slave執行節點,其中: zookeeper、Mesos-master、marathon執行在Master端;Mesos-slave和docker執行在Slave端;需要修改zk的內容來保證slave能夠被master發現和管理 這裡為了測試方便,全部採用centos7版本系統。當然,在實際生產環境中,也不一定非要要求master和slave端的伺服器版本一致,不一樣的版本系統也可以。 (當機器數量沒有這麼多比如只有兩臺機器的情況下,可以將一臺機器即作為Mesos-Master也作為Mesos-Slave,另一臺作為Mesos-Slave,也就是一主兩從的結構)
為了直觀的理解,簡單的畫了一張架構圖:
2)配置mesos-master(3臺master節點都要操作)
1)關閉防火牆和selinux 關閉selinux [root@master-1 ~]# vim /etc/sysconfig/selinux SELINUX=disabled [root@master-1 ~]# setenforce 0 #臨時關閉。reboot重啟機器後,使得上面配置生效,就永久關閉selinux了 [root@master-1 ~]# getenforce Permissive 關閉iptables防火牆。 如果不關閉,需要開啟2181,5050,8080埠 [root@master-1 ~]# vim /etc/sysconfig/iptables ....... -A INPUT -p tcp -m state --state NEW -m tcp --dport 2181 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 5050 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 8080 -j ACCEPT [root@master-1 local]# systemctl restart iptables.service 2)新增mesos的yum源 [root@master-1 ~]# rpm -Uvh http://repos.mesosphere.io/el/7/noarch/RPMS/mesosphere-el-repo-7-2.noarch.rpm 3)安裝mesos,marathon,zookeeper [root@master-1 ~]# yum install -y java-1.8.0-openjdk-devel java-1.8.0-openjdk #安裝依賴的JDK環境 [root@master-1 ~]# yum -y install mesos marathon mesosphere-zookeeper 4)配置zookeeper 設定檔案/var/lib/zookeeper/myid為當前mesos master節點的id,id必須為1-255之中的整數. master-1機器設定id為"1" [root@master-1 ~]# echo 1 > /var/lib/zookeeper/myid master-2機器設定id為"2" [root@master-2 ~]# echo 2 > /var/lib/zookeeper/myid master-3機器設定id為"3" [root@master-3 ~]# echo 3 > /var/lib/zookeeper/myid [root@master-1 ~]# cp /etc/zookeeper/conf/zoo.cfg /etc/zookeeper/conf/zoo.cfg.bak [root@master-1 ~]# vim /etc/zookeeper/conf/zoo.cfg maxClientCnxns=50 #單個客戶端與單臺伺服器之間的連線數的限制,是ip級別的,預設是50,如果設定為0,那麼表明不作任何限制。請注意這個限制的使用範圍,僅僅是單臺客戶端機器與單臺ZK伺服器之間的連線數限制,不是針對指定客戶端IP,也不是ZK叢集的連線數限制,也不是單臺ZK對所有客戶端的連線數限制。 tickTime=2000 #Zookeeper 伺服器之間或客戶端與伺服器之間維持心跳的時間間隔,也就是每個 tickTime 時間就會傳送一個心跳 initLimit=10 #Zookeeper的Leader 接受客戶端(Follower)初始化連線時最長能忍受多少個心跳時間間隔數。當已經超過 5個心跳的時間(也就是tickTime)長度後 Zookeeper 伺服器還沒有收到客戶端的返回資訊,那麼表明這個客戶端連線失敗。總的時間長度就是 5*2000=10 秒 syncLimit=5 #表示 Leader 與 Follower 之間傳送訊息時請求和應答時間長度,最長不能超過多少個tickTime 的時間長度,總的時間長度就是 2*2000=4 秒 dataDir=/var/lib/zookeeper #zookeeper資料檔案存放目錄 clientPort=2181 #客戶端連線埠 server.1=182.48.115.233:2888:3888 #數字1,2,3表示這個是第幾號伺服器(是上面myid檔案裡對應的數字);中間的是master主節點的ip地址 server.2=182.48.115.235:2888:3888 #第一個埠2888(這個埠可以自己定義)表示的是這個伺服器與叢集中的 Leader 伺服器交換資訊的埠 server.3=182.48.115.236:2888:3888 #第二個埠3888表示的是萬一叢集中的 Leader 伺服器掛了,需要一個埠來重新進行選舉,選出一個新的 Leader,而這個埠就是用來執行選舉時伺服器相互通訊的埠。 [root@master-1 ~]# vim /etc/mesos/zk #完全替換原來內容 zk://182.48.115.233:2181,182.48.115.235:2181,182.48.115.236:2181/mesos 設定檔案/etc/master-/quorum內容為一個大於(master節點數除以2)的整數。即採用四捨五入,比如這裡有3個master節點,那麼3/2=1.5,四捨五入為2 [root@master-1 ~]# echo 2 >/etc/mesos-master/quorum [root@master-1 ~]# cat /etc/mesos-master/quorum 2 5)配置mesos和marathon 主機名和ip要在hosts中寫入,最好不要使用localhost,否則會出現slave不能識別,以及marathon任務下發不正常等現象。 master-1機器 [root@master-1 ~]# mkdir -p /etc/marathon/conf [root@master-1 ~]# echo 182.48.115.233 > /etc/mesos-master/hostname [root@master-1 ~]# echo 182.48.115.233 > /etc/marathon/conf/hostname [root@master-1 ~]# hostnamectl --static set-hostname master-1.com [root@master-1 ~]# echo "182.48.115.233 master-1 master-1.com" >/etc/hosts [root@master-1 ~]# cat /etc/hosts 182.48.115.233 master-1 master-1.com master-2機器 [root@master-2 ~]# mkdir -p /etc/marathon/conf [root@master-2 ~]# echo 182.48.115.235 > /etc/mesos-master/hostname [root@master-2 ~]# echo 182.48.115.235 > /etc/marathon/conf/hostname [root@master-2 ~]# hostnamectl --static set-hostname master-2.com [root@master-2 ~]# echo "182.48.115.235 master-2 master-2.com" >/etc/hosts [root@master-2 ~]# cat /etc/hosts 182.48.115.235 master-2 master-2.com master-3機器 [root@master-3 ~]# mkdir -p /etc/marathon/conf [root@master-3 ~]# echo 182.48.115.236 > /etc/mesos-master/hostname [root@master-3 ~]# echo 182.48.115.236 > /etc/marathon/conf/hostname [root@master-3 ~]# hostnamectl --static set-hostname master-3.com [root@master-3 ~]# echo "182.48.115.236 master-3 master-3.com" >/etc/hosts [root@master-3 ~]# cat /etc/hosts 182.48.115.236 master-3 master-3.com [root@master-1 ~]# cp /etc/mesos/zk /etc/marathon/conf/master [root@master-1 ~]# cp /etc/mesos/zk /etc/marathon/conf/zk [root@master-1 ~]# sed -i 's|mesos|marathon|g' /etc/marathon/conf/zk 6)啟動mesos,marathon,zookeeper [root@master-1 ~]# systemctl enable zookeeper && systemctl enable mesos-master && systemctl enable marathon [root@master-1 ~]# systemctl start zookeeper && systemctl start mesos-master && systemctl start marathon [root@master-1 ~]# systemctl disable mesos-slave 檢視程式狀態 [root@master-1 ~]# systemctl status zookeeper [root@master-1 ~]# systemctl status mesos-master [root@master-1 ~]# systemctl status marathon [root@master-1 ~]# lsof -i:2181 [root@master-1 ~]# lsof -i:5050 [root@master-1 ~]# lsof -i:8080 7)檢查配置 配置過程中出錯,為了方便檢查對比各master配置,直接執行如下命令。 [root@master-1 ~]# cat /var/lib/zookeeper/myid && tail -6 /etc/zookeeper/conf/zoo.cfg && cat /etc/mesos/zk && cat /etc/mesos-master/quorum && cat /etc/mesos-master/hostname&& cat /etc/marathon/conf/hostname&& cat /etc/marathon/conf/master&&cat /etc/marathon/conf/zk 1 syncLimit=5 dataDir=/var/lib/zookeeper clientPort=2181 server.1=182.48.115.233:2888:3888 server.2=182.48.115.235:2888:3888 server.3=182.48.115.236:2888:3888 zk://182.48.115.233:2181,182.48.115.235:2181,182.48.115.236:2181/mesos 2 182.48.115.233 182.48.115.233 zk://182.48.115.233:2181,182.48.115.235:2181,182.48.115.236:2181/mesos zk://182.48.115.233:2181,182.48.115.235:2181,182.48.115.236:2181/marathon -------------------------------------------------------------------------------------------------------- 溫馨提示: 1) 還可以建立 /etc/mesos-master/cluster 檔案,寫入叢集的別名。 2)主機名最好不要輕易更換,否則會導致mesos啟動失敗!更換主機名後,最好徹底解除安裝並刪除源資料,然後重新部署 # yum remove mesos marathon mesosphere-zookeeper # rm -rf /etc/mesos* # rm -rf /etc/marathon* # rm -rf /var/lib/zookeeper* # rm -rf /etc/zookeeper* # rm -rf /var/lib/mesos* #源資料目錄 # yum -y install mesos marathon mesosphere-zookeeper 3)以上操作後,master節點機不能ping通外網,是因為DNS解析檔案被改變了,執行下面命令即可: [root@master-1 local]# echo "nameserver 8.8.8.8" >> /etc/resolv.conf [root@master-1 local]# ping www.baidu.com PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data. 64 bytes from 14.215.177.38: icmp_seq=1 ttl=53 time=38.3 ms ................
3)配置slave節點(3臺slave節點都要操作)
1)關閉selinux和iptables防火牆 關閉selinux [root@slave-1 ~]# vim /etc/sysconfig/selinux SELINUX=disabled [root@slave-1 ~]# setenforce 0 #臨時關閉。reboot重啟機器後,使得上面配置生效,就永久關閉selinux了 [root@slave-1 ~]# getenforce Permissive 關閉iptables防火牆。 如果不關閉,需要開啟5051埠 [root@slave-1 ~]# vim /etc/sysconfig/iptables ....... -A INPUT -p tcp -m state --state NEW -m tcp --dport 5051 -j ACCEPTT [root@slave-1 ~]# systemctl restart iptables.service 2)安裝docker,安裝後啟動docker [root@slave-1 ~]# yum install -y docker [root@slave-1 ~]# systemctl enable docker [root@slave-1 ~]# systemctl start docker 拉取映象(三臺slave節點機都需要下載映象,因為在marathon介面裡建立docker容器,是隨機在slave節點機上讀取映象建立的) [root@slave-1 ~]# docker pull nginx [root@slave-1 ~]# docker pull tomcat [root@slave-1 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/tomcat latest 08f8166740f8 4 days ago 366.7 MB docker.io/nginx latest 46102226f2fd 2 weeks ago 109.4 MB 3)新增mesos的yum源 [root@slave-1 ~]# rpm -Uvh http://repos.mesosphere.io/el/7/noarch/RPMS/mesosphere-el-repo-7-1.noarch.rpm 4)安裝mesos [root@slave-1 ~]# yum -y install mesos 5)配置master資訊 slave-1機器 [root@slave-1 ~]# echo 182.48.115.237 > /etc/mesos-slave/hostname [root@slave-1 ~]# hostnamectl --static set-hostname slave-1.com [root@slave-1 ~]# echo "182.48.115.237 slave-1 slave-1.com" >/etc/hosts [root@slave-1 ~]# cat /etc/hosts 182.48.115.237 slave-1 slave-1.com slave-2機器 [root@slave-2 ~]# echo 182.48.115.238 > /etc/mesos-slave/hostname [root@slave-2 ~]# hostnamectl --static set-hostname slave-2.com [root@slave-2 ~]# echo "182.48.115.238 slave-2 slave-2.com" >/etc/hosts [root@slave-2 ~]# cat /etc/hosts 182.48.115.238 slave-2 slave-2.com slave-3機器 [root@slave-3 ~]# echo 182.48.115.239 > /etc/mesos-slave/hostname [root@slave-3 ~]# hostnamectl --static set-hostname slave-3.com [root@slave-3 ~]# echo "182.48.115.239 slave-3 slave-3.com" >/etc/hosts [root@slave-3 ~]# cat /etc/hosts 182.48.115.239 slave-3 slave-3.com [root@slave-1 ~]# vim /etc/mesos/zk zk://182.48.115.233:2181,182.48.115.235:2181,182.48.115.236:2181/mesos 配置marathon呼叫mesos執行docker容器 [root@slave-1 ~]# echo 'docker,mesos' > /etc/mesos-slave/containerizers 6)啟動slave(要保證mesos-slave啟動後,讀取的zk資訊是那三個mesos-master的連線資訊,否則mesos訪問頁面裡就不會出現這個slave節點資訊。ps -ef|grep mesos-slave) [root@slave-1 ~]# systemctl start mesos-slave && systemctl enable mesos-slave [root@slave-1 ~]# systemctl disable mesos-master ------------------------------------------------------------------------------------------------------- 溫馨提示: 1)以上操作後,master節點機不能ping通外網,是因為DNS解析檔案被改變了,執行下面命令即可: [root@slave-1 ~]#echo "nameserver 8.8.8.8" >> /etc/resolv.conf [root@slave-1 ~]# ping www.baidu.com PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data. 64 bytes from 14.215.177.38: icmp_seq=1 ttl=53 time=38.3 ms ....... 2)如果mesos-slave啟動失敗,可以如下檢查: [root@slave-1 ~]# journalctl -f -u mesos-slave #journalctl -f -u mesos-master可以檢查master端的 mesos-slave啟動失敗(比如主機名改變導致),可以刪除源資料,解除安裝乾淨,然後重新安裝部署 # yum remove mesos # rm -rf /etc/mesos* # rm -rf /var/lib/mesos* #源資料目錄是/var/lib/mesos/meta # yum install mesos
4)訪問web管理頁面
訪問mesos的管理頁面,即訪問http://master_ip:5050
注意:master_ip是這3個master中的任意一個就行,經過zookeeper選主,會自動跳到了leader的頁面,如圖mesos的leader為182.48.115.236(即master3被選為leader master)
在Frameworks中已經能夠識別marathon,此時marathon的leader為182.48.115.236.
注意:mesos和marathon都是有zookeeper來選舉leader,但是選主過程彼此獨立,就是mesos的leader和marathon的leader可以不一樣。如圖這裡二者通過zookeeper選出的leader是同一臺機器(即都是master3:182.48.115.236)
點選"Agents",發現已經能夠識別出三個slave。
注意:這裡訪問mesos顯示的是"Agents"選項,老版本的mesos顯示的是”Salve“選項
點選上面3個slave中的任意一個,也能看出它的master是182.48.115.236
訪問marathon的管理頁面,http://master_ip:8080
這裡的master_ip就是在上面訪問mesos頁面Frameworks中識別出的marathon,即http://182.48.115.236:8080
或者直接點選mesos訪問頁面Frameworks中識別出的marathon也可以。
或者點選下圖示紅的marathon(即zookeeper選出的主marathon),可以出現marathon的管理介面
5)通過Mesos排程,使用marathon來建立容器
比如建立一個nginx映象的Docker容器,Marathon啟動時會讀取/etc/mesos/zk配置檔案,Marathon通過Zookeeper來找到Mesos Master。
Marathon有自己的REST API,我們通過API的方式來建立一個Nginx的Docker容器。
首先建立一個json檔案(這個要在master節點機器上建立,任意一臺master節點機上都可以):
[root@master-1 ~]# vim nginx.json #nginx的docker映象要提前建立或下載 { "id":"nginx", "cpus":0.2, "mem":32.0, "instances": 1, "constraints": [["hostname", "UNIQUE",""]], "container": { "type":"DOCKER", "docker": { "image": "docker.io/nginx", #這個nginx映象是在slave節點機上通過"docker images"檢視到的,映象名不能寫錯 "network": "BRIDGE", "portMappings": [ {"containerPort": 80, "hostPort": 0,"servicePort": 0, "protocol": "tcp" } ] } } }
接著使用curl的方式呼叫。注意上面的nginx.json檔案是在/root路徑下的(注意下面命令中json檔案路徑)。
[root@master-1 ~]# curl -X POST http://182.48.115.233:8080/v2/apps -d @/root/nginx.json -H "Content-type: application/json"
登陸marathon介面檢視是在哪一臺slave機器上建立的docker容器例項(這個是隨機的),點選"running"。(如果容器建立失敗,即非"running"狀態,可以嘗試重啟slave節點的docker服務)
如上截圖中可知,這個nginx容器是在slave3節點機(182.48.115.239)上建立的(注意:如果slave3節點機當機或docker服務重啟,那麼這個nginx容器就會自動漂移到其他的slave節點機上;另外,通過上面方式建立好的容器,在單個slave節點機上刪除後,容器也會自動轉移到其他slave節點機器上,這樣就實現了在slave節點出現故障時容器自動轉移的高可用功能)。可以登陸slave3機器檢視所建立的容器,如下可知:訪問Docker隨機啟動的埠是31782
[root@slave-3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b35fff88051e docker.io/nginx "nginx -g 'daemon off" 14 minutes ago Up 14 minutes 0.0.0.0:31782->80/tcp mesos-6bc17bcc-433c-425e-b85e-232ffa42fe4f-S5.f1a121be-2e79-4856-bd5c-576db3497fba
訪問所建立的nginx容器。(marathon ui介面裡建立的docker容器對映到宿主機的訪問埠預設都是隨機分配的(BRIDGE模式))、可以自己製作應用的docker映象,或者自定義構建容器並提交為新映象(自己設定應用容器結構),然後根據自己製作的映象在Marathon上建立應用。
接著訪問mesos頁面,可以看到"Active Tasks"有剛才建立的nginx任務了。(注意:只有當mesos訪問介面"Active Tasks"裡有容器建立任務時,才說明此容器真正建立成功了)
刪除marathon建立的docker例項。如下圖,點選"Destory"即可刪除。
然後登陸slave3機器,發現在伺服器上,這個容器只是被關閉了(docker ps -a),可以選擇刪除。如果再次在機器上啟動這個nginx容器,那麼在marathon上是不會顯示的。注意:在節點機器上手動建立的docker容器,這些容器資訊是不會在marathon和mesos裡展示的。
[root@slave-3 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@slave-3 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b35fff88051e docker.io/nginx "nginx -g 'daemon off" 30 minutes ago Exited (0) About a minute ago mesos-6bc17bcc-433c-425e-b85e-232ffa42fe4f-S5.f1a121be-2e79-4856-bd5c-576db3497fba [root@slave-3 ~]# docker rm b35fff88051e b35fff88051e
如上在marathon介面裡"Destory"刪除對應的application後,在mesos介面的"Active Tasks"裡的對應任務也會刪除
另外要注意:在marathon介面裡通過呼叫mesos建立docker容器,只能建立應用容器(Application),如nginx、tomcat、mysql、redis等,需要對映埠,這裡是對映的是宿主機的隨機埠。不能建立基本centos,ubuntu的系統容器!
----------------------------------------------------------------------------------------------------------------------------------------
可以直接在marathon介面裡手動建立docker應用容器:
首先點選marathon介面裡右上角的"Create Application"
然後填寫建立容器的配置資訊,如下圖,可以點選"New Application"建立頁面右上角的"JSON Mode"模式,將上面建立nginx容器的json檔案複製到這裡
這樣,就可以直接建立一個docker應用容器了。(複製寫好的json檔案到這裡後,可以再次關閉"JSON Mode"模式,然後對比下所選用的配置)
下面我關閉"JSON mode"模式,手動選擇配置資訊去建立tomcat容器:
Marathon還可以對App應用實現手動擴縮的功能,選擇"Scale Application"進行快速擴容。如下圖,對上面已建立的tomcat應用容器進行擴充套件到2個Task(注意:這裡有3個slave節點,那麼擴充套件的Task例項最好是2個,3/2=1.5,即2個Instances;如果擴充套件多個Task,會發現多餘的建立失敗,這時候可以點選"Configuration"修改,修改成2個)
------------------------------------------------------------------------------------------------------
當然也可以手動編寫json檔案進行建立 [root@master-1 ~]# cat tomcat.json { "id":"tomcat", "cpus":1, "mem":128, "instances": 1, "constraints": [["hostname", "UNIQUE",""]], "container": { "type":"DOCKER", "docker": { "image": "docker.io/tomcat", "network": "BRIDGE", "portMappings": [ {"containerPort": 8080, "hostPort": 0,"servicePort": 0, "protocol": "tcp" } ] } } } [root@master-1 ~]# curl -X POST http://182.48.115.233:8080/v2/apps -d @/root/tomcat.json -H "Content-type: application/json" 也可以將上面的tomcat.json檔案內容直接複製到marathon建立應用容器的"JSON Mode"模式裡,然後直接點選建立
檢視容器建立的日誌,可以在marathon介面裡下載,也可以到mesos頁面裡檢視或下載。如下圖:
點選下面的日誌"stderr"和"stdout"就會下載到本地。
也可以到mesos頁面檢視或下載。點選下面mesos頁面對應容器任務後面的"Sandbox"
---------------------------------------------------------------------------------------------------------------------------------------
具體配置可以參考marathon官方文件:https://mesosphere.github.io/marathon/docs/persistent-volumes.html
裡面有關於json檔案的配置
--------------------------------------------------marathon建立應用使用volumes---------------------------------------------------
在marathon介面裡建立應用,可以使用volumes,即對映容器目錄到宿主機上,JSON檔案內容如下:
{ "id": "nginx", "cmd": null, "cpus": 1, "mem": 128, "disk": 0, "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" } ] } }
在marathon介面裡建立nginx容器應用時,將上面的JSON檔案複製到"JSON Mode"模式下,然後建立即可!非"JSON Mode"模式下手動填寫,Volumes選項填寫如下
點選"Configuration",就可以看到容器建立的配置資訊,並可以"Edit"修改
注意事項:
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介面里根據自己定義的映象建立應用。
---------------------------------------------------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", "cpus":0.2, "mem":32.0, "instances": 1, "constraints": [["hostname", "UNIQUE",""]], "container": { "type":"DOCKER", "docker": { "image": "docker.io/nginx", "network": "BRIDGE", "portMappings": [ {"containerPort": 80, "hostPort": 31030,"servicePort": 33180, "protocol": "tcp" } ] } } }
在marathon介面裡建立應用,將上面的JSON檔案內容複製到"JSON Mode"模式下。構建成功後,就會發現該應用容器的訪問埠就是上面自己定義的31030埠了(如下)
---------------------------------------------------其他-----------------------------------------------------------------------------
在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 hello' >> /mnt/test ; sleep 5 ; done", "cpus": 0.1, "mem": 10.0, "instances": 1 }
在marathon介面裡新增應用,採用"JSON Mode "模式,如下:
不採用"JSON Mode"模式,即將上面的json檔案內容貼上進去後,去掉右上方的"JSON Mode"模式,也就是隻配置"General"選向,其他選項都不配置。注意:marathon裡的應用是一個長執行服務,所以shell指令碼里要配置長執行動作。
然後到182.48.115.239這臺slave節點機上檢查,發現每隔5秒鐘,就會輸出"hello world"到/mnt/test檔案中。如果這臺節點機出現故障,就會輸出到其他節點機上。
[root@slave-3 mnt]# cat /mnt/test Hello hello Hello hello Hello hello Hello hello Hello hello Hello hello Hello hello .......