平安容器雲平臺 Padis--傳統金融企業的 Docker 實踐
本文作者: 王耀武@平安科技基礎架構師,更多雲行業技術洞見請訪問七牛雲部落格。
基於 Docker 的容器雲—Padis
目前市面上基於容器雲的產品有很多,對於平安而言,則是基於 Docker 的 Padis 平臺。所謂 Padis,全稱是 PingAn Distribution ——平安分散式平臺。Padis 基於 Docker,實現了平安內部的一個分散式平臺。它的實現採用了 Mesos+Marathon(下面簡稱MM) 框架,可以完成應用程式的快速建立、執行、快速縮容擴容以及故障自愈的功能;平臺上實現了獨立 IP,可以實現任何叢集與外部的或者傳統的 IP 的通訊;平臺負載均衡的方式很多,可以根據容器的動態變化(容器的增刪)做動態調整;平臺內還有獨立的域名解析,可以做到 CMDB 和效能監控的動態更新。
Padis 的「成長」主要歷經以下幾個階段:
- 開發環境 Docker 單機版
- 測試環境 Padis 上線
- 生產環境 Padis 上線
- Padis 承接平安金管家(原平安人壽App) 系統群
下面是對每個階段的詳細敘述。
一、開發環境 Docker 單機版
平安傳統的交付過程耗時很長。從需求發起,到資源申請,到中介軟體互動,這些過程往返很多,會耗費大量的人力和時間。而交付流程長,人力支配不足等原因,會導致交付質量的下降。為了解決交付所面臨的這一系列難題,Docker 就成為了一種最初的嘗試方式。Docker 包含三方面內容(圖 1):倉庫、映象、容器。倉庫這方面需要改進的不多,重點放在映象上面。 2014 年單機版的 Docker 上線,第一版的 Padis 將 Docker 映象整合到 OS。
第一版的 Padis 基於 Docker 和 Docker UI 。 當時的 Docker UI 改了很多的東西(圖 2),原本的 Docker UI 不帶倉庫管理,也沒有映象下載和映象提升的功能, 而更改後的 Docker UI,不僅添加了 Commit 映象功能,還增加了倉庫管理功能,同時也支援定向搜尋下拉或上傳。
圖 2
第一版的 Padis 出來時,著手的重點就是定製化的映象。平安的業務系統非常多,中介軟體用的東西又比較標準化,所以定製化的主要方向就是標準的中介軟體怎麼去配,才能放到映象裡形成一個標準的東西,這個問題解決了,那麼當開發環境的映象可用時,該映象放入生產後依舊可用。此時,將應用包或中介軟體打包起來後就可以快速啟動服務;如果要對這個環境進行復制,將原來環境進行拷貝就可以。這樣一來,交付就可以做到分鐘級別或者是秒級別。
但是,怎麼將中介軟體打到標準映象中,這又是一個問題。一個容器是有限制的,如果什麼東西都打進去,日誌會越寫越多,容器容量就會爆,容器預設大小隻有 10G。金融行業的日誌,它必須要落地、必須要儲存,有一些需要排查的問題如果沒有日誌就會很不方便,因此日誌一定要保留。而把應用都打到裡面去,開始時不會出現太大的問題,但是隨著第一個版本的發行,就出現一個讓人很不爽的問題:要對映象作調整,可是無需對應用的獨立映象進行更新。所以必須要將應用包和日誌全部挪走,只留下 OS 和 中介軟體固定配置和介質,才可行。
因為需要根據一些使用者需求做調整,所以這個版本的 Padis 出來後在平安內部做了推廣並進行反饋收集。對所收集的資訊進行整合,發現單機版的 Docker 存在很多缺陷:一是沒有叢集,不能解決跨 Host 之間的通訊功能;二是沒有健康檢查機制,容器應用故障無法自愈;三是沒有監控和統計資訊,資源使用不可控;四是熟悉 Docker 命令的人不多,要去推廣使用很困難。公司中各種不同部門的人很多,每個部門的關注重點不一樣,當一個部門裡的人根本不瞭解這是什麼的時候,是沒有辦法使用 Docker 的,因此必須做到介面化。所以後續又做了相應的調整,對於使用者一定要映象透明,並把 Docker 做成叢集模式。
對於叢集模式的選擇則做了兩個選項,下面先簡單介紹一下這兩種框架選項。
圖 3
其一是 k8S(圖 3 ),它基於 Go 語言開發,並且底層基於 CentOS。如果選用這個框架,首先在 Go 語言的學習成本上會耗費很多精力,再者,平安的底層基本是基於 Red Hat Linux ,所以要將 Red Hat Linux 和 CentOS 之間做轉換又是一個很複雜的問題。鑑於這兩個原因,最後選用了 MM 框架,MM 框架解決了這兩個問題。
圖 4
MM 框架(圖 4)結構簡單,並且是基於 Java 開發,開發人員佔比很多,選用 MM 框架,不僅在上面可以做很多的二次開發和介面,底層也可以選用 Red Hat Linux。這些最基本的問題 MM 都可以解決。而伺服器資源池化、容器應用關聯、故障自愈、資源隔離、事件驅動也是 MM 框架可以解決的問題。
利用 Mesos 可以實現資源池化,包括對後臺的資源進行配置、管理。容器應用關聯,可以實現容器的動態伸縮。Marathon 框架本身會提供故障自愈這個功能,平安經常會做一個靜態的頁面,當使用 HTTP 協議訪問該頁面時,會返回一個設定好的字串, 如果不是這個字串,則會被認為是訪問異常,此時就會將原有容器刪除,之後進行重啟。資源隔離是基於 Mesos 的資源管理所做的,在後臺物理機或者是虛擬機器上打上標籤,當進行資源分配時,不同的資源自然就會落到其所對應的不同的伺服器上。平安有很多保險公司,而監管的要求是必須進行物理隔離,因此要進行資源隔離。對於事件驅動而言,在 Marathon 做容器的任何起停時,都會同時在Marathon 有 event 生成,可將自身的 API sever 註冊到 Marathon 的 上 ,之後監聽所有的 event ,根據返回的所有 event 進行解析,並做一些相應的任務下發。
叢集模式的選擇確定了,接下來就是如何解決跨 Host 之間的通訊功能問題。平安存在一些歷史性的遺留問題,一是容器沒有獨立的 IP,無法與容器叢集外面的伺服器進行通訊,當時採用的解決方案是做獨立 IP;二是由於沒有 IP,所以也不存在 DNS ,這樣就無法實現跨安全區域,平安的域名很多都是通過 DNS 做負載的,所以 DNS 不可或缺;其次是負載均衡和共享儲存的問題。下面是就獨立 IP 和 DNS 的解決方案詳述。
圖 5
首先是關於獨立 IP 的幾個問題(圖5):
- EJB 邏輯,共享儲存,傳統的共享儲存使用的是 Nas,Nas 則基本上都需要用到獨立 IP 做二層進行對接 。
- 組播與 HA,不論兩個容器在不在同一個物理機上,都要保證它們之間的組播相通。
- 要與傳統環境對接,因為不能將所有系統都搬到平臺上面來。要與傳統環境進行對接,必須與平臺外的伺服器應用做通訊,這就需要獨立 IP 。
- 使用者操作習慣,使用者需要登入主機檢視日誌,配置等相關資訊。因此不僅要在物理機上登入,也需要在容器上登入,所以獨立 IP 也發揮了很大的作用。
圖 6.1
圖 6.2
圖 6.3
什麼是 EJB 邏輯?EJB 當中存在一個 Cluster 的概念(圖 6.1),假設 Cluster 中有三臺伺服器,2.1 、2.2 、2.3 ,三臺伺服器上都做了容器,當 Container 端對他們進行訪問時,首先都會通過 T3 地址來呼叫(這裡沒有域名,所以選用的是 IP,在三個 IP 裡隨機取一個,這裡取 192.168.2.1)。首先,會發出 EJB Create Request 請求(圖 6.1),之後 2.1 會返回一個叢集資訊 Return Stub message (圖 6.2)給 Client,並告訴 Client 這個叢集中間有哪些伺服器,之後 Client 這邊會再發出 EJB Channle Create 的請求(圖 6.3), 此時不管叢集中有多少伺服器,都會建立 EJB 長連線。
圖 7
在 Padis 平臺的初始版本中,沒有獨立 IP,容器與外面通訊是基於埠 Mapping 的方式實現,這樣EJB 邏輯就會如上圖(圖 7)。這樣就出現了一個問題,假設容器裡的地址是私網 IP:172.17.0.2(外部不可見),而宿主主機的 IP 是 192.168.2.2,當請求發到這裡時,因為 172 的 IP 對外不可見,所以只能夠連線到 192(物理機)的 IP ,再通過對物理機進行埠 Mapping 的方式來獲取 172 的 IP (這是在組播通的情況下,會返回 172 的 IP )。可是,即便是獲取了 172 的 IP 地址,依舊是不能與外部建立連線的,因為 172 的 IP 對外是不可見的,所以導致容器也不能進行連線,因此要求它必須有獨立的 IP 。這裡有一點要強調,Docker 不支援 overlay。
圖 8
圖 8 是平安對 Padis Network 的一個簡單描述。圖左側的 API Server(基於 Python) 主要包括 Message Center 和 Network,Message Center 會註冊到 MM 框架當中,接收 Marathon 框架的所有 event ,用來進行分析處理,右側從上到下依次是 MM 框架、計算節點(物理機中裝了 Openvswitch,在上面起容器)、自己設計的閘道器伺服器(基於 Linux 伺服器上和 Iptables 實現)。 整個過程如圖 8 所示,Message Center 收到 event 訊息後,獲取容器建立,刪除,重啟等動作的 event,通過基於 Ansible 搭建的任務分發平臺把相應的動作下發到響應的伺服器上。
圖 9
圖 9 是 Docker 宿主主機實現的簡單示意圖。首先所有的物理機/虛擬機器(用 trunk 實現了物理機裡面跑所有 VLAN 的容器)的物理網絡卡都要通過 Openvswitch 加入到 ovs0 中,啟動容器後用Pipework 給容器指定一個 IP、閘道器、VLAN,這樣就可以實現 WEB 通訊。宿主主機的 IP 是 10.30.1.11 (第一版用的是雙網絡卡,其中 eth0 是管理網絡卡,eth1 是宿主主機的網絡卡,容器啟動後會和它進行 mapping),在這裡必須記住要給容器加路由,否則會由於Marathon自身的故障自愈功能,導致不可訪問。當然,此時也可指定相關命令,自動下發的對容器裡的路由進行調整。
在這些裡面,IP 是一個很重要的概念,所以,接下來介紹一下 Padis 平臺的 IP 管理。
對於 Padis 的 IP 管理有以下幾點:
- IP 地址池可以在使用者建立資源池時,動態的生成網段資訊。
- 網段生成時,可以自動在 Gateway 上配置閘道器和 VLAN 資訊(生產環境取消了 Gateway )
- IP 狀態設定增加為三種:預留、已分配和未分配。
- 故障自愈是指,容器和 IP 本來是繫結在一起的,但是,將容器刪除後該 IP 也會隨之刪除。
圖 10
剛剛上面講的是對 IP 的訴求,下面介紹平安關於 DNS 的需求。
平安的 DNS 安全區域架構主要分三種(圖 10):WEB 層(做展示,WEB || 提供給內部員工使用,DMZ 給公網或者合作伙伴使用)、SF 層(應用邏輯層) 、DB 層。在三層架構時 ,DMZ 上要求做雙向的 NAT ,即在 DMZ 上所看到 SF 的 IP 地址不是真實的,在 SF 上看到 DMZ 的 IP 地址也不是真實的。 做分散式協調的時候,也會存在這樣的問題,跨安全區域時,因為做了 NAT,你所看到的地址,並不是真實,可以進行訪問的地址。這樣一來,在對外提供服務時,你需要去給人家提供 IP 地址,才能讓人家進入,這樣會導致使用者體驗非常不好。 對於應用層,會經常出現跨域的問題,所以域名是必須要有,且必須要一致,還有就是平安內部會有一些應用需求,比如要做單點登入( SSO ) ,它是基於域名做的,所以也要求系統必須有域名。
對於 LB( Load balancing ),根據收集到的需求和歷史經驗做以下分析:一是軟體負載均衡,對金融公司來說,負載均衡的要求是非常穩定的,不能出事,軟體負載均衡的可靠性和效能不好,所以不被認可;硬體負載均衡的效能肯定是要高於軟體負載均衡的,可是也存在相應的問題,硬體負載均衡的成本相對很高,部分系統的使用者量沒有必要用硬體負載均衡。
針對 LB 的這 幾種情況,平安提出了三套方案:
軟體負載均衡 HAProxy
基於容器,在容器上面搭建一個 HAProxy。優點:可以實現基本功能、新版的可以做應用路由(可以根據不同規則,向不同應用上分發路由)、動態更新配置(通過 API 更改配置檔案然後進行 Reload)。
缺點:高併發能力比較弱、SSL 解除安裝能力差。軟體負載均衡 Lvs+Nginx LVS+Ospf 排程機自由伸縮,自由擴充套件(最大 8 臺,受限於網路裝置允許的等價路由數目);一個 LVS 後端可以搭建多個 Nginx。
優點:併發能力比較高、可以很輕易的完成動態配置更新、SSL 解除安裝能力好( LVS 可以搭建多個 Nginx,Nginx 多了,解除安裝能力自然有所提升)。
缺點:後端 Nginx 發生頻繁變化時(例如由 10 個變成 20 個),當進行等價路由演算法時,此時便會發生路由抖動。
- 硬體負載均衡 LTM
做了自動化配置開發、做了動態介面配置。
缺點:本身擴充套件能力不好、成本高。
測試環境 Padis 上線
圖 11
圖 11 是基於以上問題,搭建出來的一個測試環境框架。首先提供給使用者看的是 Portal(基於 JS 寫的),下面的 API 是基於 python 寫的。接下來是 MM 框架,Log 是日誌雲,Log 旁邊是認證模組和硬體負載均衡 LTM 。 圖中紅色那塊就是倉庫,開發環境時所用的映象全部在倉庫裡面,映象中包括使用者認證配置、基礎環境的調優等等,倉庫下面是儲存,儲存主要用 Nas。現在的容器支援虛擬機器和物理機的運維理念與開發不同,節點越少越好,這樣故障點也會越少,所以平臺的主要計算節點大部分是物理機。最後,在網路模組( Network )上設定了 Gateway 。
圖 12
圖 12 是一個邏輯示意圖。首先從 Potal 進入,呼叫 API 建立網段或者應用 ,API 分為認證、DNS、Traffic( LB )、Network 、Cache 這幾個模組,當時的想法是將資料庫也一同打包進來,但是由於平安的庫太大(動輒幾個 T ),所以就放棄了這樣的想法。 Padis API 可以進行使用者認證、DNS 的增刪改。從圖 12 可見,所有模組彼此相互獨立,所有系統都是通過 Portal 進來,併發送請求到 API,API 根據不同的請求做相應的操作,所有的操作會直接傳送給Marathon框架,Marathon 框架也會根據事件再給 API 相應的反饋,API 同時也會根據反饋結果再做相應的操作。
生產環境 Padis 上線
與測試環境相比,對生產環境的要求是很高的。對於生產環境,主要做了以下幾點改造:
- 測試環境的效能達不到要求,穩定性有問題,於是取消 Gateway Server ,生產環境中 全部改用網路裝置。
- CMDB,測試環境是自己獨立的,生產的要與傳統的 CMDB 對接,資料需要寫入傳統的 CMDB 裡面去,所以需要開發 CMDB 介面,進行資料匯入。
- 監控告警。需要搭建 Zabbix 監控平臺,對接傳統的監控平臺。
- 效能資料收集。在做故障分析時,都是基於對效能資料的分析,然後得出結果,並且要根據效能資料, 對容量進行判斷,比如是否要做一些動態的擴容縮容(關於擴容縮容最初的想法是做成自動化的,但存在的問題是,如果做成自動化,當別人攻擊時,後臺資源則不一定能扛住)。
- DNS 改造。對接生產網路的 DNS,實現動態更新 DNS(在這個地方專門寫一個 DNS 模組,跟平安的 DNS 對接,內部的 DNS 會做一個節點,在上面做單獨配置,所有的配置更新都在裡面做)。
- 日誌儲存。測試環境用的是 Ceph,沒有用到本地磁碟,把所有空餘的物理磁碟做了一個Ceph,但測試時用的 Ceph 是不成熟的,所以改成了 NAS,同時將日誌接入到日誌雲裡進行分析、處理和歸檔。
圖 13
經過以上幾點改造,生產環境框架就變成如圖 13 這樣(添加了 CMDB 模組)。
Padis 承接平安金融管家系統群
平安 Padis 在今年上半年的時候承接了平安金融管家(原平安人壽)系統群,當時系統群所運用的平臺,就是 Padis 平臺。
傳統環境的搭建,從 0 到上線最快 3 天,可是 Padis 卻完成了系統從 0 到上線只用 5 分鐘這個過程,當中還包括所有的除錯環節。Padis 當時做了一個網際網路出口,還有一個 LVS + Ospf 的改造,並且同時由 50 路 Nginx 和多路 LVS 提供服務。因為當時所有的配置都是標準化的,只需將包上傳,之後立馬就能使用,所以耗時短。那也是 Padis 在生產環境的第一次亮相,經過這一次之後,總結出了一個經驗:隔離集團和其他系統的相互影響,不能因為搞活動而影響系統的正常執行。