kubernetes在騰訊遊戲的應用實踐

IT大咖說發表於2017-07-25

kubernetes在騰訊遊戲的應用實踐

內容來源:2017年2月14日,來自騰訊互娛高階工程師黃惠波帶來了精彩的乾貨分享,本文轉自數人云公眾號(dmesos)。

kubernetes在騰訊遊戲的應用實踐

摘要

騰訊遊戲是國內最大的網路遊戲社群,致力為遊戲玩家提供完整的快樂解決方案。騰訊互娛高階工程師黃惠波通過一些實際場景為大家解析kubernetes在騰訊遊戲中的應用實踐。

大咖乾貨地址:t.cn/RS1nMFy

騰訊線上遊戲的容器化應用場景

2014年,我們開啟了容器化探索之路,先回顧一下之前遇到的一些問題。

在物理機時代,資源的交付時間較長,資源的利用率較低,也不能做到隔離。到了xen\kvm虛擬機器時代,問題得到了初步的解決,但在彈性伸縮方面仍有不足。隨著Docker技術的興起,我們開始調研Docker在遊戲容器化方面的應用。我們的目標有兩個,一是提高資源利用率,二是通過Docker映象來標準化部署流程。

選擇Docker技術之後,我們開始了容器排程平臺的選型。我們當時也調研了其它的一些元件,比如Shipyard、Fig等,但這些元件無法支撐海量遊戲容器排程。而自建排程平臺的話,時間成本非常的高。就在那時,Google開源了kubernetes(當時的版本是kubernetes v0.4),我們基於這個版本進行了定製和開發,使其成為我們遊戲容器的排程管理平臺。

kubernetes在騰訊遊戲的應用實踐

在2015年初的時候,TDocker平臺上線。之後,我們開始逐步接入業務。一開始的模式非常簡單,就是把Docker當成虛擬機器來使用,但這不意味著遊戲全容器化的實現。

大家知道,對於一項新技術來說,大家都很謹慎,會通過不斷的灰度上線,由點到面的策略推動。截至目前,在全國各地以及加拿大等地區,都有我們的部署點;接入容器數超過兩萬,接入的業務也有兩百多款,包括手遊、端遊、頁遊。在這麼多的業務中,主要分為兩種場景,第一種場景是輕量級虛擬機器模式,這類容器承載多個服務程式,需要一個具體的內網IP,可以通稿SSH登入。另一種是微服務化模式,這種模式會拆分得非常細,每一個容器對應一個服務程式,不需要對外可見的內網IP,可以使用虛擬IP。

接下來會對每一個場景做一些分享。首先來看一下傳統遊戲下的架構。這是非常典型的三層服務架構,包括了接入層、邏輯層、資料庫層。同時,遊戲又分為:全區全服、分割槽分服兩種型別。對於分割槽分服類遊戲,滾服對資源的排程非常頻繁,所以我們需要一個高效的排程平臺。

kubernetes在騰訊遊戲的應用實踐

容器資源的排程管理基於kubernetes v0.4版本,上圖是一個簡化後的排程框架。在Master端包括ApiServer和Scheduler,接收Web請求,然後做資源排程。在每個node節點上,包括agent程式、Docker程式,還有Lxcfs程式。在映象儲存方面,當時用的是Registry V1版,後端用的是ceph儲存。現在,我們自己維護了一個分支,功能上已滿足當前的遊戲需求,並保證執行的穩定。所以在虛擬機器模式下,我們不會升級kubernetes,而是把一些好用的功能合併進來。

基於Kubernetes的功能定製與優化

首先講排程器,排程器為數以萬計的容器提供了一個靈活、穩定、可靠的底層資源計算排程引擎。資源的合理分配像是一場博弈,裡面有很多矛盾的地方,需要我們根據遊戲的特點做取捨。

kubernetes在騰訊遊戲的應用實踐

我們在原有的排程策略上根據遊戲特點做了一些定製。比如在網路方面,傳統遊戲的每個容器都需要一個對外可見的實體IP,使用者可以通過SSH登入到容器裡面,因此對網路資源進行排程。部署容器的時候,會申請network的資源(比如IP)然後進行劃分,繫結到minions物件。這樣排程器排程的時候,就可以通過這些配置資訊給容器分配好網路資源。

kubernetes在騰訊遊戲的應用實踐

在社群中,CPU的分配用的是共享CPU的方式,遊戲採用的是一種混部的模式。也就是說,將不同遊戲業務部署到同一臺母機,採用繫結核的方式。這樣做一方面可以防止不同遊戲之間的CPU搶佔,另一方面對遊戲成本的核算也會更加精細。例如,某個遊戲用了多少CPU這些指標都是可以量化的。在容器分配CPU時,結全numa技術,對於CPU CORE的分配會盡量地分配到同一個numa node上,這樣可以提升效能,因為同個numa node的CPU訪問只需通過自身的local memory,無需通過系統匯流排。

kubernetes在騰訊遊戲的應用實踐

在磁碟容量分配方面,由於遊戲業務是有狀態的服務,需要儲存,所以我們把磁碟也作為一個可排程的資源分配給容器。還有非親和性的排程。我們知道,在容器的可靠性與碎片優化之間需要一個權衡,讓使用者根據這些策略去選擇、部署自己的容器。例如在非親和性的策略中,使用者希望把容器是分散到各個母機上的,在母機當機時,可以減少對遊戲的影響。

kubernetes在騰訊遊戲的應用實踐

在IDC Module分配方面,遊戲容器的部署會按地區劃分,比如按照上海、深圳或天津地區的IDC來劃分,所以我們提供了IDC部署策略。由於遊戲需要考慮IDC的穿越流量問題,還有網路延時的問題,所以同一個遊戲的的不同模組一般會部署到同一個IDC Module下面。

海量應用過程中遇到的問題與解決方案

kubernetes在騰訊遊戲的應用實踐

以上是基於遊戲行業特點定製的排程規劃。在資源排程過程中,也遇到過一些問題,例如容器資源的重複排程。首先在排程過程中它會跟ScheduledPod(已完全排程的容器)進行比較,判斷現在是不是有足夠的資源分配給待排程容器,最後通過Bind(非同步)把Pod資訊寫入到ETCD。這裡就會出現一個問題,那就是非同步寫入慢了或者ScheduledPod同步慢了導致ScheduledPods不能及時重新整理,Scheduler計算出錯,從而造成資源重複計算。針對這個問題,我們的解決方案是在資源排程完成後,做一個檢測的邏輯,檢測排程的容器資訊是否已在ScheduledPod Cache這裡,然後再進入下一個容器的排程。當然這會帶來一定的效能損耗。

解決了這個問題,又產生了另外一些問題,那就是效能的問題。在0.4版本的pod介面是非常低效的,在查每一個pod狀態的時候,會通過實時查所有的Host來確定,設計不太合理。社群也做了一些方案,當時我們也是參考了社群的一些方案做了一些改造,把pod狀態放在Cache裡面,定時更新,從而提高查詢效率。

kubernetes在騰訊遊戲的應用實踐

還有一點就是RESTClient。在kubernetes中,rest API大部分是非同步進行,對於這些非同步的介面的請求,並不會立刻返回結果。這裡有一個輪詢檢測狀態的邏輯,在檢測輪詢的時候有幾秒的休眠,然後進再行下一個輪詢。預設的休眠時間是2秒,這個時間對大部分場景來說有點過長,我們通過一些功能點的調整,從物理機的小時級到虛擬機器分鐘級的排程,再到還未調整之前的秒級排程,到現在達到的毫秒級排程,現在的排程能力已能滿足遊戲的需求。

講完排程,再看一下網路方面。網路是非常關鍵、也是最為複雜的一環。在虛擬機器模式下,結合公司網路環境為遊戲提供高效能、穩定的網路環境,包括Bridge+VLAN\SR-IOV兩種方案。

kubernetes在騰訊遊戲的應用實踐

先來說,Docker的網路還有kubernetes的網路。對於Docker的NAT網路來說,效能是最大的瓶頸,同時它與物理機或虛擬機器的通訊路徑不一致也會對業務帶來一些未知的影響。比如,外界不能看到容器真實的IP(必須要使用主機IP+port方式,埠本身就是稀缺資源,並且ip+port的方式,無疑增加了複雜度),TGW仍然可以為業務程式服務。Host模式沒有隔離,也不符合需求。在kubernetes中,pod作為最小排程單元,每個pod有兩個容器,一個就是網路容器,接管pod的網路,提供網路服務,並與其它容器共享net\IPC。另一個是App Container,也就是業務容器,使用第一個網路容器的網路。在這種模式下,容器之間的通訊是非常簡單的。對於pod到pod、pod到物理機、物理機到pod的通訊,我們為每個pod分配一個內網IP,對外可見,也可以互相通訊。

kubernetes在騰訊遊戲的應用實踐

接下來,通過兩個方案給大家分析。首先是Bridge+Vlan的方案,母機都是部署在虛擬化區上,通過Vlan做網路的隔離。在母機上架部署時,建立Bridge裝置和VLAN裝置並將它們進行關聯。建立容器的時候,使用pipework指令碼建立容器所需要的虛擬網路卡裝置,並把它們繫結到容器和Bridge上,同時會設定容器內的IP、MAC地址以及路由等資訊。從而打通容器到外界的網路通訊。這裡也做了一些優化以提高效能,這裡可以看到一個效能的對比,其中Bridge相對NAT網路有相當大的提升。這種方式可以滿足一部分遊戲的需求,而有一些業務,像FPS、Moba遊戲等大流量,對網路要求非常高的業務,還有類似MySQL-Proxy這種元件,在Bridge場景下是無法滿足需求的。

所以我們探索了另一種網路方式,就是SR-IOV模式,這種模式在zen\kvm虛擬化上用的比較多,遊戲也需要這種網路方案,因此我們把這種網路方案也結合到Docker容器裡面。

kubernetes在騰訊遊戲的應用實踐

這裡需要硬體的支援,結合SR-IOV技術的網路卡,在Docker容器內就可以直接通過驅動來載入虛擬的網路卡並使用。使用的方式就如同在一臺物理機上使用一個真實的物理網路卡一樣,這個虛擬網路卡也擁有驅動程式,也擁有PCI BUSID,因此所有的虛擬機器網路操作都如同操作普通網路卡一般,從而在效能上得到提升。為了進一步發揮SR-IOV的網路效能,還需要對容器的相關網路引數進行配置,主要包括以下幾個方面:VF中斷CPU繫結;關閉物理機的irqbalance;容器內設定RPS(軟中斷均衡)網路卡不能中斷均衡,對高效能的網路形成了阻礙。為了解決這個問題,需要設定容器內的軟中斷均衡。通過上述的調整,效能得到了大幅度提升。

這是我們測試的一個結果,這邊是物理機的,這是Bridge,這是SR-IOV,SR-IOV在網路效能方面基本上已經接近了物理機,所以這個對於遊戲大包量、大流量的應用是非常適合的,現在我們把SR-IOV網路作為傳統遊戲裡預設的網路模式。

在遊戲容器化過程中,我們希望資源的使用是明確的、合理的、可量化的。所以我們會為每個容器分配固定的資源,比如多少CPU、多少記憶體,還有需要多大磁碟、IO頻寬。在啟動容器的時候,比如CPU/Memory,通過Cgroup去做一個限制,disk通過xfs quota去做配額的限制。還有Buffered-IO頻寬的限制。

kubernetes在騰訊遊戲的應用實踐

在資源分配方面,我們開始做的是限定的CPU、記憶體的分配。在容器的整個生命週期,這個配置並非一沉不變,比如在業務執行過程中都會有一些起伏和動態調整,這是遊戲的一張生命週期影象,生命週期比較短,可能是一年半載的時間,而且這裡線上人數起伏也會比較大,需要動態調整。而動態調整就會涉及兩個方面,一是橫向的水平擴充套件,二是垂直伸縮。

每個遊戲都會有一個IP,因此橫向擴充比較困難,因而更傾向於穩定的垂直擴縮。在虛擬化時代,擴縮容是有損的,需要重啟機器來實現,而Docker可以做到無損的擴縮容。我們對這個需求做了一些定製開發,比如CPU或者記憶體,通過修改Cgroup的配額去把它提升上去或是削減下來。

當線上人數上來的時候,我們可以給業務做到無損擴容,不影響業務服務。過了一段時間,當人數降下來時,資源會閒置,我們會對空閒的資源做一些重複利用,將其回收。這個時候做一些縮容,針對縮容我們做一個常態的動作,檢測這些容器的CPU、記憶體,結合業務的負載、活動、定時驅動。

kubernetes在騰訊遊戲的應用實踐

Buffered IO Throttle需要核心支援,我們與核心團隊進地了緊密的合作,提供了支援 Buffered IO Throttle功能的核心版本。根據容器在母機資源的佔比分配一定比例的IO頻寬。這在某種程式上解決了遊戲之間互相影響的問題。

kubernetes在騰訊遊戲的應用實踐

監控、告警是整個遊戲運營過程中最為核心的功能之一。容器上的監控有別於物理機,cAdvisor和kubenetes結合得比較緊密,是個不錯的方案。但它也會帶來問題,那就是需要自建監控平臺,而且它與周邊各系統的相容性也有待考驗,同時改變運維的使用習慣也需要時間。綜合考慮各種因素後,我們放棄了cAdvisor,重新調研其它方案,希望可以沿用公司成熟的監控平臺,而且相容周邊系統。最終我們選用的是lxcfs + 公司agent的方案,通過lxcfs去實現Docker容器內的虛擬proc檔案系統,增強容器的隔離性。

我們這裡以meminfo記憶體統計資訊為例,為大家講解如何通過lxcfs使用者態檔案系統實現Docker容器內的虛擬proc檔案系。掛載虛擬proc檔案系統到Docker容器,通過Docker的volume功能,將母機上的/var/lib/dockerfs/docker-xxx/proc掛載到Docker容器內部的虛擬proc檔案系統目錄下/proc/。此時在容器內部/proc/目錄下可以看到一些列proc檔案,其中包括meminfo。使用者在容器內讀取/proc/meminfo時,實際上是讀取宿主機上的/var/lib/dockerfs/docker-xxx/proc/meminfo掛載到容器內部的meminfo檔案。核心VFS將使用者請求轉發到具體檔案系統——fuse,fuse檔案系統封裝VFS請求,將請求轉發給Fuse裝置(/dev/fuse)。如果裝置上有已經處理完成的請求(例如Cache),檔案系統獲取處理結果並返回給VFS,VFS再反饋給使用者。使用者庫(fuse daemon)直接訪問Fuse裝置,讀取檔案系統轉發到裝置上的請求,分析請求型別,呼叫使用者介面處理請求,處理完成後將處理結果返回給裝置,再由裝置返回給VFS,VFS再反饋給使用者,從而實現容器內的隔離。公司agent可以通過讀取memory等資訊,上報到監控平臺做分析與報警。同時運維通過SSH登入到這個容器,通過free、top等命令檢視效能,維持了運維原來的使用習慣。

kubernetes在騰訊遊戲的應用實踐

在傳統遊戲裡,更多的是有狀態的服務會涉及到資料的儲存,我們通過Docker的volume提供持久化儲存。最開始我們採用HostPath方式,把host上的目錄掛載到容器裡(例如/data)作為資料儲存。這種做法非常方便、簡單,無需額外的支援,但資料的安全性、可靠性方面比較差。所以我們採用了另外一種方案,即Ceph。改造kubenetes支援ceph,通過volume掛載,提供更安全、更可靠的資料儲存方案。解決在host故障時,資料丟失的問題,應用場景也變得更加廣泛,包括資料庫儲存,映象儲存,容器遷移等。

kubernetes在騰訊遊戲的應用實踐

今年,我們開始支撐第一款微服務化遊戲(極品飛車online),源於之前對kubernetes的使用經驗。在微服化容器的排程中我們沿用了kubernetes,但在版本上重新做了選擇,跟隨著社群的發展,選用了v1.2版。在微服務化模式下,遊戲的架構產生了很大的變化。按功能細分到各個小模組,通過映象交付、分發,最後以容器來部署服務。每個模組相對獨立,之間資訊流互動通過訊息元件(例如RabbitMQ)來實現。同時每個容器無須配置內網IP,可以通過域名來訪問。所以在網路方面也有所調整,我們也評估了docker overlay、flannel、vxlan、maxvlan、SR-IOV等,結合其中的優缺點,最後我們選定的方案如下:

1、叢集內pod與pod的之間的通訊,由於不需要內網IP(可以用虛擬IP)所以採用overlay網路,由flannel元件實現。

2、公司內網到叢集內pod通訊,例如HAProxy,遊戲某些模組,採用SR-IOV網路,由自己定製的sriov-cni元件實現。這類pod具備雙重網路,eth0對應overlay網路,eth1對應SR-IOV網路。

3、pod到公司內網之間的通訊。在微服務場景下,遊戲的資料儲存,周邊系統等,部署在物理機或者虛擬機器上,因此pod到這些模組、系統的訪問,走的是NAT網路。

4、公網(Internet)接入,採用公司的TGW方案。

kubernetes在騰訊遊戲的應用實踐

在整個微服化平臺上,涉及到的關健技術點會更多:

1、網路方案:即上述講到了overlay + SR-IOV + TGW + NAT方案

2、日誌,監控:對於微服務化架構的遊戲,版本的交付都是通過映象,不會把公司的agent打到映象,所以原來的lxcfs + agent監控就不適應了,所以這裡我們重新打造了一個新的日誌、監控平臺,與藍鯨團隊合作,實現了遊戲業務日誌採集;容器健康狀態、效能的監控

3、高可用方案:在資源的部署方面,我們採用了replication controller方式,通過kubernetes的controller manager模組來監測pod的狀態,在發生故障的時候,實現快速的遷移、恢復服務。另一方面,在load balance場景下,我們採用了HAProxy來實現

4、安全方面:kubernetes叢集承載著整個遊戲容器資源的排程、管理。不管是人為誤操作,還是黑客入侵,造成的影響將是非常之大。所以安全是我們需要考慮的重點,結合kubernetes,我們目前做了以幾方面,後面會有更加的安全策略提供

4.1 Authentication 和 Authorization。使用https來加密流量,同時在使用者許可權驗證上,提供了token驗證方式、ABAC許可權認證方式

4.2 Admission Controllers:配置具體的准入規則

4.3 ServiceAccount:主要解決執行在pod裡的程式需要呼叫kubernetes API以及非kubernetes API的其它服務問題

5、配置管理:通過configmap\secret為遊戲提供簡易的配置管理

6、服務發現:kubernetes會為每個pod分配一個虛擬的IP,但這個IP是非固定的,例如pod發生故障遷移後,那麼IP就會發生變化。所以在微服務化遊戲架構下,業務pod之間的訪問更多地採用域名方式進行訪問。在kubernetes生態鏈中,提供了skydns作為DNS伺服器,結合kubernetes的server可以很好的解決域名訪問問題

kubernetes在騰訊遊戲的應用實踐

開始講遊戲容器化的時候談到用映象來標準化部署,所以我們花了很多時間打造企業級的映象倉庫。目前支援registry v1\v2兩個版本,如右圖所示,在client端(docker)與registry之間採用nginx作為代理,實現v1\v2不同請求的轉發,這樣一來,使用者無需關心到底請求的是v1還是v2。在安全方面,不同型別使用者不同的許可權驗證方案。公司內部使用者接入OA認證,與公司平臺打通。外部使用者需要申請訪問許可權,由管理員分配帳號,然後通過分配的帳號來請求。在大批量拉取映象的時候,映象中心的效能、效率是我們需要考慮的問題。前期我們通過mirror方案來實現,在主要城市部署mirror registry,通過就近原則來拉取映象,解決效能瓶頸。後續我們還會採用P2P方案來提升映象拉取效能。同時我們定製了Notification Server,用於映象pull\push日誌記錄,便於後續分析與審計。在映象後端儲存方面,採用ceph叢集方案,從而提供穩定、強大的資料儲存。

kubernetes在騰訊遊戲的應用實踐

微服務化之路我們剛剛起航,在面臨挑戰的同時也帶來了機遇。不僅僅是線上業務的探索,我們也會探索離線計算、深度學習等系統的支援。

kubernetes在騰訊遊戲的應用實踐

來源於社群,回饋於社群。後續我們還會更多地參與社群互動,為社群做貢獻。這也是我們想去做的一點。目前有個開源的專案,sriov kubernetes的網路外掛(github.com/hustcat/sri…),集中了騰訊遊戲兩種模式下容器的高效能網路經驗,大家感興趣的可以關注下。

kubernetes在騰訊遊戲的應用實踐


相關文章