docker 在樂視的實踐之路
摘要:
現在docker 技術越來越火熱,越來越多的公司開始使用docker技術,部署應用。這次分享主要是講如何充分利用 docker 技術,實現代碼到線上環境的部署。 以及在使用docker 中遇到的問題和困擾。
背景:
我們是在14年開始研究并使用docker,最開始主要想利用docker 解決組件化和服務的上線問題。現在慢慢演化成一個提供服務從代碼環境到線上部署的一套解決方案。現在這套系統在內部我們稱之為Harbor。
實戰之路:
1.0 版本:
我們第一版采用docker-registry搭建了私有的鏡像倉庫,并使用python開發的命令行模式,對docker 主機和容器進行管理,使用APP->Service->Container 和主機集群的概念. 一個APP 下對應多個Service, 多個Service 組成一個App, 一個Servier對應多個容器,每個Server 都有對應的配置。
配置信息包括: 內存,名稱,業務描述,鏡像, 容器數量,export端口,環境變量等等。 提供基本的部署,刪除容器,查看容器,添加主機集群等功能。可以將App部署在不同的主機集群中。
1.0 的架構比較簡單, 我們在每個docker 主機上安裝上一個python 寫的agent 代理,專門向etcd 中注冊容器和主機的信息,提供服務發現功能。
命令行工具在部署時候,根據etcd 中的信息,同時根據每個App 的配置采用不同的策略,通過調用docker的api將容器部署在不同的物理機或者虛擬機上。
部署策略保證同一個APP 下的多個容器盡量分散在不同的主機上,防止主機宕機,造成服務不可用。同時根據主機剩余可分配容器內存的概念,保證一個主機不會過量部署容器。
app - service –container 邏輯:
1.0結構如下:
1.0 版本 基本上能解決應用容器的快速部署,但是有很多缺陷:
- 用戶或者開發人員需要直接寫Dockerfile,自己通過docker build命令制作docker 鏡像。 需要培訓DockerFile語法,學習成本比較高。
- 用戶的代碼中加入了跟Docker有關的邏輯,比如Dockerfile,Volume。污染了用戶或者開發人員的代碼
- 鏡像名稱和版本定義沒有統一的規范,而且存在鏡像名稱一樣的風險。
- 沒有可視化的操作界面,App 和容器數量到達一定規模,出現問題就不好排查。
- 不支持應用服務的灰度升級
- Server 升級時,需要先修改Server的配置信息,比如鏡像版本,環境變量, export端口等等,一旦修改失敗,想回退到上一版本,必須提前手工備份配置文件。
我們推廣一段時間后,在1.0 基礎上推出 1.5 版本:
1.5 版本在1.0 結構基礎上,保留了App-Service-Container 概念,同時我們主要做了以下改善:
- 推薦用戶或者開發人員,代碼管理使用git。
- 使用Jenkins ,將用戶和開發人員的代碼與Jenkins 做關聯,用戶一旦在對應分支上提交代碼或者打tag 會觸發Jenkins相應的job自動構建鏡像。實現了代碼到鏡像的自動構建。
- 使用tornado 搭建了一套可視化的web 服務,同時提供restapi接口。Web 界面集成了私有鏡像倉庫的鏡像列表查詢,和單個鏡像版本查看的功能。 利用 web 界面上,用戶和開發人員可以很方便的創建一個APP,并關聯一個鏡像。
- 提供統一的基礎鏡像,只需要用戶提供一個Dockerfile 和start.sh 的腳本,前者用來定義運行環境,后者用來定義容器啟動后所執行的操作,保證容器啟動,服務也啟動。
- 網絡方面使用macvlan。
- 用戶資源隔離,每個用戶只能看到自己的容器和App, Service資源。
1.5 版本在一定程度上解決了代碼到線上環境部署的問題,用戶可以很直觀的看到自己的App和容器資源。以及每個容器的運行狀況。但是我們在內部推廣的過程中,發現存在了很多不盡人意的地方:
- 必須向用戶或者開發人員培訓Docker, Jenkins的使用,Harbor 的使用,每一個系統或者技術的推廣會耗費很大的精力去說明。
- 依然存在鏡像名稱沖突的風險
- 依然需要用戶寫dockerfile,將docker 的邏輯放在代碼環境中,在一定程度上污染了代碼。
- Jenkins個人感覺比較重,在查看鏡像構建過程時,需要登錄到Jenkins系統中去查看。
- App, Service 沒有版本概念,無法做到基于版本的快速升級和回滾。
- 不能提供很好的進入容器的方法,用戶只能在知道ip地址和密碼后,通過ssh方式連接。
- macvlan需要專門給物理機劃分vlan,需要專門的網絡環境。
- 沒有很好的應用資源隔離和共享機制,用戶A創建的App或者容器資源,只能用戶A看到,其他的用戶無法查看,如果這時用戶A離職,則需要人工的去轉移資源。
2.0 版本 構建私有云環境。
2.0 在上一版本的基礎上提出新的一些思路,整體的思路就是按照公有云的思想去構建私有云,并負責應用的開發到上線的整個生命周期:
- 用戶資源隔離和成員管理,用戶A的 APP應用或者主機集群資源可以通過添加成員的方式,來協助管理用戶A的資源。也可以通過轉移owner 的方式來轉移資源的使用權。體現一種團隊協作的概念。
- 去掉之前的Service 概念,改為AppGroup -> App ->Version->Container 的概念,一個Group 下包含多個App 應用,每個應用有多個版本 Version, 每個Version 可以包含多個Container.
每個應用版本包含了:鏡像版本,描述,環境變量,export 端口,volume 映射,和其他高級配置(ssh,webssh密碼)。每個容器都是根據版本的信息去創建。所以能很方便的實現容器的升級和回滾。 - 在原有docker-registry做了修改,加上權限的概念,防止創建相同的鏡像名。并使用namespace,一個namespace下可以有多個鏡像。在邏輯上可以表明這一組鏡像的某種關聯性。比如一個部門可以創建一個namespace,這個部門的鏡像都放在這個namespace下。
- 公有集群和私有集群的概念,集群我們指的是一組docker 主機,物理機和虛擬機都可。公有集群對所有的用戶開放,用戶和開發人員可以將自己的App 應用部署在這些公有的集群上。 用戶和開發人員可以隨便創建自己的私有集群,并添加docker主機。應用可以部署在自己的集群中,實現私有集群的自我管理。公有集群網絡方面可以使用macvlan和NAT模式。而私有集群,我們現在只給用戶提供NAT方式,主要是方便開發人員和業務部門的接入。
- 提供Docker 環境一鍵部署的功能。業務部門分配下的主機資源可以很方便的部署docker 以及相關組件環境。
- 拋棄Jenkins,自己實現鏡像構建。整合到一個界面中。 拋棄繁瑣的Jenkins配置,用戶和開發人員只需要在頁面上選擇所要創建鏡像的基礎鏡像,輸入git地址,分支名,鏡像名,以及在界面上書寫鏡像構建腳本和鏡像啟動腳本即可。 同時在git庫中,設定好系統給定的web hook url。當下一次提交代碼后,會自動觸發構建任務,并在頁面中展示實時的構建過程。鏡像版本強制使用: git tag + commit 號+ 配置變更數目 來命名,這一能方便用戶和開發人員定位鏡像版本和git的commit做關聯。
下圖展示的是我們鏡像相關的操作:
構建日志:
鏡像版本列表:
如何創建鏡像:
鏡像構建腳本:
服務啟動腳本:
-
鏡像分為基礎鏡像和業務鏡像。基礎鏡像即包括我們提供的最基礎的鏡像(我們只提供了幾個基本的基礎鏡像),也包括業務部門在我們提供基礎鏡像基礎上修改的自己業務的基礎鏡像。 業務部門可以創建自己的基礎鏡像,下面的業務可以繼承這個基礎鏡像。
如圖:
- 支持應用的灰度上線, 開發人員或者業務部門在創建完新的app 版本后,可以 選擇特定的容器進行升級,最終測試通過后,即可全部升級。
- 支持容器通過webssh 和ssh 兩種方式訪問。若不想通過ssh 訪問容器資源,可以直接通過web的方式,訪問容器內部資源,實現bug調試以及問題查詢。
- 自動接入負載均衡, 智能負載均衡系統,我們使用nginx 實現,使用go 和etcd 實現nginx 配置自動下發。
- 支持事件操作記錄,包括集群,鏡像,應用的操作事件,方便以后的問題追蹤,下圖是應用的事件記錄:
- 支持快速查看應用部署的拓撲結構,如下圖:
第一層表示的是應用名,第二層表示的是應用所部署到的集群名稱,第三層表示的應用的版本,第四層表示的是容器名稱和運行狀態. 用戶可以在這里直接點擊特定集群,創建特定版本的容器,具反饋,這是最受業務部門喜愛的功能之一。
2.0 版本在架構上 比1.5 版本上做了很大的改動,首先我們使用分層設計。
- 基礎設施層面 docker 主機或者虛擬機,并安裝用go 寫的一個服務發現代理,go-registerd。
- 數據層包括etcd和數據庫,消息隊列以及docker-registry鏡像倉庫。 服務發現代理專門向etcd 中注冊容器和主機信息。
- 執行層 主要包括異步任務處理:harbor-compute ,獲取消息隊列中的任務,執行比如容器的創建,刪除,電源操作,鏡像構建,上傳等任務。可以處理大量的容器和鏡像操作請求,鏡像構建我們提供專門的服務器去提供鏡像構建的操作,鏡像構建完后,自動push到私有鏡像倉庫中。
- 調度層 marine,提供api接口,主要負責每個應用的容器部署調度,鏡像構建的調度,以及集群,主機管理等等。當一個App需要創建容器時,根據所選的集群資源使用情況,以及容器數量等其他的配置進行資源決策,決定每個容器應該創建在哪個主機上,生成對應的任務,投放到消息隊列中。
- 用戶層,分為面向用戶的開放系統:polaris和面向管理員的資源管理系統:ursa。
整體架構如下:
2.0 版本 從15年11月份上線以來,已經陸續創建了上百個應用,200多個鏡像,幾百臺主機,每天構建鏡像400多次,平均每天容器銷毀和創建100余次。鏡像容量在100G左右。
Harbor 基本上在樂視云計算有限公司內部成為了一個開放的容器平臺,主機的添加,鏡像的構建,應用容器的擴容,升級,回滾,現在已經完全實現開發人員和業務部門的自主管理。
開發人員和業務部門的學習成本由原來需要學習docker,Jenkins,harbor 變為單純學習如何使用harbor 即可,而且省去了大量的舊有上線部署和配置手冊,只需要學習如何升級容器即可。
下一步的任務:
隨著社區容器編排系統越完善,我們也正研究kubernetes 和mesos, 也正充分借鑒開源社區的一些設計思路和理念
自我介紹:
張杰, 東北大學 軟件工程
樂視云計算有限公司 云計算高級研發工程師, 容器私有云負責人,4年技術團隊管理經驗, 對新技術有著強烈的好奇心。
qq:695160664
來自: http://dockone.io/article/1091