伴隨着微服務的架構的普及,結合開源的Dubbo和Spring Cloud等微服務框架,宜信內部不少業務線逐漸了從原來的單體架構逐漸轉移到微服務架構。應用從有狀態到無狀態,具體來講將業務狀態數據如:會話、用戶數據等存儲到中間件中服務中。前端
微服務的拆分雖然將每一個服務的複雜度下降,但服務實例的數目卻呈現出爆炸式增加,這給運維增長難度,一方面是服務部署、升級,另外一方面是服務的監控故障恢復等。linux
在2016年,容器技術尤爲是Docker迅速流行起來,公司內部開始嘗試將容器放到容器內運行,雖然經過容器解決了服務發佈問題,但不少容器的運維仍然讓運維捉襟見肘。宜信是一家金融科技公司,在引入開源組件的時候,穩定可靠是做爲考量的最重要標準,在2017年初kubernetes慢慢成熟,成爲容器的管理標準,而且被國內外不少公司採用,在這種背景下,宜信借鑑開源社區和商業PAAS平臺產品,基於kubernetes自研一套容器管理平臺。nginx
整個架構圍繞kubernetes構建,分爲四個層級,最底層主要是基礎資源,包括網絡、計算、存儲,全部的容器都是部署在物理服務器上,容器掛載商業NAS存儲,網絡經過vxlan互連;中間層核心的是資源調度層,主要完成多集羣的管理、發佈部署、智能調度、自動伸縮等,這層主要是資源管理和服務編排;左側面是提供系統安全,主要是爲了系統安全和容器鏡像安全,右側面是一套代碼自動編譯、自動構建、自動部署系統;中間件層主要提供經常使用的中間件服務,Nginx配置和監控告警等;最上層的是用戶接入層,主要提供用戶的操做入口。總體架構以下圖所示:git
公司大部分的服務都是經過Nginx反向代理對外提供服務,爲了服務的隔離和負載均衡,總計十幾套的Nginx集羣,這些nginx的版本、配置方式各有不一樣,致使單純靠人工去運維的成本很是高並且容易出錯,而且容器的IP地址不固定,沒法直接配置到nginx後端。自研了一套nginx管理系統,主要是爲了解決nginx的模板化配置,以下圖所示:github
Nginx-mgr提供HTTP請求,負責接收nginx配置請求,並更新到etcd,每一個nginx-agent經過watch Etcd批量刷新nginx的配置。在實際的生產環境裏,部署的是阿里開源的Tengine而並不是nginx,因爲配置基本相同不作區分。每一個服務都配置了健康檢查,這樣可以保障在後端故障中自動切換。若是有虛擬機場景須要手動切換,下圖展現了手動切換nginx的頁面:web
因爲不少業務都是虛擬機和容器混跑的狀況下,若是後端是容器,咱們經過kubernetes的API獲取容器的IP地址動態刷新。算法
雖然kubernetes自己存在採用高可用的部署架構,避免單點故障,但這遠遠還不夠,一方面是由於單個kubernetes集羣部署在一個機房,若是發生機房級別的故障,將會致使服務中斷,另外一方面因爲單個kubernetes集羣自己故障,如集羣的網絡配置錯誤致使整個網絡故障等,都將會影響業務的正常使用,在宜信將kubernetes部署在多個機房內,機房之間經過專線互連。那麼多集羣的管理將成爲主要難點:第一是如何分配資源,當用戶選擇多集羣部署後,系統根據每一個集羣的資源用量,決定每一個集羣分配的容器數量,而且保證每一個集羣至少有一個容器。集羣自動伸縮時,也會按照此比例建立和回收容器。第二是故障遷移,如圖中的集羣控制器主要爲了解決多集羣的自動伸縮和集羣故障時的容器遷移,控制器定時檢測集羣的多個節點,若是屢次失敗後將觸發集羣容器遷移的操做,保障服務可靠運行。docker
第三是網絡和存儲的互連,因爲跨機房的網絡須要互連,咱們採用vxlan的網絡方案實現,存儲也是經過專線互連。容器的鏡像倉庫採用Harbor,多集羣之間設置同步策略,而且在每一個集羣都設置各自的域名解析,分別解析到不一樣的鏡像倉庫。shell
因爲業務人員對容器技術還存在疑慮,因此大部分應用都是虛擬機和容器的混合部署,容器經過域名訪問虛擬機和虛擬機經過域名訪問容器都是廣泛存在的,爲了統一管理域名,咱們沒有采用kubernetes自帶的kube-dns(coreDns)而採用bind提供域名解析。經過kubernetes支持的Default DNS策略將容器的域名指向公司的DNS服務器,並配置域名管理的API動態添加。數據庫
kubernetes的CNI的網絡方案有不少種,主要分爲二層、三層和overlay方案。一方面機房並不容許跑BGP協議,而且須要跨機房的主機互連,因此咱們採用了flannel的vxlan方案,爲了實現跨機房的互通,兩個集羣的flannel鏈接到同一個etcd集羣,這樣保障網絡配置的一致性。老版本的Flannel存在不少問題,包括:路由條數過多,ARP表緩存失效等問題。建議修改爲網段路由的形式,而且設置ARP規則永久有效,避免由於etcd等故障致使集羣網絡癱瘓。
Flannel的使用還須要注意一些配置優化,默認狀況下天天都會申請Etcd的租約,若是申請失敗會刪除etcd網段信息。爲了不網段變化,能夠將etcd數據節點的ttl置爲0(永不過時);Docker默認是會masq全部離開主機的數據包,致使flannel中沒法獲取源容器的IP地址,經過設置Ipmasq添加例外,排除目標地址爲flannel網段數據包;因爲flannel使用vxlan的方式,開啓網卡的vxlan offloading對性能提高很高。Flannel自己沒有網絡隔離,爲了實現kubernetes的network policy咱們採用canal,它是calico實現kubernetes的網絡策略的插件。
爲了支持Devops流程,在最初的版本咱們嘗試使用Jenkins的方式執行代碼編譯,但Jenkins對多租戶的支持比較差。在第二版經過kubernetes的Job機制,每一個用戶的編譯都會啓動一個編譯的Job,首先會下載用戶代碼,並根據編譯語言選擇對應的編譯鏡像,編譯完成後生成執行程序,若是jar或者war文件。經過Dockerfile打成Docker鏡像並推送到鏡像倉庫,經過鏡像倉庫的webhook觸發滾動升級流程。
系統設計了應用的邏輯概念,kubernetes雖然有服務的概念,但缺乏服務的關聯關係,一個完整的應用一般包括前端、後端API、中間件等多個服務,這些服務存在相互調用和制約的關係,經過定義應用的概念,不只能夠作到服務啓動前後順序的控制,還能夠統一規劃啓停一組服務。
容器的日誌歸集使用公司自研的watchdog日誌系統,每臺宿主機上經過DaemonSet方式部署日誌採集Agent,Agent經過Docker API獲取須要採集的容器和日誌路徑,採集日誌併發送到日誌中心,日誌中心基於elasticsearch開發,提供多維度日誌檢索和導出。
容器自己資源監控的性能監控經過Cadvisor + Prometheus的方式,容器內業務的監控集成開源的APM監控系統uav(https://github.com/uavorg/uavstack),完成應用的性能監控。uav的鏈路跟蹤基於JavaAgent技術,若是用戶部署應用勾選了使用uav監控,系統在構建鏡像時將uav的agent植入到鏡像內,並修改啓動參數。
除了上述幾個模塊外,系統還集Harbor完成容器鏡像的多租戶管理和鏡像掃描功能;日誌審計是記錄用戶在管理界面的操做,webshell提供用戶的web控制檯接入,爲了支持安全審計,後臺會截獲用戶全部在webshell的操做命令並記錄入庫;存儲管理主要是集成公司商業的NAS存儲,爲容器直接提供數據共享和持久化;應用商店主要是經過kubernetes的operator提供開發和測試使用的場景中間件服務。
在容器推廣的初期業務開發人員對容器還不是很熟悉,會下意識認爲容器就是虛擬機,其實他們不只是使用方式的區別,更是實現方式和原理的差別,虛擬機是經過模擬硬件指令虛擬出操做系統的硬件環境,而容器是在共享內核的前提下提供資源的隔離和限制。下圖展現了4.8內核中linux支持的7種namespace。
換句話說,其餘的都沒有差別,譬如,時鐘,全部容器和操做系統都共享同一個時鐘,若是修改了操做系統的時間,全部容器都時間都會變化。除此以外,容器內proc文件系統也是沒有隔離,看到的都是宿主的信息,這給不少應用程序帶來困擾,JVM初始的堆大小爲內存總量的1/4,若是容器被限制在2G的內存上限,而宿主機一般都是200+G內存,JVM很容易觸發OOM, 解決方案一般是啓動時根據內存和CPU的限制設置JVM,或者藉助lxcfs等。
Cgroup的資源限制目前對網絡和磁盤IO的限制比較弱,v1的cgroup只支持direct IO的限制,但實際的生產環境都是些緩存的。目前咱們也在測試cgroup v2關於IO的限制。當最新的CNI已經支持網絡限速,結合tc能夠很好的達到這個效果。
Kubernetes自帶了不少調度算法,在啓動容器以前會經過調度的算法,這些算法都是須要過濾全部的節點並打分排序,大大增長了容器的部署時間,經過刪除一些無用的調度算法,從而提升部署的速度。容器採用反親和的策略,下降物理機故障對服務形成的影響。
雖然kubernetes開啓了RBAC,但kubernetes token仍是不建議掛載到業務容器內,經過關閉ServiceAccountToken提高系統的安全。
Docker鏡像存儲使用direct-lvm的方式,這樣性能更優,在部署的時候劃分單獨的vg,避免由於Docker問題影響操做系統。經過devicemapper存儲限制每一個容器系統盤爲10G,避免業務容器耗盡宿主機磁盤空間,容器運行時須要限制每一個容器的最大進程數量,避免fork炸彈。
Etcd裏面記錄了kubernetes核心數據,因此etcd個高可用和定時備份是必須的,在kubernetes集羣超過一百個節點之後,查詢速度就會下降,經過SSD可以有效提高速度。本系統在kubernetes以外經過數據庫保存服務和
關注證書的有效期,在部署kubernetes集羣時候,不少都是自籤的證書,在不指定的狀況下,openssl默認一年的有效期,更新證書須要很是謹慎,由於整個kubernetes的API都是基於證書構建的,全部關聯的服務都須要修改。
Docker容器加K8S編排是當前容器雲的主流實踐之一,宜信容器集羣管理平臺也採用這種方案。本文主要分享了宜信在容器雲平臺技術上的一些探索和實踐。本文主要包含了Nginx自助管理、 多集羣管理、DNS解析、網絡方案、CICD服務編排、 日誌監控、kubernetes 優化一些技術工做,以及宜信內部容器雲平臺化的一些思考,固然咱們還有不少不足,歡迎各路英雄來宜信進行深刻溝通和交流!
做者:陳曉宇
來源:宜信技術學院