以Docker容器玩轉(zhuǎn)Mesos和Marathon
寫(xiě)在前面的話
經(jīng)歷了好幾個(gè)月起起伏伏,我們團(tuán)隊(duì)開(kāi)發(fā)的基于Dangdang Elastic Job的分布式調(diào)度系統(tǒng)/平臺(tái)終于成功開(kāi)源了,開(kāi)源地址Saturn(https://github.com/vipshop/saturn)。
人生在于折騰
身為技術(shù)人,折騰技術(shù)是人生的一種樂(lè)趣,也是一種挑戰(zhàn)。上次看老肖為了能更便利的安裝Mesos做了個(gè)開(kāi)源項(xiàng)目Crane深有感觸。不過(guò)這個(gè)方式是否還是太重了呢?既然技術(shù)上都是玩容器的,那么為什么不直接通過(guò)容器的方式來(lái)折騰Mesos集群呢?當(dāng)然只是個(gè)人測(cè)試環(huán)境,不要考慮用到生產(chǎn)上啊。
我用的是Mac,所以就想用docker聲稱的”Native”的docker來(lái)快速安裝一套Mesos集群。而不是使用虛擬機(jī)的方式來(lái)做,因?yàn)槟臉雍蚅inux搭建沒(méi)啥區(qū)別了。誰(shuí)知道,還是真的不少坑,弄了兩天才搞定。自己都覺(jué)得有點(diǎn)丟人了。
下面總結(jié)一下是如何做的,希望你不用這么折騰就能在Mac上玩轉(zhuǎn)Mesos,同時(shí)也不用安裝一堆的應(yīng)用工具如VirtualBox等。我已經(jīng)將我自己機(jī)器的VirtualBox給刪除了,因?yàn)闆](méi)有磁盤(pán)空間了。
雖然是Mac下測(cè)試的,但是既然是以容器的方式啟動(dòng),對(duì)于Linxu和Windows下原理是一樣。
后面這些步驟,希望你能在電腦前一步一步參照去做,而不是只是讀這個(gè)文章。現(xiàn)在太多文章是只能讀讀,這些沒(méi)有太多作用。我還是希望技術(shù)類的文章真正能幫到大家去操作的。
折騰一:Mesosphere的基礎(chǔ)鏡像坑
折騰一個(gè)可以測(cè)試/試用的Mesos環(huán)境是為了測(cè)試一下Mesos新版本的unitified container的功能,但是在使用中就發(fā)現(xiàn)了,Mesosphere打Mesos Slave的Image中竟然沒(méi)有curl命令,但是不知道為什么Mesos會(huì)直接使用curl的方式來(lái)拉取鏡像Image。(據(jù)說(shuō)會(huì)改掉,這個(gè)方式太low了)所以在開(kāi)始搭建環(huán)境之前,想將mesosphere的Mesos Slave的Image補(bǔ)充curl命令
需要的鏡像和版本
- Zookeeper: latest版本就可
- Mesos Master: 1.1.0-2.0.107.ubuntu1404
- Mesos Slave: 1.1.0-2.0.107.ubuntu1404
- Marathon: v1.3.6
如果需要拉這些Image,最好用國(guó)內(nèi)的代理鏡像倉(cāng)庫(kù),如Daocloud,不過(guò)正是因?yàn)橛昧诉@個(gè)代理鏡像庫(kù),給我造成了另外一個(gè)坑。后面講
打包自己的Mesos Slave鏡像
前面講了,需要給Slave鏡像補(bǔ)個(gè)CURL命令,對(duì)應(yīng)的Dockerfile為:
- FROM mesosphere/mesos-slave:1.1.0-2.0.107.ubuntu1404MAINTAINER duffqiu@gmail.comRUN apt-get update && apt-get install -y curl && apt-get clean
然后運(yùn)行命令打包: docker build -t mesos-slave .后面就使用這個(gè)包而不是mesosphere的官方包來(lái)運(yùn)行。不過(guò)還是得吐槽下Mesosphere,做為容器生態(tài)體系的領(lǐng)軍公司,這個(gè)容器image打的實(shí)在是不夠水平。
折騰二: Docker Registry的國(guó)內(nèi)代理DaoCloud不用HTTPS
搭建環(huán)境的目的是測(cè)試Unitified Container,它有個(gè)最大的優(yōu)勢(shì)是直接支持Docker Image,只需Slave啟動(dòng)的時(shí)候配置Registry的地址就可以使用鏡像的國(guó)內(nèi)代理地址(啟動(dòng)需要的參數(shù):MESOS_DOCKER_REGISTRY),原本挺好的設(shè)計(jì),誰(shuí)知道這里也有個(gè)坑,一點(diǎn)文檔都沒(méi)有。那就是它默認(rèn)使用的是HTTPS傳輸,但是我一開(kāi)始使用的是daocloud的代理庫(kù),它是http的最后造成拉包總是不成功。后來(lái)在Yu jie@Mesosphere的指導(dǎo)下,才知道,目前Mesos的實(shí)現(xiàn)是如果需要用http,則需要在配置url后面加上80端口。如果你用的私用倉(cāng)庫(kù)不是80端口,那么沒(méi)有辦法,因?yàn)镸esos還沒(méi)支持類似Docker daemon那樣的insecure-registry配置。所以最后在網(wǎng)上找了個(gè)阿里的registry地址來(lái)測(cè)試。估計(jì)這個(gè)地址的流量要猛漲了。-:)
另外需要提示一點(diǎn),就是用容器啟動(dòng)Mesos,對(duì)應(yīng)的官方文檔對(duì)應(yīng)的配置參數(shù),都可以用環(huán)境變量的方式配置,對(duì)應(yīng)環(huán)境變量名的規(guī)則是MESOS_,都要是全大寫(xiě)。如上面的registry的配置,啟動(dòng)參數(shù)是--docker_registry,而環(huán)境變量是MESOS_DOCKER_REGISTRY
折騰三: Mac下的’Native’ Docker不是’Native’
一開(kāi)始就被Docker的官方文檔誤導(dǎo)了,以為‘Native’就真的是類似Linux支持哪樣,直接使用了Mac的能力來(lái)做Docker。好在jason@uber指導(dǎo)了一下,豁然開(kāi)朗。其實(shí)Mac Native還是有VM的,只是從用戶體驗(yàn)上讓你感覺(jué)不到而已,對(duì)此相對(duì)于Mesos,還是要為Docker的用戶體驗(yàn)點(diǎn)個(gè)贊。就像你在Mac下找不到docker daemon一樣。其實(shí)docker daemon還是真實(shí)存在。但是這個(gè)docker daemon配置已經(jīng)被hardcode了,你沒(méi)法更改。同時(shí)有個(gè)問(wèn)題,在Mac下這個(gè)VM占用的空間會(huì)一直增大,無(wú)論你是否刪除了docker image。這個(gè)文件存放在/Users/macbook/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/Docker.qcow2。之前犯了個(gè)低級(jí)錯(cuò)誤,將這個(gè)文件一下子擴(kuò)大了10G,而我的Mac的硬盤(pán)又小,害我一直要?jiǎng)h文件騰空間。
Docker Build占空間
Docker build會(huì)將Dockerfile所在的目錄下的內(nèi)容都裝載進(jìn)來(lái)后才開(kāi)始打包。所以千萬(wàn)千萬(wàn)要給Dockerfile一個(gè)獨(dú)立的目錄。不然就會(huì)像我一樣無(wú)端將Mac下虛擬機(jī)擴(kuò)大了10G空間。
- Hack Mac Docker’s VM
雖然Mac下的Docker還是用的虛擬機(jī)的方式,那么如何進(jìn)入這個(gè)虛擬機(jī)呢?可以使用以下方式:
- docker run -it --rm --privileged --pid=host --net=host -v /:/rootfs --entrypoint=/bin/sh alpinecd /rootfschroot /rootfs
- 首先將虛擬機(jī)的根目錄mount給一個(gè)容器。這里就是一個(gè)理解的坑,我一直以為Mac是native的,所以主機(jī)的目錄就是Mac的目錄,其實(shí)不是,而是說(shuō)主機(jī)目錄其實(shí)是虛擬機(jī)的目錄
- 用chroot的方式,在虛擬機(jī)的根目錄為根運(yùn)行,這樣就相當(dāng)于在虛擬機(jī)中了(注意,不是完備的虛擬機(jī)能力,如網(wǎng)絡(luò)等)
這個(gè)時(shí)候,你就可以查找出dockerd的進(jìn)程了
- ps -ef|grep dockerd
可以看到對(duì)應(yīng)的dockerd的運(yùn)行參數(shù),這也就解釋了為什么Mac下的docker不能配置tcp端口了,因?yàn)檫@個(gè)已經(jīng)被這個(gè)VM的配置寫(xiě)死了,而且還改不了。(如何有任何方式可以改,請(qǐng)留言告訴我)以下是Mac的dockerd的啟動(dòng)命令
- /usr/bin/dockerd --pidfile=/run/docker.pid -H unix:///var/run/docker.sock --swarm-default-advertise-addr=eth0 --debug --storage-driver aufs
同時(shí)可以查看這個(gè)虛擬機(jī)的磁盤(pán)情況,這里就比較清晰展示哪些是VM的磁盤(pán),哪些是Mac的磁盤(pán)了。同時(shí),也可以看見(jiàn),docker用的VM是開(kāi)了50幾G的動(dòng)態(tài)空間的,默認(rèn)可以最大占用主機(jī)50幾G的,這個(gè)大家一定要注意,不然哪天機(jī)器沒(méi)有磁盤(pán)空間了都不知道用到那里去了。后續(xù)如果需要清理這些空間,只能卸載Docker再裝一次。
docker vm disk
提供Mac Docker的TCP以及Portainer
最近通過(guò)閱讀微信文章,找到一個(gè)本機(jī)管理Docker Daemon的一個(gè)好的帶界面的Container: portainer/portainer,可能需要翻墻。但是這個(gè)需要通過(guò)tcp的方式鏈接docker dameon,所以需要想個(gè)辦法將Mac下的unix socket轉(zhuǎn)為T(mén)CP。這個(gè)可以使用socat工具。Mac下可以通過(guò)port工具安裝,不過(guò)最好還是翻墻安裝,不然又是一個(gè)折磨。
socat的用法:
- socat TCP-LISTEN:2375,range=192.168.31.254/32,reuseaddr,fork UNIX-CLIENT:/var/run/docker.sock
然后啟動(dòng)portainer:
- docker run -d -p 9000:9000 --restart always portainer/portainer -H tcp://192.168.31.254:2375
192.168.31.254是你的機(jī)器ip,需要根據(jù)你的實(shí)際情況替換
這里需要注意的是,不要使用127.0.0.1的方式鏈接docker,因?yàn)樵趐ortainer里的127.0.0.1不是主機(jī)的127.0.0.1
下面是portainer的一個(gè)界面預(yù)覽,還是相當(dāng)清爽的,值得使用
portainer
另外可以在Mesos的集群的每個(gè)Slave主機(jī)上裝個(gè)這個(gè)容器,然后在集群的管理系統(tǒng)中嵌套改頁(yè)面,這樣就可以監(jiān)控和管理主機(jī)的容器/Image等了。同時(shí)它還提供了WEB Terminal,可以直接進(jìn)入容器,方便調(diào)試,非常好用。
到此,之前遇到的坑都列舉出來(lái)了,我們正是開(kāi)始進(jìn)入正題,安裝Mesos+Marathon集群
Mesos+Marthon集群搭建
Zookeeper容器化搭建
- docker run --name zookeeper --restart always -d -p 2181:2181 -p 2888:2888 -p 3888:3888 zookeeper
啟動(dòng)單機(jī)版本的Zookeeper,如果需要保留Zookeeper的數(shù)據(jù)以備下次啟動(dòng)繼續(xù)使用,則必須將zookeeper的data路徑放到主機(jī)的目錄下,這個(gè)具體就不詳細(xì)描述了。
telnet 10.100.150.22 2181 連接到Zookeeper,并輸入stat來(lái)驗(yàn)證是否安裝正確。
Mesos Master容器化搭建
- docker run -d -p 5050:5050 \
- -e MESOS_PORT=5050 \
- -e MESOS_ZK=zk://192.168.31.254:2181/mesos \
- -e MESOS_QUORUM=1 \
- -e MESOS_REGISTRY=in_memory \
- -e MESOS_LOG_DIR=/var/log/mesos \
- -e MESOS_WORK_DIR=/var/tmp/mesos \
- -e MESOS_HOSTNAME=192.168.31.254 \
- mesosphere/mesos-master:1.1.0-2.0.107.ubuntu1404
這里有一點(diǎn)需要注意:需要設(shè)置MESOS_HOSTNAME為你主機(jī)的ip地址(例子是我的機(jī)器ip,你需要根據(jù)實(shí)際情況替換),不然打開(kāi) Mesos Master地址的時(shí)候總是不穩(wěn)定。
只要能打開(kāi)mesos的UI地址,并且能在界面打得開(kāi)LOG則證明安裝成功了。
Mesos Slave容器化搭建
啟動(dòng)第一臺(tái)Slave
這里就需要用到我之前提的自己打包的Mesos Slave鏡像了,因?yàn)樾枰玫紺URL命令來(lái)啟動(dòng)Unified Container。同時(shí)我也希望Slave能夠同時(shí)使用Docker Container或者M(jìn)esos Container。
- docker run -d --privileged -p 5051:5051 \
- -v /usr/bin/docker:/usr/bin/docker \
- -v /var/run/docker.sock:/var/run/docker.sock \
- -v /sys/fs/cgroup:/sys/fs/cgroup \
- -e MESOS_PORT=5051 \
- -e MESOS_MASTER=zk://172.17.0.3:2181/mesos \
- -e MESOS_SWITCH_USER=0 \
- -e MESOS_CONTAINERIZERS=mesos,docker \
- -e MESOS_LOG_DIR=/var/log/mesos \
- -e MESOS_WORK_DIR=/var/tmp/mesos \
- -e MESOS_IMAGE_PROVIDERS=docker \
- -e MESOS_ISOLATION=filesystem/linux,docker/runtime \
- -e MESOS_DOCKER_REGISTRY=https://r6w9c7qa.mirror.aliyuncs.com \
- -e MESOS_ADVERTISE_IP=192.168.31.254 \
- -e MESOS_ADVERTISE_PORT=5051 \
- -e GLOG_v=1 \
- mesos-slave
這里有幾點(diǎn)注意點(diǎn):
- 如果需要用docker container,需要將-v的這幾個(gè)盤(pán)掛載到容器中。注意,這里的主機(jī)盤(pán)地址是VM的地址,不是Mac主機(jī)的地址
- MESOS_MASTER配置可以直接寫(xiě)Mesos Master的http地址就可,不用連接Zookeeper了。或許這樣可以減輕Zookeeper的壓力。不過(guò)依然可以使用zookeeper的方式鏈接。這里的地址使用容器間的地址就可。不過(guò)文檔沒(méi)有說(shuō)如果是配置Master的http地址的話,如何支持多臺(tái)Mesos地址。(據(jù)說(shuō)目前http方式只能用于測(cè)試,生產(chǎn)的話要用zk的鏈接,因?yàn)閦k支持多個(gè)服務(wù)器配置)
- MESOS_CONTAINERIZERS需要指明mesos和docker,這樣才可以運(yùn)行docker container以及mesos container
- IMAGE_PROVIDERS 指明都是用docker鏡像,這個(gè)是給Mesos container用的
- MESOS_ISOLATION 使用Mesos Container,則必須制定這兩個(gè)隔離器
- MESOS_DOCKER_REGISTRY 指明用Unified Container需要的docker image的拉取地址。注意我前面提到的坑。這個(gè)和docker container沒(méi)有關(guān)系
- MESOS_ADVERTISE_IP和MESOS_ADVERTISE_PORT公開(kāi)對(duì)外的ip和對(duì)外的port。如果不是用這個(gè),在容器部署里,無(wú)法在Mesos master上獲取到agent的log
- 這里不要設(shè)置MESOS_HOSTNAME,因?yàn)樵O(shè)置了就無(wú)法在界面看見(jiàn)agent的LOG了
啟動(dòng)第二臺(tái)Slave
- docker run -d --privileged -p 5052:5051 \
- -v /usr/bin/docker:/usr/bin/docker \
- -v /var/run/docker.sock:/var/run/docker.sock \
- -v /sys/fs/cgroup:/sys/fs/cgroup \
- -e MESOS_PORT=5051 \
- -e MESOS_MASTER=zk://172.17.0.3:2181/mesos \
- -e MESOS_SWITCH_USER=0 \
- -e MESOS_CONTAINERIZERS=mesos,docker \
- -e MESOS_LOG_DIR=/var/log/mesos \
- -e MESOS_WORK_DIR=/var/tmp/mesos \
- -e MESOS_IMAGE_PROVIDERS=docker \
- -e MESOS_ISOLATION=filesystem/linux,docker/runtime \
- -e MESOS_DOCKER_REGISTRY=https://r6w9c7qa.mirror.aliyuncs.com \
- -e MESOS_ADVERTISE_IP=192.168.31.254 \
- -e MESOS_ADVERTISE_PORT=5052 \
- -e GLOG_v=1 \
- mesos-slave
在同一臺(tái)機(jī)器啟動(dòng)多個(gè)Slave,這里只需要更改暴露的端口就可以了
部署Marathon
- docker run -d -p 8080:8080 mesosphere/marathon:v1.3.6 --master zk://172.17.0.3:2181/mesos --zk zk://172.17.0.3:2181/marathon
然后在Mac主機(jī)訪問(wèn) Marathon UI就可
Marathon啟動(dòng)容器
啟動(dòng)一個(gè)Docker的容器
通過(guò)界面配置的方式啟動(dòng)一個(gè)docker容器應(yīng)用,對(duì)應(yīng)的json為
- {
- "id": "testapp",
- "cmd": " while true;do echo hello;sleep 1;done",
- "cpus": 1,
- "mem": 128,
- "disk": 0,
- "instances": 1,
- "container": {
- "docker": {
- "image": "centos",
- "network": "BRIDGE"
- },
- "type": "DOCKER"
- }
- }
默認(rèn)Marathon啟動(dòng)的是docker容器。啟動(dòng)后,可以在Mac上docker ps看到這個(gè)運(yùn)行的容器了。
啟動(dòng)一個(gè)Docker Image的Mesos的容器(Unified Container)
因?yàn)楝F(xiàn)在Marathon的界面還沒(méi)有得選擇Mesos容器類型,所以需要在JSON模式修改,將之前的JSON配置的type改為MESOS就可
- {
- "id": "mesostest",
- "cmd": "while true;do echo hello docker >> txt.log ;sleep 1;done",
- "cpus": 1,
- "mem": 128,
- "disk": 0,
- "instances": 1,
- "container": {
- "docker": {
- "image": "102010cncger/centos:v1",
- "network": "BRIDGE"
- },
- "type": "MESOS"
- }
- }
上面的image名字是因?yàn)槲译S便搜索了個(gè)阿里的registry地址,所以要通過(guò)curl https://r6w9c7qa.mirror.aliyuncs.com/v2/_catalog獲取它存在的鏡像名字,然后再通過(guò)curl https://r6w9c7qa.mirror.aliyuncs.com//v2/102010cncger/centos/tags/list獲取它的tag,從而指導(dǎo)它可用的鏡像是102010cncger/centos:v1
因?yàn)镾lave用的是ubuntu,我又不太了解怎么裝個(gè)nsenter,所以只能用一下方法進(jìn)入到這個(gè)Mesos容器中
- 先用 docker exec -it <slave container id> /bin/bash 從Mac進(jìn)入到Slave的容器中
- 用ps -ef |grep mesos-executor 找到mesos executor的執(zhí)行命令參數(shù),獲得容器的具體路徑--rootfs那段,如我的例子/var/tmp/mesos/provisioner/containers/dd2a4567-4ad5-4b50-bdee-2351d0b863e8/backends/copy/rootfses/a913d575-9e5f-4384-b4bd-4ed36618f157
- 用chroot的方式進(jìn)入這個(gè)容器: chroot /var/tmp/mesos/provisioner/containers/dd2a4567-4ad5-4b50-bdee-2351d0b863e8/backends/copy/rootfses/a913d575-9e5f-4384-b4bd-4ed36618f157 /bin/bash,這樣你就進(jìn)入mesos的這個(gè)容器了的shell,但是無(wú)法獲取這個(gè)容器的其它能力如網(wǎng)絡(luò)等.
使用nsenter
ubuntu14.04安裝nsenter的方式,這里謝謝黃浩松@shopee.sg
用docker 容器的方式來(lái)安裝nsenter,步驟是
- 首先進(jìn)入到Slave的容器中docker exec -it <slave container id> /bin/bash
- 使用jpetazzo/nsenter這個(gè)鏡像,但是很奇怪不能用它推薦的docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter,而是要使用導(dǎo)出nsenter的方式docker run --rm jpetazzo/nsenter cat /nsenter > /tmp/nsenter && chmod +x /tmp/nsenter
- 獲得nsenter后,執(zhí)行nsenter --target $PID --mount --uts --ipc --net --pid /bin/bash進(jìn)入容器, $PID為容器對(duì)應(yīng)的進(jìn)程pid,通過(guò)ps -ef查看,完整的容器鏡像的cmd那個(gè)進(jìn)程id
到此Mesos container的安裝部署測(cè)試完成了。不過(guò)這里還是需要吐槽一下Mesos Container,這樣啟動(dòng)容器,就算你配置上是"network": "BRIDGE",但是如果沒(méi)有配置CNI,還是沒(méi)有bridge的,只能是host模式。
至此,整個(gè)測(cè)試環(huán)境就搭建完成了,如有任何問(wèn)題,請(qǐng)留言!
【本文是51CTO專欄作者“VIPDOCKER-了哥 ”的原創(chuàng)文章,如需轉(zhuǎn)載請(qǐng)通過(guò)51CTO與作者聯(lián)系】