某股份制商業(yè)銀行的PaaS平臺是由睿云智合(Wise2C)與Rancher合作,基于Rancher做的定制化開發(fā)。基于業(yè)務場景和銀行業(yè)的特殊需求,同時為了兼顧能夠實現(xiàn)對以后Rancher版本的平滑升級,我們在Rancher之上做了一層邏輯抽象。
一、軟件架構與部署方案
整體軟件架構如下圖所示:
頂層的DCOS作為統(tǒng)一的管理平臺,可以通過PaaS以及IaaS提供的API實現(xiàn)對云平臺的集中管控。左側藍色部分是原生Rancher,DCOS與紅色定制化部分通過API來訪問Rancher。由于未對Rancher做任何改動,可以做到對Rancher版本大于1.2的平滑升級。
紅色部分為定制化邏輯抽象部分,歸納起來可以按照功能職責大致分為以下微服務(后面會詳細介紹):
1 鑒權認證
2 資源管理
3 應用編排
4 彈性伸縮
5 日志收集
6 監(jiān)控告警
7 鏡像倉庫
這些微服務在部署時按照Rancher將infrastructure stack部署到環(huán)境中的思路,使用一個獨立的Rancher環(huán)境來部署這些微服務,部署拓撲結構如下圖所示:
圖中每一個虛線框對應Rancher中的一個環(huán)境;“擴展ENV”這個環(huán)境直接使用Rancher server的主機作為Agent,上面運行定制化的微服務。其他環(huán)境分別對應到某個租戶的特定網(wǎng)絡,單個網(wǎng)絡內(nèi)部流量不使用Rancher原生的overlay,而采用Wise2C實現(xiàn)的扁平化網(wǎng)絡,網(wǎng)絡之間流量由外部防火墻控制。
二、角色與權限模型
PaaS平臺的角色與權限模型沿用了Rancher的一部分概念,又引入了自己的內(nèi)容。主要差異在于兩方面:
1 PaaS平臺引入了對鏡像倉庫的管理,這在Rancher中是沒有的;即角色的權限,除包含操作Rancher外,還能夠操作鏡像倉庫。鏡像倉庫與PaaS的權限模型是一致的;
2 另外,客戶引入了租戶的概念,這點與Rancher中不同,租戶是可以跨越多個Rancher的環(huán)境的
Rancher權限模型:
平臺管理員:
擁有整個Rancher平臺的所有權限;
環(huán)境用戶:
1 Owner擁有環(huán)境的所有權限;
2 Member擁有除對環(huán)境內(nèi)部用戶授權外的所有權限;
3 Restricted User擁有環(huán)境內(nèi)部除對用戶授權以及操作基礎資源外的所有權限;
4 Read Only擁有環(huán)境內(nèi)部資源的只讀權限;
PaaS平臺權限模型:
平臺管理員:
等同于Rancher的平臺管理員權限再加上對鏡像倉庫管理的所有權限;
租戶內(nèi)部角色:
1 租戶管理員擁有管理租戶資源以及對租戶內(nèi)部用戶進行授權的所有權限;再加上對鏡像倉庫管理的所有權限
2 高級成員在PaaS平臺內(nèi)擁有對租戶內(nèi)用戶授權以及操作基礎資源外的所有權限;在鏡像倉庫內(nèi),擁有對鏡像倉庫設置鏡像同步規(guī)則、創(chuàng)建、刪除鏡像倉庫Namespace、改變鏡像狀態(tài)等權限;
3 受限成員在PaaS平臺內(nèi)擁有對租戶內(nèi)用戶授權以及操作基礎資源外的所有權限;在鏡像倉庫所屬Namespace內(nèi),擁有上傳、下載鏡像的權限;
4 Read Only在PaaS平臺內(nèi),擁有查看租戶類資源的權限;在鏡像倉庫所屬Namespace內(nèi),擁有查看鏡像倉庫資源的權限;
具體映射關系如下圖所示:
鑒權部分的軟件設計如下所示:
所有對PaaS訪問的API請求均經(jīng)由API proxy做鑒權控制之后代理到系統(tǒng)內(nèi)部具體的微服務上。PaaS不直接參與租戶的增刪查改,API proxy通過與PaaS外部的Keystone通信來獲取用戶角色以及租戶信息。
三、資源管理
網(wǎng)絡部分
1 由于金融行業(yè)對網(wǎng)絡安全性方面的要求比較苛刻,而Rancher所能夠提供的均是基于某個環(huán)境內(nèi)部的overlay網(wǎng)絡。Overlay必然會導致很多報文無法被安全設備透明的過濾,這是行業(yè)內(nèi)無法接受的;因此,必須采用扁平網(wǎng)絡。
2 處于安全的考慮,會出現(xiàn)同一個stack內(nèi)部的多個service需要分別部署到不同的網(wǎng)絡分區(qū)的需求,采用當前Rancher的managed網(wǎng)絡顯然無法滿足需求;因此,必須支持多網(wǎng)絡。
對于扁平網(wǎng)絡的支持,我在之前的文章(在Rancher 1.2中實現(xiàn)基于CNI的扁平網(wǎng)絡)中有詳細的介紹,主要是使用ebtable直接在linux bridge上對流量做控制,從而避免使用overlay;這樣,外部安全設備能夠透明的看到各個容器之間的流量。
對于多網(wǎng)絡的支持,我們是通過在Rancher之上實現(xiàn)一層抽象邏輯來實現(xiàn)的。整個模型演變?yōu)橐粋€網(wǎng)絡映射為Rancher的一個環(huán)境(環(huán)境內(nèi)部運行一個扁平網(wǎng)絡)。這部分主要涉及對平臺中所有網(wǎng)絡的管理,以及維護租戶與網(wǎng)絡之間的映射關系。
下面舉一個例子來描述該流程:
1 平臺管理員在PaaS上創(chuàng)建一個網(wǎng)絡,指定網(wǎng)絡的參數(shù)(子網(wǎng)掩碼、網(wǎng)關、所屬安全域、所屬隔離域等),這些數(shù)據(jù)會保存到數(shù)據(jù)庫;
2 平臺管理員根據(jù)需要為租戶分配第一個網(wǎng)絡;此時,抽象層需要真正在Rancher上創(chuàng)建出網(wǎng)絡所對應的環(huán)境;以及創(chuàng)建監(jiān)控、日志、以及定制化系統(tǒng)所需的system級別的應用堆棧;
3 當平臺管理員為租戶分配第二個以上的網(wǎng)絡時,抽象層還需要將該Rancher環(huán)境與租戶其他網(wǎng)絡對應的Rancher環(huán)境之間建立env link關系,否則跨Rancher環(huán)境的應用堆棧各service之間無法使用Rancher DNS進行互訪。
存儲部分
客戶PaaS在存儲部分最終選定NFS作為其存儲方案,前期也有討論過使用ceph等,這部分我在之前的文章(探討容器中使用塊存儲)中也有專門分析過為什么不選用那種方案。
由于單個租戶可以擁有多個網(wǎng)絡(也就是多個Rancher環(huán)境),而在Rancher中Rancher-NFS driver所創(chuàng)建volume是基于環(huán)境層面的。為了能夠將該volume映射到租戶層面,我們在抽象層中做了這層映射操作。
具體流程如下:
1 平臺管理員在PaaS中指定參數(shù)創(chuàng)建出一個NFS server;同網(wǎng)絡一樣,此時只是將數(shù)據(jù)保存到數(shù)據(jù)庫;
2 平臺管理員為租戶分配NFS server,此時抽象層真正操作租戶網(wǎng)絡所對應的多個Rancher環(huán)境,在逐個環(huán)境內(nèi)添加用于提供Rancher-NFS driver的system stack;
3 假設租戶內(nèi)用戶創(chuàng)建、刪除、更新volume;同上,抽象層需要在逐個租戶網(wǎng)絡對應的Rancher環(huán)境內(nèi)操作volume;
之所以要這樣抽象的原因在于客戶存在跨網(wǎng)絡部署應用棧的需求,因此,存儲必須基于租戶的粒度,實現(xiàn)跨Rancher環(huán)境共享。除此之外,對NFS server的管理方面,客戶方面也有自己特殊的要求:
物理存儲是按照性能分等級的,同一個租戶應該可以同時擁有金牌、銀牌、銅牌的NFS server?;跇I(yè)務的級別,可以為不同級別的微服務指定使用不同等級的NFS server。
因此,與當前Rancher對存儲的使用方式不同體現(xiàn)在:同一個租戶可以關聯(lián)多個NFS server,租戶內(nèi)用戶在創(chuàng)建volume的時候,可以指定NFS server。
四、應用編排
在應用編排方面,基于金融行業(yè)的特殊安全需求,客戶要求應用堆棧能夠基于微服務的安全等級來跨網(wǎng)絡部署同一個應用堆棧,即應用堆棧中的多個微服務可能跨域多個不同網(wǎng)絡。
1 為了實現(xiàn)跨網(wǎng)絡部署微服務,除了對基礎資源(網(wǎng)絡和存儲)模型進行抽象之外,整個應用堆棧的部署流程也需要做相應的調整;
2 另外,對應用堆棧的描述不再使用rancher的catalog,而是基于一套開源的Tosca模板標準;這樣做的目的是方便與OpenStack以及其他平臺貫通,方面以后使用同一個模板來描述整個IaaS和PaaS的編排情況;
3 對應用堆棧以及內(nèi)部微服務的更新,要求提供統(tǒng)一的接口,均通過下發(fā)新的Tosca模板更新應用棧的方式來實現(xiàn)。
在解決應用堆棧的跨網(wǎng)絡(Rancher環(huán)境)部署以及基于Tosca的編排方面,我們在抽象層中操作流程如下:
1 接受用戶輸入的Tosca模板,然后交由translator模塊做模板語法的check以及翻譯,最終輸出能夠分別部署到各個Rancher環(huán)境的rancher-compose文件以及其他附加信息;
2 orchestration模塊需要對translator的返回信息進行資源層面的檢查,比如是否該租戶擁有應用堆棧部署所需的網(wǎng)絡(Rancher環(huán)境)等;
3 基于translator的返回信息,按照各個網(wǎng)絡之間微服務的依賴關系,決定各個rancher-compose的部署先后順序,然后開始往網(wǎng)絡中(Rancher環(huán)境中)部署沒有存在依賴的rancher-compose;
4 基于Rancher環(huán)境中應用堆棧的部署情況,按照依賴順序,逐個部署后續(xù)的rancher-compose;
5 在確保當前應用堆棧在所有Rancher環(huán)境中的rancher-compose都部署完成后,將該應用棧的彈性伸縮規(guī)則下發(fā)到彈性伸縮模塊。
五、彈性伸縮
自動彈性伸縮是客戶基于其業(yè)務場景而定制化的需求,大致如下:
1 首先彈性伸縮的策略是基于時間段的,即按照一天為周期,可以設置在一天的某個時間段內(nèi)采用哪一種彈性伸縮策略;
2 彈性伸縮的策略包括三種:a)基于微服務下所有容器的CPU利用率的平均值;b)基于微服務下所有容器的內(nèi)存使用率的平均值;c)基于時間段,只要進入該時間區(qū)間,直接將容器數(shù)量伸或縮為某個最大或者最小值;在從該時間區(qū)間離去時,恢復容器數(shù);
3 支持對某個微服務的彈性伸縮策略使能和去使能;
在對CPU和內(nèi)存的監(jiān)測時,又有如下規(guī)則:
1 可設置監(jiān)控指標的上下閾值;
2 可設定時長,持續(xù)超過指定時長,容器數(shù)量增加或減少;
3 可設定觸發(fā)伸縮行為時,單次容器數(shù)量增減值;
4 可設定彈性伸縮可調節(jié)的容器數(shù)最大值和最小值;
5 可配置彈性伸縮動作之后再觸發(fā)的時間間隔;
對彈性伸縮功能的實現(xiàn)根據(jù)策略的類型不同大致分為兩種:
1 基于時間的策略,該策略主要是對當前時間與策略時間區(qū)間做匹配,一旦發(fā)現(xiàn)進入到基于時間的策略的時間區(qū)間就基于微服務的索引,找到并更改目標微服務的容器數(shù)量;
2 基于內(nèi)存和CPU利用率的策略本身并不監(jiān)測CPU和內(nèi)存信息,而是依賴于監(jiān)控模塊。在應用編排側添加或更新了某個微服務的彈性伸縮策略后,彈性伸縮模塊會將對這個微服務的彈性伸縮策略轉換為監(jiān)控告警策略下發(fā)到監(jiān)控模塊;同時,監(jiān)聽來自監(jiān)控告警模塊的告警信息。當收到告警時,彈性伸縮就從自己維護的映射表中找到是具體觸發(fā)該告警的微服務,然后基于一系列規(guī)則來決定是否伸縮微服務的容器數(shù)量以及一次調整多少個。
由于彈性伸縮策略被設定于各個時間區(qū)間內(nèi),必然需要維護眾多的定時器。一旦規(guī)則被設定后,就相當于為微服務定義好了一個周期為24小時,基于時間的狀態(tài)機。當微服務數(shù)量較多時,如何保障既管理好這些狀態(tài)機、定時器,又能不消耗掉太多的系統(tǒng)資源是軟件設計的難點。
另外,由于各個運行實例都運行著獨立的狀態(tài)機,如何做好彈性伸縮的高可用(冗余)又能夠保障冗余部分的數(shù)據(jù)同步,也是值得深入思考的問題。
六、日志收集
客戶PaaS對日志的收集主要按照日志的來源可分為三種類型:
1 主機日志收集;
2 容器日志收集;
3 應用日志收集;
對于主機和容器的日志收集相對比較簡單,主要通過對指定目錄的文件內(nèi)容進行收集,然后將收集到的日志信息進行格式化后統(tǒng)一發(fā)送到kafka集群;
對于應用的日志收集相對較復雜,既要不對業(yè)務容器產(chǎn)生侵入又要保障能夠收集到及時的日志。我們是通過在Tosca模板中定義某個微服務的log_files來指定應用日志在容器中的路徑以及擴展名的。
當容器被調度到某臺主機上時,該主機上的日志收集模塊就會基于容器標簽得知該容器內(nèi)的應用日志目錄,通過分析容器的詳情可以獲取到該容器內(nèi)日志目錄所映射到主機上的路徑,從而將對容器內(nèi)應用日志的收集,轉換為對主機上特定文件內(nèi)容的收集。具體的收集方式是采用logstash,通過程序自動修改logstach的配置文件來添加日志來源。
將所有日志收集到kafka之后,客戶再采用第三方的日志分析工具來對日志做特定的過濾、分析、搜索和多維度的展現(xiàn)。
七、監(jiān)控告警
客戶的監(jiān)控需求大致如下:
1 租戶宿主機集群的資源使用情況和運行狀況,具體包括:○?租戶集群的容器宿主機數(shù)量和總體資源使用情況○?租戶集群中不同網(wǎng)絡區(qū)域、等保區(qū)域等細分范圍的容器宿主機數(shù)量和資源使用情況○?集群總體容器數(shù)量、容器在集群各容器宿主機節(jié)點的運行和分布情況○?每個容器宿主機節(jié)點的資源使用情況、運行容器列表
2 應用(包含Stack和Service)監(jiān)控數(shù)據(jù),監(jiān)控數(shù)據(jù)包括應用容器列表(容器IP、所在宿主機)、應用運行情況(健康情況、資源占用)等
3 每個容器所使用CPU、內(nèi)存、網(wǎng)絡、存儲、標簽、端口號等信息進行監(jiān)控,提供Restful API
事件等信息寫入事件審計數(shù)據(jù)庫;同時支持配置事件告警規(guī)則,當激活事件告警功能后,根據(jù)事先設定的告警規(guī)則,從事件審計數(shù)據(jù)庫中讀取和過濾信息,轉換成syslog格式,再將告警信息通過消息隊列發(fā)送到PaaS平臺外部。
該部分的實現(xiàn)主要使用bosun平臺, 容器方面從cAdvisor中采集監(jiān)控數(shù)據(jù),主機方面是直接讀取主機實時信息,對Rancher的審計日志,主要通過讀取Rancher的數(shù)據(jù)庫來實現(xiàn)。所有的監(jiān)控數(shù)據(jù)匯集到bosun之后,通過對bosun做一層封裝,一方面用于按照自定義的格式設置告警規(guī)則、另一方面實現(xiàn)bosun對接Active MQ將監(jiān)控信息發(fā)送到消息隊列,從而對接第三方監(jiān)控大數(shù)據(jù)平臺。
八、鏡像倉庫
鏡像倉庫分為測試倉庫和生成倉庫,這兩個倉庫均實現(xiàn)了與PaaS平臺的權限模型對接,實現(xiàn)單點登錄以及統(tǒng)一的鑒權控制。
另外值得提的是,客戶對鏡像從測試倉庫到生產(chǎn)倉庫的同步的流程劃分為手動和自動,具體如下:
1 鏡像在被提交到測試倉庫后,默認為“開發(fā)中”狀態(tài);
2 開發(fā)完鏡像后,受限用戶通過外部協(xié)同管理平臺來通知高級用戶將鏡像從測試倉庫同步到生產(chǎn)倉庫;
3 高級用戶登錄測試倉庫后,可以修改鏡像同步規(guī)則;在正式同步之前,高級用戶可以修改鏡像的“待同步”狀態(tài)為“開發(fā)中”;
4 如果在生產(chǎn)倉庫中已存在對應的Namespace,且高級用戶勾選了自動同步,測試倉庫會在同步周期超時時同步鏡像并將“待同步”鏡像狀態(tài)改為“同步中”。如果同步成功,狀態(tài)自動更新為“已同步”;否則為“待同步”;
5 如果在生產(chǎn)倉庫中已存在對應的Namespace,且高級用戶勾選了手動同步,需要高級用戶在測試倉庫中手動點擊“同步”按鈕來同步鏡像到生產(chǎn)倉庫;如果同步成功,狀態(tài)自動更新為“已同步”;否則為“待同步”。
九、Q & A
Q: 彈性這塊,擴容好說,縮的話有個問題,就是還有用戶請求在這個容器上,怎么辦?
A: 在該項目中我們并未對這種情況做特殊處理,但是在我們另外的產(chǎn)品中,已經(jīng)考慮到了該問題。正確的方法應該是基于ingress設置一個銷毀容器的寬限時間,即:在這段時間內(nèi),不允許新流量導入即將銷毀的容器,這些容器在該寬限時間到期后,自動銷毀。
Q:請問docker構建網(wǎng)絡是不是要做的事情較多?
A:你說的是基于rancher的扁平網(wǎng)絡方案嗎? 在分享提到的文章中(https://mp.weixin.qq.com/s?__biz=MzAwMDk0MTMzNQ==&mid=2247484308&idx=1&sn=2fec4ba4ed6418c93dd1b7c095daeb04&chksm=9ae00fecad9786fa0a66c71a5bdba528a4dfbb45c737eb2e5beb323bae879d873b15e777de9e&scene=0&key=86f5e7f8149f38079bda614c3ebad4a041be4d0020d4d)有詳細的介紹!你可以參考!
Q:感謝分享,對彈性伸縮部分請教一下:您分享的彈性伸縮的場景業(yè)務周期性很明顯,所以基于時間區(qū)間觸發(fā)采取不同的伸縮操作,如果業(yè)務周期性不明顯,伸縮機制能處理嗎?如何處理?
A:在當前項目中,客戶明確要求按照1天為周期。在我們自己的PaaS產(chǎn)品線中,彈性伸縮可以調整周期(比如:星期、月份等),另外,還可以不按照時間周期,直接基于CPU、內(nèi)存或者某一個可監(jiān)控項。你可以理解為只要能夠被監(jiān)控的監(jiān)控項,都可以作為彈性伸縮的依據(jù)。這部分我已經(jīng)寫了對應的文章,后續(xù)會在“Wise2C”公眾號發(fā)出,請關注!
Q:我目前關注的是日志這塊,怎么才能把日志集中在一起,能不能說的具體點。
A:我們是將日志收集后,統(tǒng)一發(fā)送到kafka集群,你可以理解為拷貝一份集中存儲到kafka集群。這里的集中不是什么難點,難點在于對日志的收集,涉及三個層面:主機、容器、應用。我們的方式是在各臺主機上部署容器化后的logstash,然后通過程序修改其配置模板,從而收集不同目錄的日志。而這些目錄就分別對應著主機日志、容器日志映射到主機的目錄、以及應用日志映射到主機的目錄。
Q:根據(jù)日志標簽獲得應用日志目錄,請問容器標簽具體是什么格式的,采集日志信息中包含節(jié)點信息,容器信息,應用信息等跟平臺、應用相關的元數(shù)據(jù)字段嗎?
A:這里的日志標簽是可以自定義的,相當于主機上的daemon 程序會監(jiān)聽該主機上容器的創(chuàng)建、銷毀等event,一旦發(fā)現(xiàn)容器創(chuàng)建,就去check其標簽,是否有自定義的“日志目錄信息”,“日志文件擴展名信息”。這些日志目錄都有對應的volume掛載到宿主機上,因此通過分析容器的inspect信息,就能夠找到日志目錄映射到宿主機的目錄。而你提到的節(jié)點信息,這些是每個宿主機上的日志收集的服務容器在啟動的時候就定義好的,所有由它收集并發(fā)送出去的日志,都會有該宿主機的標簽。
Q:關于日志收集的時間取值問題,是日志收集點的本地時間還是系統(tǒng)時間,具體如何保持一致?ntp?
A:是日志收集點的本地時間,具體通過NTP,但是要注意,需要保障容器時間與宿主機時間(時區(qū))要保持一致。
Q:彈性伸縮另一個問題,如果不是周期性彈性伸縮是否考慮避免短期脈沖現(xiàn)象引起的不必要的彈性伸縮操作?
A:所以在彈性伸縮的規(guī)則里面有一個參數(shù)為:“retrigger time” 也可以把它理解為一個安全的時間片,再一次伸縮動作之后,必須要等待這個時間片結束之后才會再次觸發(fā)彈性伸縮行為。否則不予響應。