摘要:大家好今天我分享的主題與游戲行業相關,為大家介紹的是在騰訊游戲中的應用實踐。隨著技術的興起,我們開始調研在游戲容器化方面的應用。也就是說,將不同游戲業務部署到同一臺母機,采用綁定核的方式。在母機上架部署時,創建設備和設備并將它們進行關聯。
今天小數的推送內容來自騰訊互娛高級工程師黃惠波,讓我們一起來看看吧~~~
黃惠波,騰訊互娛高級工程師
目前主要負責游戲計算資源容器化平臺的研發工作,包括 kubernetes/docker 研究以及定制化開發,主導騰訊游戲萬級容器資源調度平臺的建設工作。
大家好!今天我分享的主題與游戲行業相關,為大家介紹的是 kubernetes 在騰訊游戲中的應用實踐。
騰訊在線游戲的容器化應用場景2014 年,我們開啟了容器化探索之路,先回顧一下之前遇到的一些問題。
在物理機時代,資源的交付時間較長,資源的利用率較低,也不能做到隔離。到了 xenkvm 虛擬機時代,問題得到了初步的解決,但在彈性伸縮方面仍有不足。隨著 Docker 技術的興起,我們開始調研 Docker 在游戲容器化方面的應用。我們的目標有兩個,一是提高資源利用率,二是通過 Docker 鏡像來標準化部署流程。
選擇 Docker 技術之后,我們開始了容器調度平臺的選型。我們當時也調研了其它的一些組件,比如 Shipyard 、 Fig 等,但這些組件無法支撐海量游戲容器調度。而自建調度平臺的話,時間成本非常的高。就在那時, Google 開源了 kubernetes (當時的版本是 kubernetes v0.4 ),我們基于這個版本進行了定制和開發,使其成為我們游戲容器的調度管理平臺。
在 2015 年初的時候, TDocker 平臺上線。之后,我們開始逐步接入業務。一開始的模式非常簡單,就是把 Docker 當成虛擬機來使用,但這不意味著游戲全容器化的實現。
大家知道,對于一項新技術來說,大家都很謹慎,會通過不斷的灰度上線,由點到面的策略推動。截至目前,在全國各地以及加拿大等地區,都有我們的部署點;接入容器數超過兩萬,接入的業務也有兩百多款,包括手游、端游、頁游。在這么多的業務中,主要分為兩種場景,第一種場景是輕量級虛擬機模式,這類容器承載多個服務進程,需要一個具體的內網 IP ,可以通稿 SSH 登錄。另一種是微服務化模式,這種模式會拆分得非常細,每一個容器對應一個服務進程,不需要對外可見的內網 IP ,可以使用虛擬 IP 。
接下來會對每一個場景做一些分享。首先來看一下傳統游戲下的架構。這是非常典型的三層服務架構,包括了接入層、邏輯層、數據庫層。同時,游戲又分為:全區全服、分區分服兩種類型。對于分區分服類游戲,滾服對資源的調度非常頻繁,所以我們需要一個高效的調度平臺。
容器資源的調度管理基于 kubernetes v0.4 版本,上圖是一個簡化后的調度框架。在 Master 端包括 ApiServer 和 Scheduler ,接收 Web 請求,然后做資源調度。在每個 node 節點上,包括 agent 進程、 Docker 進程,還有 Lxcfs 進程。在鏡像存儲方面,當時用的是 Registry V1 版,后端用的是 ceph 存儲。現在,我們自己維護了一個分支,功能上已滿足當前的游戲需求,并保證運行的穩定。所以在虛擬機模式下,我們不會升級 kubernetes ,而是把一些好用的功能合并進來。
基于 kubernetes 的功能定制與優化首先講調度器,調度器為數以萬計的容器提供了一個靈活、穩定、可靠的底層資源計算調度引擎。資源的合理分配像是一場博弈,里面有很多矛盾的地方,需要我們根據游戲的特點做取舍。
我們在原有的調度策略上根據游戲特點做了一些定制。比如在網絡方面,傳統游戲的每個容器都需要一個對外可見的實體 IP ,用戶可以通過 SSH 登錄到容器里面,因此對網絡資源進行調度。部署容器的時候,會申請 network 的資源(比如 IP )然后進行劃分,綁定到 minions 對象。這樣調度器調度的時候,就可以通過這些配置信息給容器分配好網絡資源。
在社區中, CPU 的分配用的是共享 CPU 的方式,游戲采用的是一種混部的模式。也就是說,將不同游戲業務部署到同一臺母機,采用綁定核的方式。這樣做一方面可以防止不同游戲之間的 CPU 搶占,另一方面對游戲成本的核算也會更加精細。例如,某個游戲用了多少 CPU 這些指標都是可以量化的。在容器分配 CPU 時,結全 numa 技術,對于 CPU CORE 的分配會盡量地分配到同一個 numa node 上,這樣可以提升性能,因為同個 numa node 的 CPU 訪問只需通過自身的 local memory ,無需通過系統總線。
在磁盤容量分配方面,由于游戲業務是有狀態的服務,需要存儲,所以我們把磁盤也作為一個可調度的資源分配給容器。還有非親和性的調度。我們知道,在容器的可靠性與碎片優化之間需要一個權衡,讓用戶根據這些策略去選擇、部署自己的容器。例如在非親和性的策略中,用戶希望把容器是分散到各個母機上的,在母機宕機時,可以減少對游戲的影響。
在 IDC Module 分配方面,游戲容器的部署會按地區劃分,比如按照上海、深圳或天津地區的 IDC 來劃分,所以我們提供了 IDC 部署策略。由于游戲需要考慮 IDC 的穿越流量問題,還有網絡延時的問題,所以同一個游戲的的不同模塊一般會部署到同一個 IDC Module 下面。
海量應用過程中遇到的問題與解決方案以上是基于游戲行業特點定制的調度規劃。在資源調度過程中,也遇到過一些問題,例如容器資源的重復調度。首先在調度過程中它會跟 ScheduledPod (已完全調度的容器)進行比較,判斷現在是不是有足夠的資源分配給待調度容器,最后通過 Bind (異步)把 Pod 信息寫入到 ETCD 。這里就會出現一個問題,那就是異步寫入慢了或者 ScheduledPod 同步慢了導致 ScheduledPods 不能及時刷新, Scheduler 計算出錯,從而造成資源重復計算。針對這個問題,我們的解決方案是在資源調度完成后,做一個檢測的邏輯,檢測調度的容器信息是否已在 ScheduledPod Cache 這里,然后再進入下一個容器的調度。當然這會帶來一定的性能損耗。
解決了這個問題,又產生了另外一些問題,那就是性能的問題。在 0.4 版本的 pod 接口是非常低效的,在查每一個 pod 狀態的時候,會通過實時查所有的 Host 來確定,設計不太合理。社區也做了一些方案,當時我們也是參考了社區的一些方案做了一些改造,把 pod 狀態放在 Cache 里面,定時更新,從而提高查詢效率。
還有一點就是 RESTClient 。在 kubernetes 中, rest API 大部分是異步進行,對于這些異步的接口的請求,并不會立刻返回結果。這里有一個輪詢檢測狀態的邏輯,在檢測輪詢的時候有幾秒的休眠,然后進再行下一個輪詢。默認的休眠時間是 2 秒,這個時間對大部分場景來說有點過長,我們通過一些功能點的調整,從物理機的小時級到虛擬機分鐘級的調度,再到還未調整之前的秒級調度,到現在達到的毫秒級調度,現在的調度能力已能滿足游戲的需求。
講完調度,再看一下網絡方面。網絡是非常關鍵、也是最為復雜的一環。在虛擬機模式下,結合公司網絡環境為游戲提供高性能、穩定的網絡環境,包括 Bridge+VLANSR-IOV 兩種方案。
先來說, Docker 的網絡還有 kubernetes 的網絡。對于 Docker 的 NAT 網絡來說,性能是最大的瓶頸,同時它與物理機或虛擬機的通信路徑不一致也會對業務帶來一些未知的影響。比如,外界不能看到容器真實的 IP(必須要使用主機 IP+port 方式,端口本身就是稀缺資源,并且 ip+port 的方式,無疑增加了復雜度), TGW 仍然可以為業務程序服務。 Host 模式沒有隔離,也不符合需求。在 kubernetes 中, pod 作為最小調度單元,每個 pod 有兩個容器,一個就是網絡容器,接管 pod 的網絡,提供網絡服務,并與其它容器共享 netIPC 。另一個是 App Container ,也就是業務容器,使用第一個網絡容器的網絡。在這種模式下,容器之間的通訊是非常簡單的。對于 pod 到 pod 、 pod 到物理機、物理機到 pod 的通訊,我們為每個 pod 分配一個內網 IP ,對外可見,也可以互相通訊。
接下來,通過兩個方案給大家分析。首先是 Bridge+Vlan 的方案,母機都是部署在虛擬化區上,通過 Vlan 做網絡的隔離。在母機上架部署時,創建 Bridge 設備和 VLAN 設備并將它們進行關聯。創建容器的時候,使用 pipework 腳本創建容器所需要的虛擬網卡設備,并把它們綁定到容器和 Bridge 上,同時會設置容器內的 IP 、 MAC 地址以及路由等信息。從而打通容器到外界的網絡通信。這里也做了一些優化以提高性能,這里可以看到一個性能的對比,其中 Bridge 相對 NAT 網絡有相當大的提升。這種方式可以滿足一部分游戲的需求,而有一些業務,像 FPS 、 Moba 游戲等大流量,對網絡要求非常高的業務,還有類似 MySQL-Proxy 這種組件,在 Bridge 場景下是無法滿足需求的。
所以我們探索了另一種網絡方式,就是 SR-IOV 模式,這種模式在 zenkvm 虛擬化上用的比較多,游戲也需要這種網絡方案,因此我們把這種網絡方案也結合到 Docker 容器里面。
這里需要硬件的支持,結合 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 帶寬的限制。
在資源分配方面,我們開始做的是限定的 CPU 、內存的分配。在容器的整個生命周期,這個配置并非一沉不變,比如在業務運行過程中都會有一些起伏和動態調整,這是游戲的一張生命周期圖像,生命周期比較短,可能是一年半載的時間,而且這里在線人數起伏也會比較大,需要動態調整。而動態調整就會涉及兩個方面,一是橫向的水平擴展,二是垂直伸縮。
每個游戲都會有一個 IP ,因此橫向拓展比較困難,因而更傾向于穩定的垂直擴縮。在虛擬化時代,擴縮容是有損的,需要重啟機器來實現,而 Docker 可以做到無損的擴縮容。我們對這個需求做了一些定制開發,比如 CPU 或者內存,通過修改 Cgroup 的配額去把它提升上去或是削減下來。
當在線人數上來的時候,我們可以給業務做到無損擴容,不影響業務服務。過了一段時間,當人數降下來時,資源會閑置,我們會對空閑的資源做一些重復利用,將其回收。這個時候做一些縮容,針對縮容我們做一個常態的動作,檢測這些容器的 CPU 、內存,結合業務的負載、活動、定時驅動。
Buffered IO Throttle 需要內核支持,我們與內核團隊進地了緊密的合作,提供了支持 Buffered IO Throttle 功能的內核版本。根據容器在母機資源的占比分配一定比例的 IO 帶寬。這在某種程序上解決了游戲之間互相影響的問題。
監控、告警是整個游戲運營過程中最為核心的功能之一。容器上的監控有別于物理機, 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 等命令查看性能,維持了運維原來的使用習慣。
在傳統游戲里,更多的是有狀態的服務會涉及到數據的存儲,我們通過 Docker 的 volume 提供持久化存儲。最開始我們采用 HostPath 方式,把 host 上的目錄掛載到容器里(例如 /data )作為數據存儲。這種做法非常方便、簡單,無需額外的支持,但數據的安全性、可靠性方面比較差。所以我們采用了另外一種方案,即 Ceph 。改造 kubenetes 支持 ceph ,通過 volume 掛載,提供更安全、更可靠的數據存儲方案。解決在 host 故障時,數據丟失的問題,應用場景也變得更加廣泛,包括數據庫存儲,鏡像存儲,容器遷移等。
今年,我們開始支撐第一款微服務化游戲(極品飛車 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 方案。
在整個微服化平臺上,涉及到的關健技術點會更多:
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 、配置管理:通過 configmapsecret 為游戲提供簡易的配置管理
6 、服務發現: kubernetes 會為每個 pod 分配一個虛擬的 IP ,但這個 IP 是非固定的,例如 pod 發生故障遷移后,那么 IP 就會發生變化。所以在微服務化游戲架構下,業務 pod 之間的訪問更多地采用域名方式進行訪問。在 kubernetes 生態鏈中,提供了 skydns 作為 DNS 服務器,結合 kubernetes 的 server 可以很好的解決域名訪問問題
開始講游戲容器化的時候談到用鏡像來標準化部署,所以我們花了很多時間打造企業級的鏡像倉庫。目前支持 registry v1v2 兩個版本,如右圖所示,在 client 端(docker)與 registry 之間采用 nginx 作為代理,實現 v1v2 不同請求的轉發,這樣一來,用戶無需關心到底請求的是 v1 還是 v2 。在安全方面,不同類型用戶不同的權限驗證方案。公司內部用戶接入 OA 認證,與公司平臺打通。外部用戶需要申請訪問權限,由管理員分配帳號,然后通過分配的帳號來請求。在大批量拉取鏡像的時候,鏡像中心的性能、效率是我們需要考慮的問題。前期我們通過 mirror 方案來實現,在主要城市部署 mirror registry ,通過就近原則來拉取鏡像,解決性能瓶頸。后續我們還會采用 P2P 方案來提升鏡像拉取性能。同時我們定制了 Notification Server ,用于鏡像 pullpush 日志記錄,便于后續分析與審計。在鏡像后端存儲方面,采用 ceph 集群方案,從而提供穩定、強大的數據存儲。
微服務化之路我們剛剛起航,在面臨挑戰的同時也帶來了機遇。不僅僅是在線業務的探索,我們也會探索離線計算、深度學習等系統的支持。
來源于社區,回饋于社區。后續我們還會更多地參與社區互動,為社區做貢獻。這也是我們想去做的一點。目前有個開源的項目, sriov kubernetes 的網絡插件( https://github.com/hustcat/sr... ),集中了騰訊游戲兩種模式下容器的高性能網絡經驗,大家感興趣的可以關注下。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/32534.html
摘要:正在走遠,新年之初,小數精選過去一年閱讀量居高的技術干貨,從容器到微服務云原生,匯集成篇精華集錦,充分反映了這一年的技術熱點走向。此文值得收藏,方便隨時搜索和查看。,小數將繼續陪伴大家,為朋友們奉獻更有逼格的技術內容。 2017正在走遠,新年之初,小數精選過去一年閱讀量居高的技術干貨,從容器、K8S 到微服務、云原生、Service Mesh,匯集成52篇精華集錦,充分反映了這一年的技...
摘要:本文內容節選自由主辦的第七屆,架構師高欣分享的的實踐實錄。當然,在部署完成后,我們要做一個監測以便掌握它的運行狀況。規劃配置運行環境在正式部署前,還要考慮如何規劃并配置好運行環境。在使用部署時,可以利用這些命令做驗證,檢驗部署是否正常。 showImg(https://segmentfault.com/img/bVblRHj?w=2880&h=1920); 本文內容節選自由msup主辦...
摘要:今天小數給大家帶來一篇技術正能量滿滿的分享來自社區線上群分享的實錄,分享嘉賓是數人云肖德時。第二級調度由被稱作的組件組成。它們是最小的部署單元,由統一創建調度管理。 今天小數給大家帶來一篇技術正能量滿滿的分享——來自KVM社區線上群分享的實錄,分享嘉賓是數人云CTO肖德時。 嘉賓介紹: 肖德時,數人云CTO 十五年計算機行業從業經驗,曾為紅帽 Engineering Service ...
摘要:數人云容器助力產品迭代力沙龍干貨分享實錄持續上新,今天是來自人人貸高級運維工程師杜天鵬的分享,與我們細數了人人貸容器化實踐過程中遇到的問題以及解決方法。 數人云容器助力產品迭代力MAX沙龍干貨分享實錄持續上新,今天是來自人人貸高級運維工程師杜天鵬的分享,與我們細數了人人貸容器化實踐過程中遇到的問題以及解決方法。 很高興站在這里和大家一起交流容器技術,我叫杜天鵬,是人人貸的運維工程師。人...
閱讀 1017·2021-09-30 09:58
閱讀 2848·2021-09-09 11:55
閱讀 2011·2021-09-01 11:41
閱讀 1004·2019-08-30 15:55
閱讀 3363·2019-08-30 12:50
閱讀 3508·2019-08-29 18:37
閱讀 3310·2019-08-29 16:37
閱讀 2023·2019-08-29 13:00