測試環境docker化—容器集羣編排實踐

本文來自網易雲社區html

做者:孫婷婷node


背景mysql

在前文《測試環境docker化—基於ndp部署模式的docker基礎鏡像製做》中已經詳述了docker鏡像製做及模塊部署的過程,按照上述作法已能夠搭建測試環境。可是在實踐過程當中發現存在不少問題:git

  1. 在一臺雲主機上搭建多個模塊,容易出現資源不足的狀況(咱們在實驗過程當中有臺雲主機好幾回宕機,常常要刪掉不用的鏡像容器);web

  2. 部分模塊之間須要相互調用,爲方便部署多套環境簡化配置修改,部署時須要肯定容器的ip地址;redis

  3. 手動敲命令一個個構建容器,n個模塊就要敲n個構建指令,構建容易出錯;sql

基於上述緣由,同時參考組內大神倪子的實踐《細說Mammut大數據系統測試環境Docker遷移之路》,咱們也嘗試了引入容器集羣編排,來進一步優化測試環境docker化的過程。docker


容器集羣搭建安全

爲解決一臺測試環境雲主機可能支撐不了一套環境的問題,咱們考慮使用多臺雲主機組成一個容器集羣,將多個deploy容器負載均衡的部署到多臺雲主機上,來實現環境的穩定和資源的合理利用。bash

要實現多主機的容器部署和分配,須要引入集羣調度工具。目前業界比較主流的調度管理工具備Docker Swarm、Google Kubernetes 和 Apache Mesos(基於Marathon框架),其中目前已佔領上風的是Kubernetes,成爲容器編排管理的最佳實踐工具。可是參考倪子的文章和介紹,我最終決定繼續選擇Swarm來進行實踐。在Swarm的學習調研過程當中,我發現區別於倪子實踐使用的Docker Swarm,docker1.12版本已經進一步推出了內置的簡單易用的Swarm mode集羣。老的Docker Swarm使用獨立的外部KV存儲(好比Consul、etcd、zookeeper),搭建獨立運行的Docker主機集羣,使用KV存儲配置進行服務發現。新版的Swarm mode則將docker swarm包含到docker引擎中,並內置了服務發現工具,使得集羣搭建進一步簡化爲直接使用docker swarm命令初始化一臺主機做爲manager,其餘機器加入該swarm成爲worker便可。具體命令以下(咱們的測試環境共使用3臺雲主機):

#將一臺主機指定爲manager,該命令會返回惟一一個集羣惟一token,且該節點會同時做爲manager和worker運行sudo docker swarm init --listen-addr 10.165.148.87:2377 --advertise-addr 10.165.148.87#在另兩臺主機上運行上述命令返回的join命令,便可加入該swarm集羣sudo docker swarm join \
    --token SWMTKN-1-0cytn4js5b8jn0vibtk935y7jptqxv63ttiqui1qhi2uo07emx-cr80z41yz9v2tsn8vyxgy6k2u \    10.165.148.87:2377

以上命令即完成集羣搭建,可經過sudo docker node ls命令查看集羣中的節點。此後用戶即可以經過manager節點操做整個集羣,把多臺Docker主機當作一臺主機來部署容器服務和管理。


跨主機通訊

docker官方文檔介紹,當咱們在一臺主機上初始化一個swarm或者將一臺雲主機加入到一個swarm中時,該主機上將會默認建立兩種新的網絡:

  • 一種是名稱爲ingress的overlay型網絡。ingress主要負責swarm集羣中服務之間的負載均衡和服務發佈。若用戶在新建swarm service時未指定自定義的overlay網絡,它會自動加入ingress。

  • 另外一箇中名稱爲docker_gwbridge的bridge型網絡。它是一個用於鏈接overlay型網絡(包括ingress)和獨立docker主機的物理網絡的虛擬網橋。

備註:理論上docker_gwbridge是自動建立的,可是不知道爲何我在實踐過程當中沒有找到docker_gwbridge,最後本身從新建立了該網絡。若想自定義建立和設置docker_gwbridge,那麼必須在初始化或者加入swarm前建立,不然以後建立的容器端口將沒法成功映射至主機端口。

當咱們發佈服務時,能夠建立一個私有網絡,實現跨主機之間的容器通訊。在Docker1.9版本以後,Dokcer給你們帶來了一種原生的跨主機容器網絡解決方案,該方案基於VXLAN的覆蓋網技術、依靠獨立的外部KV存儲(好比Consul、etcd、zookeeper)來經過註冊於同一存儲的配置來實現「服務發現」和「DNS」解析,從而實現私有網絡的跨主機通訊;同時在Docker1.12版本以後,咱們只要經過Swarm mode搭建集羣,然後建立overlay網絡,直接用「原生態」的swarm來發現進行通訊。

#若須要自定義建立docker_gwbridge或加入swarm後未發現docker_gwbridge,能夠經過退出swarm後自定義建立;注意若想手動建立,必需要在加入swarm集羣以前sudo docker network create --subnet 192.168.18.0/24 --opt com.docker.network.bridge.name=docker_gwbridge --opt com.docker.network.bridge.enable_icc=false --opt com.docker.network.bridge.enable_ip_masquerade=true docker_gwbridge#建立私有overlay網絡,用於跨主機容器通訊,-- opt 指定網絡安全模式sudo docker network create --driver overlay --subnet 192.168.47.0/24 --opt encrypted overlay-net

私有網絡建立完成後,只需在建立容器服務時指定自定義網絡,容器變會在建立時自動加入該網絡,實現容器間通訊。

好了,如今容器之間能夠互相訪問了。可是每次容器啓動的時候overlay都會動態分配一個虛擬IP地址,這樣容器之間互相調用的時候就會須要在每次容器啓動後再去容器中修改IP地址,當配置文件較多時修改起來會更加麻煩。熟悉docker engine的人必定知道link這個功能,Swarm mode則提供了一個相似的service discovery功能,它會將容器的虛擬IP映射到swarm的內置dns中,使用服務名稱service name來做爲域名。那麼訪問容器的IP則只須要訪問服務名稱,使得容器間通訊更加方便。


compose部署

到此其實測試環境docker化的基本工做已經完成了,可是結合前文鏡像製做的內容,咱們的測試環境部署須要至少1個compile容器+n個deploy容器,deploy容器中也可能有多個web服務,各個容器須要暴露port,添加各自的entry.sh,如果經過docker service create命令一個個建立,一不當心就會配置錯誤致使容器沒法啓動;配置多套環境的可複製性也會差不少。

一個簡單的辦法是使用compose進行容器編排,將各命令簡化爲只須要編寫compose的yaml文件便可。Docker1.13版本以後增長了compose v3,在Swarm的基礎上引入了stack對service鏡像的管理和編排,使得容器服務的部署更加簡單。compose v3的語法能夠參考Compose file version 3 reference,注意其與v2有些許不一樣。

咱們在項目部署中,考慮到compile容器須要先行建立,以便在deploy部署前完成項目代碼的構建,咱們將整個測試環境的部署分割爲3個yaml文件:

  • compose-compile.yaml:用於compile容器先行建立

  • compose-dependency.yaml:用於項目中依賴模塊容器建立(好比zk、kafka、redis、mysql等)

  • compose-deploy.yaml:裏面添加了項目各個模塊的容器建立指令

咱們在搭建完swarm環境+準備好各配置文件後,因爲compose同時能夠自定義建立network,最終咱們僅須要三行命令便可建立一套測試環境:

#生成dependency應用,該應用中包含項目部署所須要的相關依賴,包括kafka、zk等 sudo docker stack deploy --with-registry-auth -c ./compose-dependency.yaml antispamdependency#生成compile應用,建立antispamcompile-compile服務完成項目編譯sudo docker stack deploy --with-registry-auth -c ./compose-compile.yaml antispamcompile#生成antispam應用,該應用中包含各模塊部署的相關服務sudo docker stack deploy --with-registry-auth -c ./compose-deploy.yaml antispam


測試環境docker自動部署

在完成compile和deploy鏡像的製做後,能夠將鏡像保存在蜂巢,以方便部署環境時拉取。同時爲保證每一個deploy容器在建立後能自動拉取compile容器中構建好的編譯模塊進行模塊部署,咱們爲各個功能模塊編寫了相應的entry.sh並保存在網易git倉庫中,entry.sh文件實現相應的構建模塊拉取、部分配置修改和模塊啓動。同時在deploy鏡像中內置一個inter-entry.sh,該腳本用於deploy啓動時拉取entry項目,並經過容器啓動參數運行相應的entry.sh文件。

inter-entry.sh文件內容以下:

#!/bin/bashgit clone ssh://git@xxxx:22222/hzsuntingting/xxx-docker-entries.git /usr/local/docker-entry/xxx-docker-entries/echo $1chmod 777 /usr/local/docker-entry/xxx-docker-entries/entries/$1/usr/local/docker-entry/xxx-docker-entries/entries/$1

同時docker-entries項目中保存了compile編譯項目須要的build.xml和容器編排鬚要的yaml文件,這樣項目測試環境docker化只須要增長一個docker-entries項目,該項目目錄結構以下:

最終,在搭建完swarm環境和準備好文件後,一個項目使用docker部署的流程以下圖所示:

  1. 主機下載各依賴模塊的鏡像建立相應的依賴模塊的容器;

  2. 修改被部署項目的接口調用配置爲docker服務的service name,例如部分模塊須要調用zk,而docker部署環境中zk的service name爲dependency_zookeeper,則直接將調用ip改成該服務名便可;

  3. 主機下載compile鏡像建立compile容器,容器在git拉取項目代碼和docker-entries(裏面含有build.xml),進行項目構建打包,並httpServer等待其餘模塊拉取;

  4. 主機下載deploy鏡像建立各deploy容器,容器內置的inter-entry.sh運行在git拉取docker-entries;

  5. 各deploy模塊拉取docker-entries後,根據容器啓動的entrypoint參數運行相應的entry.sh,到compile容器中拉取相應的構建模塊,解壓,修改配置並啓動。


總結

到此,測試環境docker化的自動化部署過程基本完成,組內成員已可實現用幾行命令即完成一套環境的部署工做。可是在實踐過程當中,還有不少須要優化的地方,例如:目前各跨主機容器之間的文件共享採用的是起一個簡單的httpServer+wget的方式以及git的方式替代,必需要指定肯定的路徑,在腳本編寫過程當中須要仔細比對,容易出錯,若實現跨主機的文件共享則會避免更多錯誤問題。同時,查看網上資料,Swarm mode集羣會折損系統約50%的性能,後續替換爲k8s來實踐,確定爲更有利於測試環境來完成異常測試等對系統穩定和性能要求比較高的測試。


例行一坑,讓你們少走彎路~

1. 指定主機爲manager時,若機器有多個ip地址,需在其後加參數「--advertise-addr 10.165.148.87 」,不然會報錯

2. 建立overlay網絡時能夠用subnet參數指定用於網絡的子網,若是不指定,swarm會自動選擇一個子網,可是根據官網的描述這個自動指定的子網可能會引發container通訊的問題

3.compose的yaml編寫時,volumes中type:volume須要版本在3.2及以上,不然會返回services.compile.volumes.0 must be a string

4.在一開始從蜂巢拉取鏡像的時候報錯以下,緣由是其餘主機節點無權限,須要經過--with-registry-auth參數來增長權限。

unable to pin image hub.c.163.com/neteaseqa2017/compile to digest: errors:
denied: requested access to the resource is denied
unauthorized: authentication required



網易雲容器服務爲用戶提供了無服務器容器,讓企業可以快速部署業務,輕鬆運維服務。容器服務支持彈性伸縮、垂直擴容、灰度升級、服務發現、服務編排、錯誤恢復及性能監測等功能,  點擊可免費試用

   

   

網易雲免費體驗館,0成本體驗20+款雲產品!

更多網易研發、產品、運營經驗分享請訪問網易雲社區


相關文章:
【推薦】 微服務監控探索
【推薦】 接口文檔神器Swagger(下篇)

相關文章
相關標籤/搜索