歡迎光臨
每天分享高質量文章

滴滴彈性雲Kubernetes實踐

當前Kubetnetes已經成為容器編排領域事實的行業標準,越來越多的公司選擇使用Kubernetes來搭建其容器雲平臺。本次分享主要介紹滴滴彈性雲在圍繞Kubernetes打造企業級私有雲過程中的一些實踐經驗和教訓,為同樣正走在企業雲化轉型道路上的朋友們提供一些啟發和幫助。
當前滴滴國際化業務全部運行在彈性雲平臺上,國內的順風車,金融,汽車後市場、企業安全、客服以及專車快車等業務的全部或部分模塊也運行在我們的平臺上。平臺規模大約1K+宿主,2W+容器實體。 
今天的分享我主要聚焦一些我們平臺相對有特色的地方,希望能給各位帶來一些啟發。

 

網絡模型

首先介紹一下平臺的網絡模型,我們最開始使用的是Flannel,這種網絡模型的問題大家應該都有體會,這裡不多說。 
之後我們過度到了使用ONOS為主體集中式SDN網絡,這種網絡模型的功能可以說非常豐富,容器可以在overlay網絡上隨意漂移,且在容器名不變的情況下保證IP不變。於此同時容器IP相互獨立,和物理網絡雙向互通,所以設置各類白名單也和物理機完全一致,不占用物理網絡IP資源。利用Kubernetes的CNI可以很方便的為容器配置網絡,用戶使用起來和物理機無異。
但是此種樣式的最大問題是:集中式的網絡控制器在出現故障或是任何一點性能問題時,都會對集群的穩定性造成顯著的影響。在經歷了一些穩定性問題後,我們將網絡模型演進到了當前的使用物理網絡的樣式。在此種場景下,容器只能在同一個接入交換機下的宿主上進行漂移,所以我們在部署新集群的時候每個交換機下的宿主數量儘量趨同。 
同時我們預先為每個APP提供一個IP池,用戶在創建容器之前可以先申請一個IP池(預設30個IP,未來創建的容器的IP不會超出這個IP池的範圍),使用平臺提供的白名單功能,預先將IP池內的IP自動化的加入到MySQL或Codis這樣的公共服務白名單中,最後再啟動容器。這樣就實現了容器啟動後不會因為連不上資料庫而報錯,或者擴容後新容器異常。當然,IP池是能夠隨著業務的變化而隨時擴縮容的。調度系統在預分配IP池的時候也會根據各個tor IP的實際使用量均勻分配。 
值得一提的是我們利用Kubernetes提供的nodeAffinity和podAntiAffinity實現同一服務、同一產品線、同一服務等級等多種維度下的容器實體平均分配到不同的接入交換機和宿主下的目的。

 

服務發現

接下來給大家介紹一下彈性雲在服務發現方面做的一些改進。首先我們在很早的時候就拋棄了kube-proxy。在我們運維雲平臺的過程中我們發現當一個集群有幾百、幾千個service之後其iptables的規模要再乘以10(通常是service背後Endpoint的數量),如此多的iptables條目讓我們比較難以維護和故障定位。
所以除了老集群,我們的新集群全部使用公司自研的服務發現:DSI & DGW。DSI就是基於NGINX做的公司內7層代理服務,其核心是借助服務樹獲取到節點對應的容器或物理機信息,將他們動態的、自動的掛載到NGINX的upstream中,實現高可用及負載均衡。容器變化時DSI可以通過watch服務樹接口實時感知,實時調整,用戶無需操心。
DGW則是四層的負載均衡,他同樣實現了容器作為RealServer動態實時變更的功能。

 

業務上雲穩定性

下麵再說一下針對業務上雲穩定性做的一些改進,我們認為雲上穩定性主要分為大概三個方面:
  • 容器相對於此前物理機樣式下發佈更新、線上擴容等流程異構導致的穩定性問題;

  • 容器自身特性導致的穩定性隱患;

  • Kubernetes本身特性帶來的穩定性隱患。

首先對於業務發佈流程,我們首先要做到的是儘量避免因發佈導致的流量丟失或服務不可用問題,為此我們首先預設不使用Liveness探針(用戶需要可以自己配),僅保留一個Readiness探針保證容器服務在創建時能正常啟動。在Readiness探針探測通過後,我們會根據service的Endpoint將容器變化推送到周邊系統,如之前提到的DSI、DGW等,後續的探活就由這些前端設備完成。 
此外我們為每個服務強制的分為n個分組(通常是4個),每次上線過程中用戶都必須逐一分組更新服務,組與組之間強制時間隔離用於檢查,前一組不發佈更新完成後一組無法操作。使用這種方式一是規避了Kubernetes來做服務探活的“不確定性”,二是同物理機發佈更新樣式趨同,用戶認同度更高,從流程上規避可能的故障風險。 
其次,針對容器自身特性的穩定性隱患可以歸納為容器隔離性不強的隱患。大家都知道直到1.10版本的Kubernetes才正式引入了cgroup的cpu_set功能,此前只有cpu_share,記憶體只能限制大小,磁盤和網絡限制更是沒有。當一臺宿主上運行了多個在線業務容器時,經常遇到某容器性能下降的case,而同服務的其他容器無異常。檢查發現,這通常是因為問題容器所在宿主上的其他容器負載突增或容器異常導致的消耗宿主資源過多,進而影響同宿主其他容器。為此我們在混部資源隔離方面做了一些拓展:首先對每個容器進行服務定級,根據容器的cpu request值為容器綁CPU核(cpu_set),利用cgroup v2的blk-throttle實現對非driect io場景下的磁盤讀寫速度隔離,利用Intel的CAT功能實現對系統三級快取的資源優化分配,利用MBA和MBM技術實現對記憶體帶寬的使用限制,利用tc實現對容器網絡帶寬的限制,利用xfs_quota實現對容器hostpath掛載目錄的容量限制。我們的標的是:動態的變更以上容器所分配的資源配比,而更改的依據則是容器內業務指標的變化而變化。這塊我們還在努力探索中,也歡迎有其他感興趣的朋友和我們交流。

 

安全加固

針對Kubernetes本身的安全加固主要體現在:
  1. 限制容器的重建次數:我們在運維過程中發現:某些配置了探針的容器因為服務沒有成功啟動而不斷的被Kubernetes殺掉重建,在重建超過幾百或數千次之後會偶發性的導致宿主的一些異常。這個問題的原因我們尚未查明,但是容器不斷的重建本身就顯得沒有意義,再加上我們使用了自研的服務發現,所以就對每個容器的重啟次數做了限制,讓負載均衡層去做健康檢查;

  2. 調高controller驅逐Pod的容忍時間,宿主偶發的notready可能導致容器觸發evict動作,對於有狀態容器來說漂移並不是完全無損的,所以調高驅逐時間是完全有必要的;

  3. 添加判斷宿主狀態旁路系統,對宿主狀態變化做二次確認。宿主notready帶來的最大影響就是容器的強制漂移,而生殺大權完全依靠kubelet向kube-apiserver上報狀態資料。很多複雜的因素都有可能導致這條通路的不穩定進而影響狀態更新,造成健康宿主被誤診成故障進而觸發漂移最終雪崩的結果。為此我們對kube-controller-manager做了改造,controller在決定要對宿主狀態做修改後還需要通過一個旁路流程確認宿主狀態,兩邊一致之後再做修改。

Q&A;

Q:利用cgroup v2的blk-throttle實現對非driect io場景下的磁盤讀寫速度隔離,這個怎麼做的,Kubernetes支持嗎?
A:如果是3的內核,那麼只支持cgroup v1,v1只支持對driect io的磁盤讀寫限制,而我們知道大多數情況下的寫磁盤都是先寫到記憶體里再FLUSH到磁盤上,所以要限制的是從記憶體到磁盤的這個環節。4的內核支持cgroup v2,這個功能已經比較成熟,你可以嘗試升級內核或者將v2的功能移植到v1上。
Q:是要修改dockerd的配置,還是在Kubernetes上擴展?
A:如果是接著上面的問題的話,我們是使用了一個Agent的方式,單獨的做加強的資源隔離的,沒有在Kubernetes上做擴展。
Q:DGW是基於什麼實現的?
A:DGW其實就是LVS,我們這邊的系統組實現了通過接口的方式動態的變更LVS配置的能力。
Q:容器網絡和物理網絡型別一樣,具體是什麼網絡?原有的ONOS SDN網絡還有用嗎?不同namespace之間隔離怎麼做?
A:老的集群使用SDN網絡,新集群使用物理網絡。所謂物理網絡就是和物理機同一個網絡,只不過每個tor下劃分出一段專門給容器分配使用。
Q:請問下“利用tc實現對容器網絡帶寬的限制”,具體怎麼做的?
A:參考物理機使用tc對容器做網絡流量限制,如果你用了SDN網絡DPDK/OVS什麼的,限速就更方便了。
Q:滴滴的捲管理是怎麼設計的?有狀態服務怎麼設計調度,來保證資料持久化的?
A:目前我們這邊有狀態服務非常多,無狀態非常少,用戶的使用習慣還是和物理機趨同,對於這部分“老派”的用戶我們提供了類似虛擬機這樣的容器。使用本地捲(hostpath),容器只能本地重建不可跨宿主漂移。這也是對業務的一種妥協。另外我們也使用過ceph,但是最後評估風險更大,故暫時放棄使用,或小範圍使用。
Q:通過負載均衡的健康檢查測試服務可用性,健康檢查的周期內,如何保證流量不丟失?
A:我們這邊LVS預設有7秒的探活間隔,在7秒的間隔內如果容器故障不可用那麼確實會有流量的丟失,目前不可避免。
Q:容器的優雅下線怎麼實現的?
A:我們之前的容器啟動都是用Supervisor托管的,後來我們自己寫了一個dockerinit,用於用戶業務服務的啟停,他的功能比較強大能執行單獨的一次性程式(類似物理機的rc.local),也能托管行程。於此同時他會保證容器所有的業務行程退出後再銷毀容器,避免粗暴的停止容器。
Q:有沒有使用cpu_quota來做精細的限制呢?CPU request系結CPU,超分的情況怎麼處理呢?
A:你想問的其實是超售的問題,參考業內一些走在前面的大廠,我們的容器會根據容器的服務等級做適當的超售,這樣一個48核的宿主就能承載更多的容器。這裡面的細節比較多,這裡不太好描述。

基於Kubernetes的DevOps實踐培訓

基於Kubernetes的DevOps實踐培訓將於2018年8月24日在北京開課,3天時間帶你系統掌握Kubernetes本次培訓包括:容器特性、鏡像、網絡;Kubernetes架構、核心組件、基本功能;Kubernetes設計理念、架構設計、基本功能、常用物件、設計原則;Kubernetes的資料庫、運行時、網絡、插件已經落地經驗;微服務架構、組件、監控方案等,點擊下方圖片查看詳情。
赞(0)

分享創造快樂