京東雲的雲原生理念及 Serverless 最佳實踐

京東科技開發者發表於2019-08-29
京東雲的雲原生理念及 Serverless 最佳實踐
在雲原生技術全面爆發之前,我們開發的應用可以被稱為非雲原生應用,非雲原生應用並沒有考慮到應用的彈性和規模性,甚至很多都不具備擴充套件性,當業務規模擴大時,特別依賴硬體的升級,進而帶來了很多問題。雲原生的出現帶來了新的開發方式,然而這一技術處於快速的發展過程中,導致很難定義清楚各類概念和理解各種技術名詞。 為此,Infoq專門採訪了京東雲中介軟體團隊負責人李道兵,瞭解京東雲在雲原生領域的理念和相關探索,以期對開發者有所幫助。以下為本次採訪的整編內容。
如今,企業很難在聊雲原生這個話題時避開容器,但是往回倒四年,容器在國內的應用並不普遍,大多集中在技術實力較強的網際網路大廠,但也並非後來大火的 Docker,當時的不少文章還將這群早期實踐者稱作“敢於吃螃蟹的人”。顯然,在雲原生領域,容器的發展是推動其落地的重要條件,但最大的需求並不是為了使用容器,這個邏輯本身就很奇怪,為了出現而出現的技術往往不會有好的結局,容器所解決的問題才是組織或開發者最大的需求。那麼,組織現階段對雲原生實踐最大的需求是什麼呢?
過去幾個月,InfoQ 先後就雲原生這一話題採訪了阿里巴巴、騰訊、青雲、居然之家、華為等眾多廠商,對值得關注的開源技術及相關落地實踐進行了初步探索。本文,InfoQ 對京東雲中介軟體產品研發部高階總監李道兵進行了獨家專訪,瞭解京東雲在雲原生領域的理念和相關探索。

雲原生理念

關於雲原生,其實每篇相關文章都會特意留出一部分講解企業的理念,也多次提到了 Pivotal 公司的 Matt Stine 寫的一本叫做遷移到雲原生應用架構的小冊子以及 CNCF 在今年 KubeCon 上海站提出的定義(V1.0):
雲原生技術有利於各組織在公有云、私有云和混合雲等新型動態環境中,構建和執行可彈性擴充套件的應用。雲原生的代表技術包括容器、服務網格、微服務、不可變基礎設施和宣告式 API。
但是,正如李道兵在接受採訪時所言:“與其說雲原生涉及了眾多理念,不如說現在社群還沒有找到最佳實踐應該是什麼樣子。”正因如此,每篇文章都會花費一些篇幅介紹本文所討論的雲原生理唸的範圍。
相比於“雲原生”這個名字的誕生,李道兵認為這一概念的出現可以追溯到更早之前。
2008 年,透過將 cgroups 的資源管理能力和 Linux Namespace 的檢視隔離能力組合在一起,LXC(Linux Container)這樣的完整的容器技術出現在了 Linux 核心當中。當然,在這之前的虛擬機器的概念此處就不贅述了,李道兵介紹道,LXC 比虛擬機器輕量很多,但可以達到大部分虛擬機器的效果,隔離性和安全性卻不夠好。
在這之後,Docker 專案的正式釋出是對雲原生領域產生深遠影響的重要事件。李道兵補充道,Docker 真正的成功在於 Docker Hub,也就是官方維護的公共倉庫,其記憶體儲了大量映象。其次就是構建映象的方法,Docker 構造映象的方法比其他的簡單很多,也能更輕鬆地利用其他人的已有成果。總之,Docker 的出現大幅降低了微服務的運維負擔,讓微服務能真正成為一個可以大面積推廣的技術。在服務拆分之後,組織就會出現服務治理的需求,包括服務發現、服務伸縮、日誌收集、問題定位等,隨即就出現了很多類似 Mesos、Kubernetes 的技術,做服務的方式由原來的用 Java 寫完後跑在 Tomcat 上演變成將服務部署在容器之上,再利用 Kubernetes 進行管理,開發者已經不需要操心伺服器的事情,這一系列由此產生的新理念可以稱之為“Cloud Native(雲原生)”。
不難看出,容器是雲原生得以落地的重要條件,但這背後的真正訴求則是開發者對服務治理和去運維化的需求,可以認為在雲原生時代,系統運維這個角色可能完全消失掉,因為不需要操心伺服器,自然就無運維,容器映象可以直接將一個應用執行所需的完整環境,即:整個作業系統的檔案系統全部打包進去,這才是容器得以大面積普及的原因。換句話說,這樣的服務交付方式才是開發者的真正訴求。

雲原生最佳實踐

正如開篇所言,現在談到雲原生實踐很難避開容器這個話題,同樣也很難避開Kubernetes(k8s),這就好像曾經的 Hadoop 是大資料領域的事實標準一樣,但 Kuberntes 的複雜性也是有目共睹的,李道兵表示:“我承認 Kubernetes 底層體系的重要性,但它的介面真的不夠簡單。相比較而言,早些年穀歌推出的 Google App Engine 反而是對未來很好的示範,但很可惜,由於種種原因(當時雲的概念還沒有起來、在 AppEngine 寫一個有狀態服務非常困難、對 AppEngine 的效能分析和最佳化困難等),Google App Engine 並沒有獲得很好的反響。但就這個層面來講,未來,我們應該可以得到比 Kubernetes 友好得多的介面。”
既然如此,為什麼 Kubernetes 頂著“複雜性”的帽子還可以發展得如此迅速呢?李道兵認為,首先,底層的複雜性是不可避免的,開發者只能在上層透過合適的抽象來簡化使用介面;其次,過去幾年採用 K8s 大都是技術好的團隊,他們能駕馭這種複雜性,同時還能從底層的靈活性中獲益。但最近幾年隨著 K8s 的更廣泛採用,這個問題就愈發嚴重了,也有很多專案在嘗試解決這個問題。
那麼,K8s 是否會被新的框架取代呢?李道兵認為這個問題可以類比為程式語言來看待,比如“Java 就足夠好到把所有程式語言都比下去嗎?”這也未必,當年,Java 確實好到足以淘汰 COBOL(現在依舊有一些企業在使用),但一旦 Java 被大面積採用,你淘汰 Java 就需要比 Java 好一個數量級的語言出現。所以,儘管出現了一些針對 Java 作出改進的語言,比如 Groovy、Scala 等,但仍然無法撬動 Java 在企業市場的佔有率,畢竟對於整個 IT 業界,做出決定更換程式語言是要耗費很多成本的。同理,Kubernetes 還是有非常多優點的,並且已被廣泛採納,所以要被取代其實很難。
如今,在 Kubernetes 上進行探索的大部分企業以技術見長的網際網路大廠為主,這些企業有動力也有能力選擇 Kubernetes,因為搞得定。但是,為了面向更加廣泛的使用者,Kubernetes 社群一直沒有停止在這個領域的持續探索,並已經取得一些關鍵性突破。因此,雲原生領域的核心技術其實是處在不斷的發展和變化之中,現在很難對最佳實踐給出定論。

京東雲的雲原生實踐

京東雲雖然是一個雲服務的提供者,但其內部也需要進行雲原生改造,比如京東雲提供的物件儲存服務,其下的數十個元件同樣有服務治理的需求。因此,京東雲在這個過程中有很多 Service Mesh 相關實踐,主要是透過 Service Mesh 的 sidecar 將原本需要寫在程式碼中的邏輯替換掉,而微服務改造和容器化可以認為在此之前已經陸續完成(如果對這部分感興趣,可以閱讀《專訪京東雲:願雲原生不再只有 Kubernetes》,本文不作為重點介紹)。
在 Service Mesh 方面,目前比較有代表性的開源工具就是 Istio。
京東雲的雲原生理念及 Serverless 最佳實踐
如上圖,Istio 的核心元件主要包括 Proxy 代理、Mixer 混合器、Pilot 引導、Citadel 堡壘和 Galley。其中,Proxy 代理的代理元件主要是 Envoy,用來攔截所有想攔截的流量;Mixer 混合器混合了各種策略以及後端資料採集或遙測系統的介面卡,實現了前端 Proxy 與後端系統的隔離與匯合;Pilot 引導提供了一系列 rules api,允許運維人員指定一系列高階的流量管理規則;Citadel 堡壘管理著叢集的金鑰和證照,是叢集的安全部門;Galley 主要是用來驗證使用者編寫的 Istio api 配置。
目前來看,Istio 並沒有太大的問題,但李道兵表示,Envoy 可能成為 Istio 發展的阻礙,Envoy 本身是用 C++ 編寫的,主要由核心團隊維護,社群參與度一般。Envoy 支援了多種呼叫機制,但仍然不能滿足部分工業界的需求(比如 Backup Request),而 Envoy 的複雜性又限制了使用者自行擴充套件,不排除未來 Envoy 會被更靈活的 Sidecar 元件替代掉。
除此之外,過去一段時間,京東雲在 Serverless 層面進行了大量實踐,這也是京東雲整體改造中非常重要的一個環節。

Serverless 實踐

2019 年,Serverless 被 Gartner 稱為最有潛力的雲端計算技術發展方向,並被賦予是必然性的發展趨勢。Serverless 從底層開始變革計算資源的形態,為軟體架構設計與應用服務部署帶來了新的設計思路。在行業內,對 Serverless 的解讀並沒有公認的準確定義,京東雲認為 Serverless 技術目前有三種實現:
  • 真正的無伺服器,就是所謂的函式計算 FaaS;
  • 類似京東雲的原生容器,容器直接呈現給使用者,並且背後不需要有虛擬機器來支援;
  • 應用比較廣泛的無伺服器,背後虛擬機器由雲廠商來提供,但是對使用者不可見,仍然是以虛擬機器的方式來提供容器。
目前,京東雲在 Serverless 還在開發中,完整的 Serverless 實踐需要包括如下幾個模組:
  • 負責提供計算能力的 FaaS
  • 負責提供通訊能力的 Queue Service 和 Notification Service
  • 負責提供持久化能力的 Serverless KV 和 Object Storage
  • 負責提供入口的 API Gateway
  • 負責提供編排能力的 Step Function
京東雲已經提供了 FaaS, Queue Service, Object Storage 和 API Gateway, 其他模組也會在近期陸續釋出。

FaaS

在 FaaS 層面,京東雲和 AWS 的 Lambda 以及 Azure 的 Function 類似,都是需要使用者提供一段程式碼,這段程式碼以 HTTP 的入口形式可以訪問。程式碼可以用 Java 等多種語言寫出,處理完使用者請求後給出一定反饋,整體程式碼的生存週期就是請求的處理過程。程式碼是由函式計算來提供包括 CPU、記憶體、語言平臺等執行環境,使用者完全不用關心程式碼執行在什麼地方。
當併發請求非常多時,平臺就會執行這段程式碼容器的多個副本,這樣就能做到:使用者無需預留計算資源,僅根據呼叫的時長、次數來付費。這種情況是目前為止計算資源能做到的最小化分配粒度。粒度越小時,越有可能填滿伺服器的計算能力,粒度越大,後期就可能有越多的計算能力被閒置。
李道兵表示,FaaS 的優勢和劣勢都很明顯,主要優勢包括:徹底的無運維、近乎無限的伸縮能力和零啟動成本。劣勢則包括:冷啟動比較慢,相對常規服務延時較高、壓力穩定時沒有成本優勢。不過這些劣勢並不是 FaaS 的本質造成的,而是可以解決掉的問題,在解決掉這些問題之後,FaaS 就能獲得更大的適用範圍和更遠大的前景。
現階段,FaaS 比較適合的應用場景主要有兩類:一是事件驅動型應用,比如 IoT、網頁遊戲等型別;二是實驗性專案,這類專案租用虛擬機器的成本比較高,而 FaaS 幾乎是零成本,不呼叫的情況下不會產生開銷。目前還有一個趨勢是逐步用 FaaS 取代 AppEngine。京東雲目前將 FaaS 應用在多媒體內容分析處理和 Serverless 後端服務兩個場景:
  • 透過物件儲存上傳事件可以觸發多個函式,完成實時圖片或檔案篩選、轉存、建立縮圖、轉換影片編碼等處理分析。透過事件觸發機制,您能夠快速部署複雜的應用與服務,構建一個彈性、可靠的後端系統。
  • 透過函式服務和 API 閘道器構建後端,以驗證和處理 API 請求。採用函式服務構建可靈活擴充架構,輕鬆創造豐富、個性化的應用程式體驗。
京東雲的雲原生理念及 Serverless 最佳實踐
如上,京東雲目前的 FaaS 主要支援 Python 2&3 和 Nodejs 6&8,這兩者是目前 FaaS 適用場景中使用較多的語言,而接下來也會陸續支援 Java 和 PHP 等程式語言,畢竟幾行程式碼就可以處理的事件通常開發者更願意用 Python 而不是 Java。籠統地說,可以透過 K8s 和 Docker 來實現的服務,也可以選擇用 FaaS 實現,但要認清楚 FaaS 的優劣。李道兵表示,FaaS 的冷啟動是業界目前在共同努力解決的問題,這個概念很好理解,就是指函式第一次呼叫時平臺部署函式例項的過程。
在本地呼叫函式時,響應基本是實時的,而云上的 FaaS 需要部署計算環境,這個過程的時間從數百毫秒到數秒不等,難於應對時延敏感型應用;此外,FaaS 的優勢是極度彈性伸縮,這讓其在呼叫量下降時會進行資源回收清理,下次呼叫時則又需要冷啟動,這個過程一直反覆存在於服務的整個生命週期中。
李道兵表示,京東雲在這方面進行了不少嘗試,主要可以分為兩部分:一是加快原生容器(下文將介紹這一概念)和雲硬碟的啟動速度,甚至說在雲硬碟載入之前先按需載入資料;二是預留部分例項,需要的時候再啟動,不過這未必適合所有場景,當 FaaS 執行在客戶的 VPC 中時,使用的是 VPC 中的資源,第二種方案暫時並不適用。
目前,業界也有一些方案,比如 Kata、Firecracker 對 qemu,虛擬機器映象做裁剪來加速虛擬機器的建立和啟動,但是效果並沒有那麼好。李道兵表示,虛擬機器啟動慢的問題並不是第一天出現,因此沒有那麼好解決,而容器的問題則是安全性不夠高,如果容器足夠安全,也不需要造虛擬機器了,直接物理機上執行可以節省不少時間,而原生容器算是平衡各種利弊後的一個不錯的嘗試。

佇列服務

根據瞭解,京東雲的佇列服務(Queue Service)是一項基於 Serverless 架構的全託管訊息佇列服務,它可以提供高可靠並且幾乎無限擴充套件的託管訊息佇列。
京東雲的雲原生理念及 Serverless 最佳實踐
如上圖是佇列服務的架構圖,主要分為底層分散式儲存、功能及解決方案、安全管理及使用者接入四層,其特點是毫秒級自動伸縮和無規格限制。在訊息型別上,標準佇列理論上無限制的 TPS 上限,最大努力的訊息排序以及至少一次訊息傳達;FIFO 佇列保證訊息的傳達順序與訊息傳送順序一致以及精確的一次性處理。主要的應用場景是如下兩種:
  • 非同步解耦,削峰填谷。上下游系統處理能力存在差距的時候,利用佇列作為資料的緩衝器,增加系統架構的可用性和可靠性,平滑處理峰值流量,解耦系統架構,避免對業務主流程的影響。
  • 效能擴充套件,容錯處理。由於佇列服務會解耦分離使用者應用的處理程式,因此對於有擴充套件需求的應用,可以輕鬆提高從佇列服務傳送或接收速率來增加使用者應用的處理能力,對於部分故障的模組可以從整個系統中摘除。

原生容器

原生容器與普通意義的容器還是有一些差別,通常容器會被認為是在 PaaS 層,由 PaaS 團隊負責,而原生容器在京東雲內部屬於 IaaS 團隊,這也可以看出原生容器與底層的關聯比較密切。簡單來說,可以將原生容器理解為普通容器和削薄後的虛擬機器的結合體。
如上文所言,容器的安全性和隔離性是很大的問題,一旦容器被入侵,入侵者很容易透過穿透容器到達下面的物理機,從而影響整個雲平臺上的使用者,雖然這也是老生常談的問題,但要想既保證效能和啟動時間不受影響,又達到更高的安全級別,這本身就是一件棘手的事情,常規的安全手法成本又太高,最好的方式是將虛擬機器隔離起來,透過這個彌補容器安全性上的不足,當容器被入侵時,入侵者不至於影響整個雲平臺的使用者。同時,原生容器對虛擬機器做了大幅簡化,資源損耗和啟動時間均有所降低,這就是所謂的原生容器的概念。坦白地說,使用者申請的每一個原生容器裡面跑的就是一個 Docker 或者 Pod。
在原生容器方面,京東的產品推出時,Kubernetes 還沒這麼流行。所以為了實現節點容量的無限大,是透過一個叫 virtual kubelet 的外掛讓 Kubernetes 叢集擁有一個虛擬節點。而如今,原生容器完全看使用者需求。如果是一次性的任務處理批次計算工作,這種方式非常有效,因為虛擬節點可能會在某些方面不能實現 Kubernetes 所有的介面,某些特殊應用可能需要一定的適配工作,例如 daemonset。京東雲正在考慮把原生容器執行的節點暴露出來,並提供和現在 Kubernetes 所有介面相容的一個應用。而在 Docker 方面,京東雲希望能向輕量化發展,可以隨時建立、隨時銷燬,並且可以隨時隨地建立更多的副本。
此外,京東雲也希望能將原生容器和 Kubernetes 透過比較緊密的方式結合在一起。比如在 Kubernetes 裡的 Kata Container,其在 Kubernetes 裡使用了更安全的容器;還有 Rancher Labs 基於 K8s 推出的輕量級的 Kubernetes 發行版 K3s,可以滿足在邊緣計算環境中執行在記憶體和處理能力受限的小型、易於管理的 Kubernetes 叢集日益增長的需求。

結束語

面向未來,京東雲的整體目標還是希望在雲原生領域有更多投入。李道兵表示,具體來說,在 Service Mesh 方面達到更好的透視遙感能力,如果是較大呼叫量的分析需要很好地分析服務之間的關係以及出現瓶頸和延遲的原因,甚至在開發者不需要增加程式碼的情況下就可以享受這些功能。
在 Serverless 層面,需要進一步最佳化 FaaS 的冷啟動能力,大幅縮短啟動時間至毫秒級別,並儘可能降低延遲,因為現在需要過的層和轉換的協議還比較多,這部分消耗的時間需要儘量減少,並增加更多語言支援,將介面簡化到接近當年 Google App Engine 的樣子。
京東雲的雲原生理念及 Serverless 最佳實踐


歡迎點選“ 京東雲 ”瞭解更多精彩內容

京東雲的雲原生理念及 Serverless 最佳實踐
京東雲的雲原生理念及 Serverless 最佳實踐


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69912185/viewspace-2655382/,如需轉載,請註明出處,否則將追究法律責任。

相關文章