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