揭祕LOL背後的IT基礎架構丨產品而非服務

歡迎來到Tungsten Fabric用戶案例系列文章,一起發現TF的更多應用場景。“揭祕LOL”系列的主人公是Tungsten Fabric用戶Riot Games遊戲公司,作爲LOL《英雄聯盟》的開發和運營商,Riot Games面臨全球範圍複雜部署的挑戰,讓我們一起揭祕LOL背後的“英雄們”,看他們是如何運行在線服務的吧。
作者:Nicolas Tittley和Ala Shiban(文章來源:Riot Games)譯者:TF編譯組

在這裏插入圖片描述
這個長系列的文章,探討並記錄了Riot Games如何開發、部署和運營後端基礎架構的歷程。我們是Riot 開發體驗團隊的軟件架構師兼產品經理Nicolas Tittley和Ala Shiban。我們團隊負責幫助Riot開發人員在玩家所處的任何地方構建、部署和運營遊戲,同時專注於雲無感(cloud-agnostic)平臺,這些平臺使遊戲的發行和運營變得更加輕鬆。

在過去的兩年前的一篇文章中,Maxfield Stewart介紹了有關開發生態系統,以及當時使用的許多工具。這裏我們將更新一些最新的內容,包括面臨的新挑戰,如何解決問題,以及我們從中學到的東西。

快速回顧

我們強烈建議您回過頭閱讀以前的文章,但是如果您想直接閱讀本文,這裏有一個超級精簡版本來幫您趕上進度。

Riot使用裸金屬和雲基礎架構的組合來在全球範圍內運行後端系統。這些後端系統被分散到不同的地理位置,基於完全不同的部署,運行着允許玩家與LOL《英雄聯盟》互動的整套服務。像大多數遊戲的後端系統一樣,LOL後端開始時作爲一個整體,由專門的運營團隊來負責運營。隨着時間的推移,Riot逐漸擁抱了DevOps實踐和基於微服務的體系架構。本系列的第一篇文章做了詳細介紹,爲了幫助我們的開發人員更快地服務玩家,Riot大量依賴於Docker容器這種打包服務,並開始在集羣調度程序中運行它們。直到最近一篇文章,討論了爲實現此目的而使用的許多工具。

運行效果如何?

非常牛,但,痛並快樂着。

在上篇文章發表之時(編者按:發表時間爲2017年12月),我們運營着5000多個生產容器。這個數字並沒有停止增長,今天,僅在Riot自主運營的區域(Riot-operated regions),我們就運行了14,500多個容器。Riot的開發人員喜歡爲玩家創造新事物,當他們越容易編寫、部署和運營服務,他們就越能創造出令人興奮的新體驗。

開發團隊以真正的DevOps方式,擁有並負責他們的服務。他們創建了工作流來部署、監視和運營那些服務,當他們找不到所需的東西時,就乾脆自己發明再造。對於開發人員來說,這是一個非常自由的時期,他們很少遇到無法自行解決的問題。

但慢慢地,我們開始注意到一些令人擔憂的趨勢。每個月的QA和負載測試環境變得越來越不穩定。我們不得不花費更多的時間,來查找錯誤的配置或過時的依賴關係。這些孤立的事件並不是關鍵,但總的來說,它們耗費了團隊很多時間和精力——我們更願意將其花費在創造玩家價值上。

更糟糕的是,在非Riot自主運營的分片區域(non-Riot shards),不僅開始出現類似的困難,而且還爆出一系列其它問題。合作伙伴們必須與越來越多的開發人員進行對接,並採用越來越多的微服務,每種微服務都有不同的方式,彼此各不一樣。現在,運營人員必須比以往更加努力,以創造出有效且穩定的分片區域。在這些非Riot自主運營的分片區域,問題發生率要高得多,直接原因就是微服務的實時版本不兼容,或者其它類似的跨界問題。

Riot的DevOps現狀

在討論如何解決打包、部署和運營之前,讓我們花一點時間來探討Riot的運行環境。這些都不是Riot所獨有的,但所有這些細節的重疊,都說明了我們是如何組織起來,以便爲所有玩家提供價值的。

開發者模式
Riot的工程師們喜歡自己建造東西!爲了幫助他們做到這一點,我們採用了強大的DevOps思維方式。團隊建立並擁有了自己的後端服務,確保對其提供支持,並在服務表現不如預期時進行分流。總的來說,Riot工程師很高興能夠實現快速迭代,也很樂意對自己的實時服務負責。這是一個非常標準的DevOps設置,Riot並沒有在任何方面逆勢而上。

有狀態分片模式
由於歷史原因、規模性問題,以及法律方面你的因素,Riot產品的後端系統按照分片的方式進行組織。其中,生產分片通常在地理位置上靠近目標受衆。這樣做有許多好處,包括改進的延遲問題,更好的匹配性,有限的故障域,以及清晰的非高峯時間窗口(可在其中執行維護操作)。當然,我們還在內部和外部運行着許多開發和QA分片,例如《英雄聯盟》公開測試服(PBE)。
https://technology.riotgames.com/sites/default/files/engineeringesports_4.gif

運營模式
這是事情變得更加複雜的地方。儘管Riot是開發者,但出於合規性和專有技術的原因,我們與一些本地運營商合作以提供一些服務分片。實際上,這意味着Riot的開發人員必須打包分片的每個組件,將其交付給運營人員,並指導他們如何部署、配置和運營所有分片。Riot的開發人員不會自己去操作、訪問甚至查看這些分片。(編者按:文中的分片邏輯可以理解成分塊分區域的定義)

迭代解決方案

嘗試1-新的聯盟部署工具
我們第一次嘗試改善情況,就採取了全新的方法,嘗試利用開源組件和最少Riot定製功能,來推進Riot的部署和運營工作。儘管這項工作成功地部署了完整的《英雄聯盟》分片,但工具的設計方式並沒有達到開發人員和運營人員的期望。團隊表達了對工具的不滿——這種工具被證明對運營來說太難採用,對開發者來說太受約束。

因此,在第一個分片部署後,我們就做出了痛苦的決定——讓這些工具退役。這看起來好像很激進,但由於所有團隊仍然擁有自己維護的部署系統並且尚未完全過渡,因此我們能夠快速淘汰新的工具。

嘗試2-更多流程
由於第一次嘗試並不如預期的成功,我們轉向傳統,通過添加流程來達到要求。廣泛的溝通,明確的發佈日期,文檔化的流程,變更管理會議和儀式,以及永遠存在的電子表格,在某種程度上取得了一點點進展,但始終感覺不佳。團隊喜歡他們的自由DevOps,巨大的變化量和變化速度,都使他們的工作更加繁重。儘管合作伙伴的情況有所改善,但我們仍未達到所期望的運營水準。

嘗試3-元數據
我們決定嘗試另一種方法。之前我們一直將開發人員作爲工具的主要受衆,現在則開始研究針對於合作伙伴的運營人員,部署/運營系統將如何工作。我們精心設計了一種工具,允許開發人員向其Docker容器的打包微服務添加標準化元數據,例如所需的配置和擴展特性。這帶來了進步,運營人員可以採用更加標準化的方式來理解所需的服務配置和部署特性,並且在日常運營中減少對開發人員的依賴。
此時,本地和合作夥伴運營站點的故障率、事件率和額外的停機時間都有所改善,但我們仍然頻繁遇到部署和運營故障,這些故障本來都是可以避免的。

嘗試4-Riot的應用程序和環境模式
我們最終採用了一種新方法,將關注點從個人服務轉移到了整個產品。我們創建了一個高級別的聲明性規範,以及可對其執行操作的工具集,讓規範和工具變得與衆不同。在詳細介紹之前,我們先來看一下前三次的嘗試中出了什麼問題。

反思錯誤之處

部署和運營的是產品,而非服務
儘管擁抱DevOps和微服務給我們帶來了許多好處,但它創建了一個危險的反饋環路。開發團隊創建微服務,對其進行部署、運營,並對其性能負責。這意味着他們爲自己優化了日誌、度量標準和流程,並且通常很少考慮其服務能否爲其他人所理解,包括沒有開發背景甚至工程能力的人。

隨着開發人員創建出越來越多的微服務,運營整體產品變得非常困難,並導致越來越多的失敗。最重要的是,Riot的流動團隊結構,使一些微服務的所有權變得不清晰,很難在分流時搞清楚應該與誰聯繫,從而導致出現很多屬性錯誤的頁面。越來越多的異構微服務、部署流程和組織變更,使得合作伙伴地區的運營團隊不知所措。

搞清楚“爲什麼”
我們檢查了Riot運營區域和非Riot運營區域的故障,並將故障頻率的差異提煉爲一項關鍵的觀察結果:

允許不連續的變更流進入分佈式系統最終將導致可預防的事件。

當團隊希望跨邊界進行協調時,就會開始發生故障,因爲依賴關係需要將發佈與多個更改捆綁在一起。團隊要麼使用人工流程來創建發佈週期,通過項目管理儀式協調發布,要麼臨時發佈較小規模的發佈更改,導致團隊在找出兼容版本的過程中陷入混亂。

兩者各有其優缺點,但是在大型組織中往往會崩潰。想象一下,數十個團隊需要以協調的方式,連續交付代表共享產品的數百個微服務,並且允許這些微服務使用不同的開發實踐。更糟的是,對於合作伙伴來說,嘗試應用這些流程非常困難,他們的操作人員缺乏關於各個部分如何組合起來的上下文。

新解決方案:Riot的應用程序和環境模型

鑑於先前的嘗試未能產生預期的結果,我們決定通過創建一個自用固有對的(opinionated)聲明性規範來消除部分狀態操縱,該聲明性規範可以捕獲整個分佈式產品——環境。環境包含完全指定、部署、配置、運行和運營一組分佈式微服務所需的所有聲明性元數據,這些微服務共同代表一種產品,並且是完整且不變的版本。我們之所以選擇“環境”這個名字,是因爲它是Riot 最不會過度使用的一個詞。命名實在是一件難事。

隨着遊戲《符文之地傳奇》LOR的發佈,我們證明了可以描述整個的微服務遊戲後端(包括遊戲服務器),並使其在Riot自主運營地區以及全球合作伙伴的數據中心中,作爲產品進行部署、運行和運營。我們還展示了實現這一目標的能力,同時改善了已經廣受喜愛的DevOps方法的優勢。

對什麼進行規定描述(OPINIONATED ON WHAT)
該規範描述了服務捆綁包或環境之間的層次關係。
在這裏插入圖片描述
捆綁到環境規範中的應用程序規範

聲明性與高等級
聲明性規範的好處之一是它易於操作。對於合作伙伴的運營人員,他們的其中一個困難,就是無法理解、調整和潛在地自動化整個遊戲後端的部署方式。規範的聲明性性質,意味着它不需要工程師具有腳本或編程專業知識,就可以對規範中的大多數內容進行更改。

保持規範的高等級,有助於將遊戲後端的定義與基礎實現脫鉤。這使我們能夠在對遊戲工作室影響最小的情況下,從名爲Admiral的內部編排器/調度程序,遷移到基於Mesos的調度程序,以及考慮遷移到Kubernetes。它還使我們的合作伙伴運營人員可以在需要時交換其基礎架構組件。例如,它允許運營人員可以使用不同的指標聚合系統,而不需要更改微服務工具。

不可變與版本化
我們發現,要在快速發展的DevOps世界中有效部署和運營,使用共享語言來引用服務和環境至關重要。版本控制服務和環境及其關聯的元數據,使我們能夠確保所有位置都部署了正確的版本。它使我們的合作伙伴運營人員可以確定地知道正在運行哪個版本,並且回傳給我們。此外,當應用於整個環境時,它提供了一組衆所周知的服務,可以對其進行質量檢查並標記爲“好”。這種捆綁消除了在向合作伙伴傳達新版本時遺失依賴項的任何可能性。

使這些版本不可變,可以確保我們維持這種通用語言。當相同版本的服務被部署在兩個不同的分片中,我們現在也可以確定它們是完全相同的。

專注於運營
鑑於我們的目標是提高合作伙伴運營人員服務玩家的水平,我們很快意識到,部署軟件只是第一步。瞭解如何對實時系統進行分類、運營和維護,是同樣重要的事情。

從歷史上看,我們非常依賴於運行手冊。手冊由開發人員維護,並取得了不同程度的成功,他們記錄了從必需的配置值到高等級體系架構的所有內容。爲了使合作伙伴運營人員具備配置和操作每種服務所需的全部知識,我們決定將這些運行手冊中包含的儘可能多的信息帶到服務規範的最前面。這大大減少了合作伙伴地區投入新服務的時間,並確保他們在微服務更新時被告知所有重要變化。

如今,合作伙伴運營人員可以使用該規範來了解有關操作元數據的信息,包括所需/可選配置、擴展特性、維護操作,重要指標/警報定義、部署策略,服務間依存關係,以及越來越多的其它有用信息。

處理分片差異
當然,分片不是彼此完全相同的副本。儘管我們希望使它們儘可能地接近,但總有一些配置必須有所不同。數據庫密碼、支持的語言、擴展參數,以及特定的調整參數必須隨每個分片而變化。爲了支持該模式,我們的工具使用分層的覆蓋系統部署環境規範,使運營人員可以專門化特定的部署,同時仍然知道它們都源自已知的良好版本。讓我們看看它是如何工作的!

應用案例
一個簡單的遊戲後端可以包括兩個環境,一個用於遊戲服務器,另一個用於元遊戲服務(排行榜,匹配系統等)。元遊戲環境由多種服務組成:排行榜、匹配系統、比賽歷史等等。每個服務都包含一個或多個Docker映像,從概念上講,它們等效於Kubernetes容器。對於所有環境,相同的層次結構都是正確的,並且從哲學上講,每一個環境都毫無例外地封裝了在任何受支持的基礎架構或雲上部署、運行和運營的遊戲後端所需的一切,及其所有的依賴項。

該規範還包括運行和運營整個環境所需的所有元數據。不斷增長的集合包括配置、機密、指標、警報、文檔、部署及rollout策略、入站網絡限制,以及存儲、數據庫和緩存要求。

下面我們有一個示例,演示在兩個區域中進行兩個假設的遊戲分片部署。您可以看到它們都由元遊戲環境和遊戲服務器環境組成。在歐洲分片中的遊戲服務器產品環境,落後於美國分片中的同類遊戲環境。這爲遊戲和運營團隊提供了描述和比較不同遊戲分片部署的通用語言。每個環境中不斷增加的服務數量可以保持簡單性,從而可以可靠地部署數十個分片。在這裏插入圖片描述遊戲分片部署示例

我們的下一步:延遲感知調度
我們希望能夠描述服務之間的預期和可接受的延遲,並使工具針對基礎區域和較低級別的PaaS服務進行優化,使其能夠滿足這些需求。這將導致某些服務位於同一個機架、主機或雲區域中,而不是允許它們分佈在其它服務中。
由於遊戲服務器和支持服務的性能特點,這件事與我們高度相關。Riot已經是一家多雲公司,有我們自己的數據中心,也有AWS以及合作伙伴的雲,但是我們依靠靜態設計的拓撲。紙牌遊戲和射擊遊戲具有不同的配置文件,不必針對一、兩種情況的優化進行手工拓撲,從而節省了工程師們的時間,使他們可以專注在遊戲上面。

最後的話

我們在運行遊戲過程中面臨着穩定性下降的問題,主要是來自合作伙伴經營的遊戲分片。工具開發團隊捆綁了開源部署工具,並將元數據添加到了容器中,而遊戲團隊則實施了集中發佈流程。這些方法可以解決症狀,但不能解決導致問題的根本原因,這意味着我們未能達到目標水準。

我們最終採用的解決方案引入了一個新規範,該規範捕獲了整個遊戲後端的所有拓撲、層次結構和元數據及其所有依賴項。這種方法之所以有效,是因爲它帶來了綁定容器的一致的版本發佈,它們之間交互方式的依賴關係,以及啓動和操作整個遊戲所需的所有支持元數據。而不可變性帶來了確定性的部署和可預測的操作。

作爲一個平臺團隊,我們的目標是挑選能夠產生良性循環的系統和構建模塊,在這樣的良性循環中,功能開發工作自然會帶來易於操作的產品。將DevOps模式的敏捷性與易於操作的整個產品相結合是長期組織敏捷性的關鍵。我們的環境捆綁方法直接改善了運營指標,更重要的是提高了玩家體驗的質量。我們很高興看到業界其他人士如何解決類似的問題。我們已經看到了來自CNCF(雲原生計算基金會)和大型雲供應商(例如Microsoft開放應用程序模式規範)的想法和項目。希望其中一些項目能夠取代我們自己制定的規範,並朝着全行業解決方案邁進。

在以後的文章中,我們還將更詳細地探討Riot規範,介紹示例,並討論設計中的權衡以及Riot特定的快捷方式。

謝謝閱讀!如果您有任何疑問,非常歡迎與我們取得聯繫。

更多“揭祕LOL”系列文章
揭祕LOL背後的IT基礎架構丨踏上部署多樣性的征程
揭祕LOL背後的IT基礎設施丨關鍵角色“調度”
揭祕LOL背後的IT基礎架構丨SDN解鎖新基礎架構
揭祕LOL背後的IT基礎架構丨基礎設施即代碼
揭祕LOL背後的IT基礎架構丨微服務生態系統
揭祕LOL背後的IT基礎架構丨開發者“打野”工具能做什麼?

在這裏插入圖片描述在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章