做者簡介:劉曉明,五阿哥(www.wuage.com)公司運維技術負責人,擁有10年的互聯網開發和運維經驗。一直致力於運維工具的開發和運維專家服務的推動,賦能開發,提升效能。最後給本身代個鹽~~歡迎你們有空時翻下我牌子(知乎號:佈道 ),看看以前的文章,順便關注下專欄「開發運維」。java
五阿哥鋼鐵電商平臺(www.wuage.com)是由鋼鐵行業第一的中國五礦與互聯網第一的阿里巴巴聯手打造,並充分運用雙方股東優點資源,即:阿里巴巴在大數據、電商運營、互聯網產品技術上的巨大優點,尤爲是在B2B終端買家上的獨有市場基礎,以及中國五礦67年的行業經驗,和遍及全球的200多個營銷和物流網點,致力於爲鋼鐵行業帶來全新而持續的發展。Docker容器雲平臺是運維技術團隊爲內部服務整合、開發的一套容器管理平臺,支持基礎設施私有云和公有云對接,實現雲上和雲下實例使用一套平臺進行管理,業務實例按需彈性擴容和縮容,規範化的項目管理流程、測試、上線流程,旨在將開發、測試人員從基礎環境的配置與管理中解放出來,使其更聚焦於本身的業務開發。node
本文主要結合在五阿哥業務場景狀況,從如下三個部分講解:python
一、爲何使用Docker技術 。nginx
二、Docker容器雲架構方案。git
三、技術的選型和實踐。web
1. 硬件資源利用率的問題,形成部分紅本的浪費docker
在網站功能中不一樣的業務場景有計算型的,有IO讀寫型的,有網絡型,有內存型的,集中部署應用就會致使資源利用率不合理的問題。好比,一個機器上部署的服務都是內存密集型,那麼CPU資源就都很容易浪費了。json
2. 單物理機多應用沒法對沒法進行有效的隔離,致使應用對資源的搶佔和相互影響後端
一個物理機器跑多個應用,沒法進行所使用的CPU,內存,進程進行限制,若是一個應用出現對資源的搶佔問題,就會引發連鎖反應,最終致使網站部分功能不可用。緩存
3. 環境、版本管理複雜,上線部署流程缺少,增長問題排查的複雜度
因爲內部開發流程的不規範,代碼在測試或者上線過程當中,對一些配置項和系統參數進行隨意的調整,在發佈時進行增量發佈,一旦出現問題,就會致使測試的代碼和線上運行的代碼是不一致的,增長了服務上線的風險,也增長了線上服務故障排查的難度。
4. 環境不穩定,遷移成本高,增長上線風險
在開發過程當中存在多個項目並行開發和服務的依賴問題,因爲環境和版本的複雜性很高,不能快速搭建和遷移一個環境,致使沒法在測試環境中沒法模擬出線上的流程進行測試,不少同窗在線上環境進行測試,這裏有很高的潛在風險,同時致使開發效率下降。
5. 傳統虛擬機和物理機佔用空間大,啓動慢,管理複雜等問題
傳統虛擬機和物理機在啓動過程進行加載內核,執行內核和init進行,致使在啓動過程佔用很長時間,並且在管理過程當中會遇到各類各樣的管理問題。
基於Docker容器技術,運維技術團隊開發了五阿哥網站的容器雲平臺。總體架構圖以下:
基礎設施包含網絡、服務器、存儲等計算資源。
私有云(VMware)和公有云(aliyun)進行統一託管,包含網絡區域配置,VM實例開通及Docker的環境初始化配置等。
Docker容器雲平臺集羣節點管理,Saltstack進行配置管理,鏡像中心管理業務鏡像,統一監控,統一日誌管理,定時任務管理。
服務註冊,服務發現,容器節點在線的擴容和縮容,服務優雅上線,回滾降級,規範Java,Node,Python,iOS,Android等規範化的上線。
規範化整個業務流程,簡潔的用戶流程,可動態管理整個雲環境的全部資源。
鏡像標準
衆所周知,Docker的鏡像是分層的。對鏡像分層進行約定:
第一層是操做系統層,由CentOS/Alpine等基礎鏡像構成,安裝一些通用的基礎組件;
第二層是中間件層,根據不一樣的應用程序,安裝它們運行時須要使用到的各類中間件和依賴軟件包,如,nginx、tomcat等;
第三層是應用層,這層僅包含已經打好包的各應用程序代碼。
經驗總結:如何讓本身的鏡像變的更小,PUSH的更快?
- dockerfile構建應用鏡像,在中間件層遇到一些須要安裝的軟件包時,儘量的使用包管理工具(如yum)或以git clone方式下載源碼包進行安裝,目的是將軟件包的copy和安裝控制在同一層,軟件部署成功後清除一些無用的rpm包或源碼包,讓基礎鏡像的尺寸更小。
- Java應用鏡像中並無將jdk軟件包打入鏡像,將jdk部署在每臺宿主上,在運行鏡像時,經過掛載目錄的方式將宿主機上的java家目錄掛載至容器指定目錄下。由於它會把基礎鏡像撐得很是大;
- 在構建應用鏡像時,docker會對這兩層進行緩存並直接使用,僅會從新建立代碼出現變更的應用層,這樣就提升了應用鏡像的構建速度和構建成功後向鏡像倉庫推送的速度,從總體流程上提高了應用的部署效率。
編排工具
Rancher圖形化管理界面,部署簡單、方便, 能夠與AD、LDAP、GITHUB集成,基於用戶或用戶組進行訪問控制,快速將系統的編排工具升級至kubernetes或者swarm,同時有專業的技術團隊進行支持,下降容器技術入門的難度。
基於以上優勢咱們選擇Rancher做爲咱們容器雲平臺的編排工具,在對應用的容器實例進行統一的編排調度時,配合Docker-Compose組件,能夠在同一時間對多臺宿主機執行調度操做。同時,在服務訪問出現峯值和低谷時,利用特有的rancher-compose.yml文件調用「SCALE」特性,對應用集羣執行動態擴容和縮容,讓應用按需求處理不一樣的請求。
網絡模型
因爲後端開發基於阿里的HSF框架,生產者和消費者之間須要網絡可達,對網絡要求比較高,須要以真實IP地址進行註冊和拉取服務。因此在選擇容器網絡時,咱們使用了Host模式,在容器啓動過程當中會執行腳本檢查宿主機並分配給容器一個獨立的端口,來避免衝突的問題。
持續集成
監測代碼提交狀態,對代碼進行持續集成,在集成過程當中執行單元測試,代碼Sonar和安全工具進行靜態掃描,將結果通知給開發同窗同時部署集成環境,部署成功後觸發自動化測試。
靜態掃描結果:
持續部署
這是一種能力,這種能力很是重要,把一個包快速部署在你想要的地方。平臺採用分佈式構建、部署,master管理多個slave節點,每一個slave節點分屬不一樣的環境。在master上安裝並更新插件、建立job、管理各開發團隊權限。slave用於執行job。
基於上述架構,咱們定義了持續部署規範的流程:
(1)開發同窗向gitlab提交代碼;
(2)拉取項目代碼和配置項文件,執行編譯任務;
(3)拉取基礎鏡像,將編譯好的應用包打入生成最新的應用鏡像,推送到鏡像倉庫;
(4)根據當前應用及所屬環境定製化生成docker-compose.yml文件,基於這個文件執行rancher-compose命令,將應用鏡像部署到預發環境(發佈生產前的測試環境,相關配置、服務依賴關係和生產環境一致)。
(5)預發環境測試經過後將應用鏡像部署至線上環境,測試結果通知後端測試同窗。
監控管理
經過zabbix 自動註冊(AutoRegistration),Grafana經過調用zabbix的API接口進行監控指標的統一展現。
日誌管理
容器在運行時會在只讀層之上建立讀寫層,全部對應用程序的寫操做都在這層進行。當容器重啓後,讀寫層中的數據(包含日誌)也會一併被清除。雖然能夠經過將容器中日誌目錄掛載到宿主機解決此類問題,但當容器在多個宿主機間頻繁漂移時,每一個宿主機上都會有留存應用名的部分日誌,增長了開發同窗查看、排查問題的難度。
綜上所述,日誌服務平臺做爲五阿哥網站日誌倉庫,將應用運行過程當中產生的日誌統一存儲,而且支持多種方式的查詢操做。
經過在日誌服務的管理界面配置日誌採集路徑,在容器中部署agent把應用日誌統一投遞到logstore中,再在logstore中配置全文索引和分詞符,以便開發同窗可以經過關鍵字搜索、查詢想要的日誌內容。
經驗總結:如何避免日誌的重複採集問題?
日誌服務agent須要在配置文件「ilogtail_config.json」中增長配置參數「check_point_filename」,指定checkpoint文件生成的絕對路徑,而且將此路徑掛載至宿主機目錄下,確保容器在重啓時不會丟失checkpoint文件,不會出現重複採集問題。
服務註冊
etcd是一個具有高可用性和強一致性的鍵值存儲倉庫,它使用相似於文件系統的樹形結構,數據所有以「/」開頭。etcd的數據分爲兩種類型:key和directories,其中key下存儲單獨的字符串值,directories下則存放key的集合或者其餘子目錄。
在五阿哥環境中,每一個向etcd註冊的應用服務,它們的根目錄都以」/${APP_NAME}_${ENVIRONMENT}」命名。根目錄下存儲每一個應用實例的Key信息,它們都以「${IP}-${PORT}」的方式命名。 下圖是使用上述約定,存儲在etcd上某應用實例的數據結構:
能夠看到我是使用get方法向etcd發送請求的,請求的是部署在預發環境(PRE)的搜索服務(search);在它的根目錄「/search_PRE」下,僅存儲了一個應用實例的信息,這個實例的key是「172.18.100.31-86」;對應的value是「172.18.100.31:86‘’,整個註冊過程是這樣的:
① 經過代碼爲容器應用程序生成隨機端口,和宿主機正在使用的端口進行比對,確保端口沒有衝突後寫入程序配置文件;
② 把經過python和etcd模塊編寫的服務註冊工具集成在腳本中,將IP地址和上一步獲取的隨機端口以參數的方式傳遞給服務註冊工具;
③ 待應用程序徹底啓動後,由服務註冊工具以約定好的數據結構將應用實例的寫入etcd集羣,完成服務註冊工做;
④ 容器定時向etcd發送心跳,報告存活並刷新ttl時間;
⑤ 容器腳本捕獲rancher發送至應用實例的singnal terminal信號,在接收到信號後向etcd發送delete請求刪除實例的數據。
注:在ttl基礎上增長主動清除功能,在服務正常釋放時,能夠馬上清除etcd上註冊信息,沒必要等待ttl時間。
經驗總結:容器在重啓或者意外銷燬時,讓咱們一塊兒看一下這個過程當中容器和註冊中心都作了什麼事情?
應用在註冊是攜帶key 和value時攜帶了ttl超時屬性,就是考慮到當服務集羣中的實例宕機後,它在etcd中註冊的信息也隨之失效,若不予清除,失效的信息將會成爲垃圾數據被一直保存,並且配置管理工具還會把它當作正常數據讀取出來,寫入web server的配置文件中。要保證存儲在etcd中的數據始終有效,就須要讓etcd主動釋放無效的實例信息,來看一下注冊中心刷新的機制,代碼直接奉上:
服務發現
confd是一個輕量級的配置管理工具,支持etcd做爲後端數據源,經過讀取數據源數據,保證本地配置文件爲最新;不只如此 ,它還能夠在配置文件更新後,檢查配置文件語法有效性,以從新加載應用程序使配置生效。這裏須要說明的是,confd雖然支持rancher做爲數據源,但考慮易用性和擴展性等緣由,最終咱們仍是選擇了etcd。
和大多數部署方式同樣,咱們把confd部署在web server所在的ECS上,便於confd在監測到數據變化後及時更新配置文件和重啓程序。confd的相關配置文件和模板文件部署在默認路徑/etc/confd下,目錄結構以下:
/etc/confd/
├── conf.d
├── confd.toml
└── templates
confd.toml是confd的主配置文件,使用TOML格式編寫,由於etcd是集羣部署,有多個節點,將interval、nodes等選項寫到了這個配置文件裏。
cond.d目錄存放web server的模板配置源文件,也使用TOML格式編寫。該文件用於指定應用模板配置文件路徑(src)、應用配置文件路徑(dest)、數據源的key信息(keys)等。
templates目錄存放web server下每一個應用的模板配置文件。它使用Go支持的text/template語言格式進行編寫。在confd從etcd中讀取到最新應用註冊信息後,經過下面的語句寫入模板配置文件中:
{{range getvs "/${APP_NAME}/*"}}
server {{.}};
{{end}}
經過supervisor管理confd進程。confd在運行後會每隔5秒對etcd進行輪詢,當某個應用服務的K/V更新後,confd會讀取該應用存儲在etcd中的數據,寫入到模板配置文件中,生成這個應用配置文件,最後由confd將配置文件寫入到目標路徑下,從新加載nginx程序使配置生效。
以上是五阿哥運維技術團隊針對Docker容器雲平臺建設實踐,目前已經將權限開放給開發同窗,實現雲上和雲下實例使用一套平臺進行管理,業務實例按需彈性擴容和縮容,規範化的項目管理和發佈流程,實例和業務可按需進行擴容和縮容,實現7*24小時「一站式」的持續交付,開發同窗更聚焦於本身的業務開發,提升了公司的研發過程的效能。
接下來會不斷優化和適配各類業務場景,逐漸完善容器雲平臺,同時會將容器雲平臺各類功能,總結的經驗和教訓不斷分享給你們,給你們在工做中一些參考,避免走重複的「彎路」。