您好,登錄后才能下訂單哦!
歡迎來到Tungsten Fabric用戶案例系列文章,一起發現TF的更多應用場景。“揭秘LOL”系列的主人公是Tungsten Fabric用戶Riot Games游戲公司,作為LOL《英雄聯盟》的開發和運營商,Riot Games面臨全球范圍復雜部署的挑戰,讓我們一起揭秘LOL背后的“英雄們”,看他們是如何運行在線服務的吧。
作者:Kyle Allan和Carl Quinn(文章來源:Riot Games)
我們是Kyle Allan和Carl Quinn,在Riot的基礎架構團隊工作。歡迎閱讀這個系列的第二篇文章,詳細介紹我們如何在全球范圍內部署和操作后端功能。在本文中,我們將深入探討部署生態系統的第一個核心組件:容器調度。
在Jonathan的第一篇系列文章中,討論了Riot的部署歷史和我們面臨的挑戰。特別是,他概述了當我們為《英雄聯盟》不斷添加基礎架構設施時,尤其是面對“為每個應用程序手動配置服務器”這樣的場景下,我們軟件部署難度不斷加劇。后來,出現了一個名為Docker的工具,改變了我們的服務器部署方法——進一步在我們內部就迭代出來Admiral,它是我們用于集群調度和管理的內部工具。
重要的是,應用程序部署的旅程還遠遠沒有結束,它還在不斷發展,我們正在為下一個階段做準備(可能采用DC/OS,稍后討論)。本文介紹了如何到達這一步,以及為什么做出這樣的決定,希望其他人也可以從這個故事中有所收益。
當Docker橫空出世,并且Linux容器化成為一種更廣為人知的技術時,我們意識到,可以通過容器化基礎架構的實施而受益。Docker容器映像提供了一個不變的、可部署的“神器”,它可以一次構建并部署在開發、測試和生產中。此外,它還保證生產環境中運行的映像的依賴性,與測試期間的依賴性完全相同。
另一個好處尤其重要:Docker允許將部署單元(容器)與計算單元(主機)解耦,它通過利用調度程序將容器分配給主機(希望以一種智能的方式),從而消除了服務器與應用程序之間的耦合——給定的容器可以在任意數量的可能的服務器上運行。
通過將后端服務打包成Docker映像,并且可以隨時將其部署并擴展到服務器集群,我們應該能夠迅速適應變化。我們可以添加新的玩家功能,當流量增加時進行擴容,并快速推出更新和修復程序。在考慮將容器內的服務部署到生產環境時,需要解決三個主要問題:
這三個問題的答案是,我們需要一個調度程序——一種在服務集群層面運行并執行我們的容器策略的服務。調度程序是維護集群、確保容器在正確的位置運行,以及在容器退出時重新啟動它們的關鍵組件。
例如,我們可能要啟動諸如Hextech Crafting之類的服務,該服務需要六個容器實例來處理其負載。調度程序負責查找具有足夠內存和CPU資源以支持這些容器的主機,并執行使這些容器運行所需的任何操作。如果這些服務器之一發生故障,調度程序還負責為受影響的容器查找替換主機。
當我們決定使用調度程序時,就快速進行原型設計,以便了解容器化服務在生產中是否適合我們。此外,我們需要確保現有的開放源代碼選項可以在目前的環境中運行,或者確保維護人員愿意接受我們的調整。
在開始編寫Admiral調度程序之前,我們調查了現有集群管理器和調度程序的狀況。都有誰在Docker主機集群之間調度容器,它們是如何做到的?它們的技術還能解決我們的問題嗎?
在最初的研究中,我們調研了一些項目:
Mesos + Marathon
LMCTFY => Kubernetes
Fleet
我們還原型化了一個小型命令行工具,該工具可通過REST與Docker API進行通信,并且成功演示了如何使用此工具來協調部署。然后,我們決定繼續編寫自己的調度程序。
我們借鑒了研究過的系統的一些最佳功能,包括Kubernetes的Pods和Marathon的約束系統背后的核心思想。我們的愿景是跟蹤這些系統的體系結構和功能,在可能的情況下影響它們,并最終嘗試在將來與其中之一融合。
在創建了一個基于JSON的基礎部署元數據語言(我們稱為CUDL,ClUster描述語言)之后,我們開始編寫Admiral。CUDL成為Admiral在其REST API中使用的語言,兩個主要組成部分如下:
集群和打包具有兩個不同的方面:spec和live。每個方面都代表對容器生命周期不同階段的描述。
Spec,表示元素所需的狀態
Live,表示元素已實現的狀態
Admiral用Go編寫,并且在生產數據中心中運行時,被編譯并打包到Docker容器中。Admiral有幾個內部子系統,其中大部分如下圖所示。
從用戶的角度來看,與Admiral的交互是通過其提供的admiralctl命令行工具進行的,該工具通過REST API與Admiral進行通信。借助admiralctl,用戶可以通過標準指令訪問Admiral的所有功能:POST新的Spec打包以進行調度,DELETE舊包(Packs),以及GET當前狀態。
在生產過程中,Admiral將使用Hashicorp的Consul存儲Spec狀態,定期對其進行備份,以防發生災難性故障。萬一完全丟失數據,Admiral還能使用從各個Docker守護程序檢索到的Live狀態中的信息,來部分重建其Spec狀態。
協調器(reconciler)屬于Admiral的核心,是驅動調度工作流程的關鍵子系統。協調器會周期性地將實際的Live狀態與所需的Spec狀態進行比較,并且在出現差異時,調度所需的操作,以便將Live狀態恢復正常。
Live狀態及其驅動程序包通過緩存Live主機和容器狀態,并通過其REST API提供與集群主機上所有Docker守護程序的通信,來支持協調器。
Admiral的協調器可對Spec打包進行操作,有效地將其轉換為Live打包。在將Spec打包提交給Admiral時,協調器將創建容器并使用Docker守護程序啟動它們。正是通過這種機制,協調器實現了我們前面所述的最重要的兩個高級調度目標。當協調器收到Spec打包時,它將:
讓我們看一下在Docker主機上啟動容器的示例。在此示例中,我們將使用本地Docker守護程序作為Docker主機,并與Admiral服務器的本地實例進行交互。
首先,我們使用“admiral pack create <cluster name> <pack file>”命令啟動一個打包。此命令針對特定集群,并將Spec打包的JSON 提交到Admiral服務器。
你能注意到,幾乎在剛剛運行命令后,容器就已經在我的機器上啟動。這個容器是使用我的打包文件中的參數啟動的,如下所示:
接下來,在調用“admiral pack create”之后,我們可以使用“show”命令來查看Admiral創建的Live打包。這里的命令是“admiral pack show <cluster name> <pack name>”。
最后,通過點擊容器中的服務,我們可以驗證打包是否正常工作。使用來自“admiral pack show”命令的信息,我們可以通過一個簡單的curl來拼出我們的服務:
在Admiral內部,協調器始終處于運行狀態,以確保集群的Live狀態始終與所需的Spec狀態相匹配。這樣,當容器由于崩潰而失敗并退出,或者由于硬件故障而導致整個服務器不可用時,我們還可以進行恢復業務。協調器努力確保狀態匹配,以便玩家永遠不會遇到中斷問題。此功能解決了我們前面提到的第三個,也是最后一個問題:當容器意外退出時,我們可以快速恢復,并且將影響控制到最小。
下面將展示通過“admiral pack create”命令啟動的現有容器。然后,我將終止該容器,并停止其執行。在幾秒鐘內,協調器啟動了一個新的容器(具有不同的ID),因為它意識到Live狀態與Spec狀態不匹配。
為了最好地分配容器,調度程序必須洞悉主機集群。解決此問題有兩個關鍵組件:
資源——服務器可用資源的一種表示形式,包括內存、CPU、I/O,以及網絡等其他資源。
約束——打包隨附的一組條件,可為調度程序提供有關可放置打包的限制的詳細信息。例如,我們可能要放置一個打包實例:
通過在主機上定義資源,我們使調度程序可以靈活地決定將容器放置在何處。
通過在打包集(packs)上定義約束,我們可以限制調度程序的選擇,以便將特定的模式強制應用到集群中。
對于Riot而言,Admiral是我們部署技術不斷發展的重要組成部分。通過利用Docker和調度系統的功能,我們能夠比以前更快地向玩家交付后端功能。
在本文中,我們深入研究了Admiral的一些功能,并展示了如何在一組機器集群之間調度容器。就像Jonathan在他的第一篇文章中提到的那樣,開源世界已經迅速轉向非常相似的模型。展望未來,我們將轉移Admiral的工作,并專注于部署DC/OS,它已成為調度容器工作負載的領先的開源應用程序之一。
如果你經歷了類似的旅程,或者覺得自己有話要補充,非常歡迎與我們取得聯系。
更多“揭秘LOL”系列文章
● 揭秘LOL背后的IT基礎架構丨踏上部署多樣性的征程
關注微信:TF中文社區
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。