1. 程式人生 > >易寶支付基於Kubernetes的私有容器雲從0到1的建設之路_Kubernetes中文社群

易寶支付基於Kubernetes的私有容器雲從0到1的建設之路_Kubernetes中文社群

【編者的話】本次分享將為大家介紹易寶支付私有容器雲從0到1的建設之路。包括技術選型、理論基礎、基於Kubernetes的容器雲和CI/CD落地過程中的挑戰和踩過的坑。

20170519135250

建設背景及目標

Docker技術流行開來之前,保證軟體交付的質量和速度對於大多數企業來說都是困難的。業務的複雜性帶來了應用的複雜性,面對成千上萬的不同應用,運維部門需要時刻應對來自不同應用、不同環境的挑戰。特別是在自動化運維程度不高的企業,“人肉運維”成了解決問題的常用手段,人肉運維使軟體交付的週期變得漫長、人為事故風險升高。 2013年,Docker橫空出世,它的”Build once, Run anywhere”的特性讓軟體交付煥然一新。我們在認真調研了Docker技術後,決定構建自己的私有容器雲,背景和目標如下:

實現運維自動化是我們立項之初最主要的目標,而它又是實現後面目標的基礎。這個因素直接決定了我們的技術選型。

技術選型

我們是在2015年6月份開始調研技術,2015年8月份開始容器雲立項,首先要面對的問題,就是如何進行容器編排引擎的選型,可供選擇的有Swarm,Mesos,Kubernetes,甚至自主研發叢集編排,我們認真調研了每一種方案:

20170519135301

Swarm當時是0.4版本,功能還相對簡單,優勢是技術棧比較簡單,小團隊即可駕馭,但是考慮到它不是穩定版,雖然它發展很快,但是沒有解決我們現有的問題,所以Swarm不被優先考慮。

Mesos當時是0.23版本,它能夠勝任大規模場景的容器編排,偏重於資源抽象,與我們大多數是Java Web的應用的場景不符,另外,Mesos技術棧與我們現有技術棧差別太大,不得不放棄這個選擇。

自主研發容器編排引擎我們也考慮過,但是經過認真的探討,自研編排引擎對標三個開源的元件的功能,研發投入需要很多的成本,可能結果並不能達到預期,投入產出比低。另外,容器雲作為底層的基礎設施,選擇更要慎重,如果自研專案失敗,可能會離主流的容器技術越來越遠,機會成本太高,所以自研的路線也被否定。

Kubernetes是我們的最終選擇,它當時是1.0.2版本,已經是”Production Ready”,我們選擇Kubernetes的最主要的原因是它理念的先進,而且非常適合我們公司的主流應用,Java Web應用都是Long time running的任務,Kubernetes的”Replication controller”對它支援非常好。Kubernetes以應用為中心的理念和社群的活躍度更是堅定了我們的選擇,歷時三個月的技術選型終於落下帷幕,我們決定使用Kubernetes構建我們的私有容器雲平臺。

理論基礎和原則

在我們決定使用Kubernetes的作為容器編排引擎後,關於選型的爭論持續了很長的一段時間,當時國內Kubernetes的使用者還比較少,很難找到成功的案例。我們需要深入的研究Docker, Kubernetes相關的容器技術,確保我們的決策是正確的,這對我們構建容器雲至關重要。經過很多的調研和討論,我們發現容器雲的是有一套完成的理論基礎支撐的,這些理論又引申出我們構建容器雲的原則:

20170519135313
  • 不可變基礎設施,是利用Docker映象的不可變性,以更加便捷的方式維護基礎設施:當基礎設施損壞或者變更時,以直接替換的方式達到目的,而不是通過修繕損壞的基礎設施,這麼做需要替換的成本足夠低,Docker顯然做到了這一點;對於已經執行的Docker容器,如果它出現異常,不再是傳統ssh上去除錯的方式,應該是殺掉這個容器,重新啟動一個新的容器;替換操作具有快速和可重複的特性,任何操作都可以隨時回滾,安全可靠;對於生產環境的運維,不可變基礎設施的理念尤為重要,很多事故都是在生產環境中直接修改造成的。
  • 基礎設施即程式碼,管理基礎設施像管理程式碼一樣,每個基礎設施都是“可描述”的,例如Kubernetes中的Node概念,他們也應該作為“程式碼”的一部分以程式碼的方式進行管理。
  • 可程式設計的基礎設施,基礎設施不僅僅是提供計算、儲存、網路資源,還要為上層應用提供可程式設計的介面,讓上層應用可以更加靈活的使用基礎設施,容器雲從立項之初就考慮到了這一點,容器雲平臺有一套完整的對外Restful API,可供上層應用,甚至外部應用呼叫。

保證構建容器雲的過程能夠正確的進行,還需要一些原則,”Build once,Run anywhere”,一個Docker映象要貫穿QA到生產環境的每個環節,不允許QA和生產的映象出現不一致的情況。”All in one”,對於Java Web應用,由於歷史原因,可能多個Web App執行在同一個Tomcat中,要求每個Docker映象中只執行一個Web App。

以應用為中心,是我們最重要的原則,也是建設容器雲的出發點,這個原則確保我們關注的重點是應用,而不是進行計算資源的抽象和資源的排程,我們的理想目標是,在“優雅地“管理應用的整個生命週期同時,順便做好資源抽象,提高資源的利用率。

分層治理,基礎設施的治理由容器雲完成,上層應用的治理由應用治理層負責,從SaaS,到PaaS,再到CaaS,分層治理,各層通過介面相互呼叫,層與層之間互不侵入。

以Kubernetes為中心構建容器雲

20170519135321

容器雲的目標決定了我們面對的是應用的管理,即應用對應的docker容器的管理,這就要求我們要以Kubernetes為中心構建容器雲,而不是以docker為中心。Docker只作為應用打包、傳遞、執行時的工具,所有的API都要面向Kubernetes進行設計。

容器雲要實現高可用的基礎設施,能夠支援多個數據中心。對於應用,要有多維度的高可用保證,要貫通部署流水線,通過CI/CD實現快速交付,另外,容器雲的建設肩負的額外目標是要為未來2~4年的技術發展做鋪墊,為應用的CloudNative改造和整個技術團隊的DevOps實踐奠定基礎。

容器雲第一步是實現應用的全生命週期管理,讓應用實現秒級的上線、回滾、升級、擴容/縮容、下線。由於歷史的原因,有些應用的配置和環境耦合在一起,有的應用是對於外部依賴是硬編碼(例如服務方的IP地址)等,這些應用在遷移至容器雲之前需要進行改造。

容器雲要實現多資料中心多活,以保證資料中心級的高可用性。對於彈性擴容,我們的計劃是先實現手動擴容,再實現自動擴容; 對於自動擴容,先實現基於CPU/Memory的自動擴容,再實現基於Custom Metrics的自動擴容。與大多數構建容器雲的方式不同,我們首先解決生產環境的運維自動化的問題,其次再解決容器的構建問題(即CI/CD)。我們的網路選型是flannel,萬兆網路,flannel雖說有效能損失,但遠能滿足我們的實際需要。儲存我們使用Ceph的RBD方式,使用一年多來,RBD的方案非常穩定。Ceph FS的方式我們也有嘗試,但是由於團隊精力有限和可能的風險,一直沒有正式使用。

高可用基礎設施

容器雲要實現高可用的基礎設施,多維度保證應用/服務的高可用性:

20170519135329

在應用層面,每個應用有至少3個副本,通過Kubernetes ReplicationController/ReplicaSets來保證。強制每個應用暴露健康檢查介面,通過設定liveness和readness保證應用異常後能夠被及時的發現,從而用新的例項代替。

Kubernetes的元件也要實現高可用,特別是ETCD叢集的高可用,定期備份ETCD的資料是個好習慣。

為了保證資料中心級別的高可用,我們在每個資料中心部署了一套Kubernetes叢集,每個資料中心能夠獨立存活,多個數據中心互相災備。

計算資源QoS與超賣

20170519135335

由於資源限制,技術人員往往過於關注單機的資源利用率。Docker(Cgroup、Namespace)提供的資源共享與隔離的機制,讓我們對資源利用率有了新的認識,特別是使用容器編排引擎後,我們對資源的理解應該在叢集維度進行考量,而不是在考慮單機的利用率。同樣,在整個資料中心,甚至多個數據中心進行資源利用率的綜合考量也是非常必要的。

在提高資源利用率、降低成本的同時,需要在服務的QoS與優化資源利用率之間有個平衡。我們的原則是在保證服務質量的同時,儘量提高資源的利用率。

根據Kubernetes的資源模型,在Pod level的QoS分為三個等級:Guarantee、Burstable、BestEffort,我們也是依照這三個級別對應我們應用的優先順序來制定資源超賣的標準。

我們對應用設定的QoS標準:

  • Kubernetes自帶的元件使用Guarantee
  • 重要的元件和應用,比如ZooKeeper、Redis,使用者服務等使用Guarantee
  • 普通的應用(Burstable)按照重要性分級,按重要程度CPU分為2,5,10三個超賣標準,10倍超賣適合boss後臺類的應用,大多數適合訪問量不高。記憶體使用固定的1.5倍超賣標準。

有一點需要特別注意,在生產環境中,不要使用BestEffort的方式,它會引發不確定的行為。

容器雲管理平臺

20170519135343

隨著越來越多的應用遷移到容器雲中,需要建立一個視覺化的管理系統,我們使用Kubernetes原生API搭建一套Web管理系統,通過對Namespace/ResourceQuota/Deployment/Service/Endpoint等API的呼叫實現資源配額的劃分和應用生命週期的管理。

容器雲平臺在易用性方面最大的挑戰是Troubleshooting的環節,容器雲最終是要交付開發人員使用,他們對Kubernetes並不瞭解,這讓Troubleshooting的環節充滿挑戰,我們現在只是想通過websocket將kubectl exec的console展示給使用者,或者讓使用者在日誌中心(EFK)中檢視日誌,還沒有更好的方案,如果各位有更好的方案,請不吝賜教。

容器雲未來要實現整個資料中心的視覺化,讓運維對所有的資料中心的實時執行情況一目瞭然,當然,實現這一目標有相當的難度。

容器雲的監控採用Heapster的方案,正在向Prometheus方式轉變。

日誌收集是主流的EFK的組合方式。

容器雲管理系統的基本功能如下圖所示:

20170519135350

日誌收集方案如下圖所示:

20170519135403

我們為Java應用提供了一個公共日誌元件——Appenders,它會將Java的日誌流式輸出到Fluentd中轉,輸出到Fluentd中轉的原因是與現有的日誌中心並行執行。其他的部分跟主流的EFK模式沒有任何區別。使用DaemonSet執行Fluentd和Fluentd與應用以Sidecar的方式進行日誌採集也是比較好的選擇。

在容器時代,CloudNative應用是必然的選擇,構建雲原生應用的原則請參考12因子。

容器雲管理系統自身也是CloudNative應用,它同樣執行在Kubernetes中,與傳統的上線工具不同的是,它能夠進行自我生命週期管理。

Container based、Mircoservices Oriented是Cloud Native倡導,只有應用向Cloud Native轉化,才能更好的發揮容器雲的效力。

CI/CD建設

20170519135410

按照我們預先的Roadmap,先解放生產環境的運維工作,再解決應用的構建、整合的問題。現在,容器雲的管理系統基本上替代了日常維護的手工操作,頻繁的手工觸發構建成了容器雲推進的瓶頸,所以,構建CI/CD平臺變得非常緊迫。

經過前期調研,我們決定使用Gitlab + Jenkins + Docker Registry的技術棧構建CI/CD平臺。為了統一技術標準和儘量減少構建過程中的不確定性,我們採用自動生成Dockerfile的方式,而不是讓開發自己編寫Dockerfile。我們採用穩定主幹的方式,MR自動觸發構建過程,經過單元測試,打包,編譯和Docker構建,容器雲的介面會實時顯示構建的過程,在構建結束後,使用者會收到構建的結果的郵件。最終,CI產出的Docker映象會被推送至QA環境的Registry上。

對我們來說,CI/CD最重要和最難的環節是自動化測試,尤其是自動化整合測試,我們正在努力解決。

CI的過程我們還做了程式碼的依賴庫檢查,程式碼版本追蹤和Docker映象自描述等,讓Docker映象從產生開始,在測試,生產測試,生產等每個環節都是可追溯的。這樣便於我們查詢問題和對CI的過程進行持續的改進。

對常用技術棧和配置進行標準化也是CI建設的一個重要目標。保證CI產出的映象的質量(類似次品率)是對CI系統考核的重要標準。

下圖是我們CI/CD平臺的工作流示意圖:

20170519135418

下圖展示了整個部署流水線,映象從構建到生產部署的全過程,以及過程、結果的反饋:

20170519135424

遇到的問題和挑戰

到目前為止,回顧整個容器雲的構建過程,來自技術上的挑戰並不多,但是也踩了一些坑。

遇到過RBD盤被鎖住,新產生的Pod無法掛載的情形,解決辦法是將RBD盤手工解鎖,新的Pod會自動掛載。

Kubernetes的一個Bug,Kubernetes的ReplicaSets名稱是根據Deployment的PodTemplate的摘要產生,使用的Adler演算法,Hash碰撞非常頻繁,會在升級過程中,Deployment不能建立最新的ReplicaSets而造成升級失敗。解決辦法是講adler演算法換成FNV演算法,來減少Hash碰撞的頻率,這顯然不是最終的解決方案,最終的方案還在持續討論中,有興趣的朋友可以參與:https://github.com/kubernetes/community/pull/384,https://github.com/kubernetes/ … 29735

由於一直沒來得及遷移Harbor,我們一直直接使用Docker registry 2.1版本作為私有映象倉庫,使用Restful API時,_catalog預設返回字母序的前100個映象,客戶端需要處理分頁的問題。

應用向容器雲遷移是容器雲建設過程中花費最多精力的地方,由於需要適應容器雲背後的理念轉變和對現有應用改造進行改造,遷移過程中受到了很多挑戰,最大的挑戰是Dubbo應用的遷移問題,由於Flannel的Overlay網路使容器化的Dubbo應用不能與Overlay網路之外的應用連通,最後我們修改了網路策略,使得Dubbo的應用可以無縫的遷移到容器雲中。

下一階段容器雲工作的重點,是推動應用向Cloud Native和微服務化方向改造。

容器雲面臨的最大挑戰來自於理念轉變,容器技術改變了軟體交付的生態,容器時代需要技術人員以新的理念構建應用,如何讓技術人員順利的完成理念的轉變是每個容器雲的建設者們需要認真考慮的問題。

以上內容根據2017年4月25日晚DocKOne微信群分享內容整理。分享人李大偉,易寶支付有限公司,架構師,主要負責易寶容器雲的建設與落地,DevOps平臺建設和理念推廣。北京大學碩士,7年工作經驗,有堅實的理論基礎和多年的底層開發經驗。開源愛好者,現專注於容器技術與DevOps實踐,對Docker、 Kubernetes、DevOps、微服務等有濃厚興趣。** DockOne每週都會組織定向的技術分享,歡迎感興趣的同學加微信:liyingjiesz,進群參與,您有想聽的話題或者想分享的話題都可以給我們留言。