1. 程式人生 > >網易雲基於Kubernetes的深度定製化實踐_Kubernetes中文社群

網易雲基於Kubernetes的深度定製化實踐_Kubernetes中文社群

本文主要整理了網易雲容器編排技術負責人婁超的演講“網易雲基於Kubernetes的深度定製化實踐”,其他講師的演講內容還在整理中,敬請期待!

婁超,網易雲容器編排技術負責人。曾經參與淘寶分散式檔案系統TFS和阿里雲快取服務研發,2015年加入網易參與網易雲容器服務研發,經歷網易雲基礎服務(蜂巢)v1.0,v2.0的容器編排相關的設計和研發工作,並推動網易雲內部Kubernetes版本不斷升級。

網易雲的容器服務基於網易雲的IaaS。為了簡化使用者的操作,Kubernetes並不是直接暴露給使用者的,而是通過上層的業務層為使用者提供容器服務,增加獨立的Netease-Controller, 對接網易IaaS及公共平臺,資源管理和複雜的業務需求。

Kubernetes公有云實踐

Kubernetes的社群版本主要面向私有云市場,沒有租戶的概念,只有namespace的邏輯隔離,Node/pv等資源都是叢集全域性共享的,服務發現和負載均衡也都是全域性的,Node須在叢集內預備足夠,不用擔心資源排程出現失敗,也無需關心Docker隔離安全性問題。而對於公有云來說,雲中有著海量使用者,使用者的技術背景多樣,需要很高的安全隔離性。網易雲在基於Kubernetes實現公有云的過程中,做了很多工作。

1. 首先,在多租戶的安全隔離方面,有專門的IaaS團隊提供主機、硬碟和網路的隔離;
2. 對於每個租戶來說,都可以自定義建立namespace;
3. 原生的Kubernetes認證很簡單,而且Node是全域性共享的,每個Node上都可訪問Kubernetes的所有資源,所以為了實現公有云,網易雲做了租戶級別的安全隔離,包括認證、授權和API分類統計和流控報警;
4. 在網易雲中計算、儲存、網路資源均按需實時分配、回收,保證資源的利用率儘可能高;因為資源是實時分配的,所以建立起來一般比較慢,所以網易雲對建立流程做了一些全域性的優化,比如加快Node註冊的程序,根據映象選擇主機等;
5. 原生的Kubernetes中沒有網路IP的概念,網易雲增加了Network資源型別表示網路IP。

網易雲容器pod網路

容器的網路主要有以下幾種方案:

入門級:Docker 基礎網路模型 host(共享),bridge(NAT)。

進階級:自建網橋(IP-per-Pod),可跨主機通訊,如Flannel, Weave。

專業級: 多租戶,ACL,高效能可擴充套件 ,如Calico,GCE高階網路模式。

網易雲容器網路實現

網易雲的容器服務的網路實現與GCE類似,基於底層的IaaS網路,通過Kubernetes與網易雲網絡對接,網易雲容器與主機在網路上完全對等,租戶內全互通。

Kubernetes中沒有定義IP的管理,可能一個容器或節點重啟一下,IP就變了。網易雲通過IP的管理實現了IP的保持功能,同時Pod支援私有網、公網雙重網路。

此外,網易雲還實現了Pod的私有網、公網IP對映關係管理,在Kubelet上實現Netease CNI外掛管理網絡卡掛解除安裝、路由配置。

網易雲有狀態容器

提到容器的狀態,人們常用Cattle和Pet來做比喻。Cattle是指無狀態的容器,隨時可以被替換,Pet則是有標記的,它的資料、狀態和配置可能都需要持久化。社群從1.3版本就開始用PetSet實現有狀態的容器,最新的1.6版本中,是叫StatefulSet。

網易雲在社群版本的有狀態容器誕生之前(1.0版本),就自研了StatefulPod的實現方式:

  • 和StatefulSet不同的是,它可以支援容器系統卷、資料卷的保持(PV、PVC)。StatefulSet只能支援外掛的資料卷,但是網易雲的StatefulPod能夠保證只要不刪除使用者,使用者系統盤的資料也能夠保持下來;
  • StatefulPod還能保證容器私有網、公網IP保持(Network);
  • 在原生的Docker中,一個Node啟動的所有容器目錄都是統一的,網易雲擴充套件Docker支援容器rootfs目錄自定義;
  • 網易雲的有狀態容器還支援故障的遷移,比如硬碟和IP等資源都能在Node間漂移。

網易雲Kubernetes效能優化

一般在實現公有云時,儘量會保證同一個機房內,只有一個Kubernetes叢集,但隨著使用者的增多,叢集的規模也越來越大,會出現很多效能問題。網易雲隨著社群的發展一路走來,也遇到了社群在設計之初可能沒有預料到的一些問題,比如:

1. Kube-scheduler對所有Pod順序序列排程;
2. Kube-controller的deltaQueue是無優先順序的FIFO佇列;
3. Serviceaccounts控制器裡沒有Secret本地快取;
4. 所有Node重複配置叢集所有Service的iptables規則;
5. Kubelet的SyncLoop每次檢查都重複GET imagePullSecrets;
6. 大量Node的心跳彙報嚴重影響了Node的監聽;
7. Kube-apiserver 沒有查詢索引。

master端的排程器

針對這些問題,網易雲做了很多效能優化,首先是master端的排程器:

  • 公有云的場景和私有云不一樣,容器分佈在不同的租戶中,每個租戶的資源都是獨立的,本身就可以通過租戶來溝通並排程;
  • 通常在排程的時候需要一個個去遍歷Node,實際上很多無閒置資源的Node可以不參與排程的檢查,網易雲會在遍歷前過濾掉無閒置資源的Node;
  • 優化predicate排程演算法過濾順序,提高排程效率;
  • 網易雲中,排程都是基於事件的,比如排程失敗如果是因為Node資源不足,就會發一個事件去申請資源,資源回來後會又會返回一個事件驅動Pod重排程,沒有任何時間等待。

上圖就是在網易雲中並行排程的過程。

mater端控制器的優化

Kubernetes中有很多控制器,比如Node控制器、Namespace控制器,其中Replication Controller是一個核心的控制器,能確保任何時候Kubernetes叢集中有指定數量的Pod副本在執行。網易雲建立了事件優先順序機制,根據事件型別進入優先順序佇列workqueue。

Node端的優化

網易雲的使用者很多,使用者之間都是完全隔離的,網易雲kube-proxy按租戶對Node分組:

  • 租戶之間容器網路完全隔離,不配多餘轉發規則;
  • 只監聽本租戶的Service,再生成iptable 規則。

Kubelet降低master請求負載:

  • imagePullSecret推遲都要拉映象才GET或增加Secret local cache;
  • 只監聽本租戶相關資源變化(依賴apiserver新加的tenant索引);
  • 精簡kubelet watch 低master連線數,包括Node。

單叢集擴充套件的優化

根據官方的資料,Kubernetes 1.0最多支援100個Node,3000個Pod;在1.3版本中這個數字上升到2000個Node,6萬個Pod,今年最新發布的1.6版本已經支援5K個Node,15W個Pod。

通過上圖可以知道APIserver是整個叢集的通訊閘道器,只是一個proxy代理,而且goroutine對web服務完美支援,最終效能瓶頸在對 etcd的訪問上。

為了解決這個問題,首先想到的是分庫,按Node/RS/Pod/Event分庫存入多個etcd叢集。因為Etcd本身容量和效能均不能水平擴充套件,而且沒有效能診斷工具:

  • Etcd2 調優,比如針對snapshot的優化,採用SSD硬碟等;
  • 升級Etcd3,在之前的版本中,每次更改都會發送一個請求,一個請求又對應一個回覆,在Etcd3中是批量請求的方式,可能一次請求就把1000個變化推送過來了,所以效率提高很多;
  • 更換Kubernetes後端的儲存,換其他效能更優的KV儲存。

Node心跳彙報模式修改:

  • Node心跳間隔延長;
  • Node心跳不持久化;
  • 心跳從Node分離出來,Node心跳只需list不必watch;
  • NodeController被動改主動探測。

其它優化

映象、容器的GC完善:目前的GC只考慮了磁碟的空間使用量,沒考慮inode的問題,很多使用者的小檔案很多,所以網易雲新增了磁碟inode使用率檢查。

容器監控統計:Cadvisor新增網路流量、TCP連線、磁碟相關統計。

NodeController安全模式,自定義Protected,Normal,Advanced 3種模式:

  • Protected: 底層IaaS主動臨時運維時,為了避免大規模遷移波動, Node離線只報警不遷移;
  • Normal:有狀態的不遷移,無狀態的及時離線刪除重建。(僅僅底層雲盤、網路故障);
  • Advanced:有狀態無狀態都自動遷移恢復。

還需要注意的一些問題:

  • Pod的graceful delete要容器能正常傳遞SIGTERM訊號;
  • StatefulSet在kubelet掛掉時可能出現兩個同時執行的Pod。