1. 程式人生 > >京東618:容器技法日趨嫻熟,60%業務已切換至Kubernetes_Kubernetes中文社群

京東618:容器技法日趨嫻熟,60%業務已切換至Kubernetes_Kubernetes中文社群

容器技術火遍技術界,很多公司包括傳統行業企業都已經從觀望者轉變為採用者。作為最早期採用容器技術的一批先鋒者,京東從 2015 年的 9 千多例項擴大到如今容器作為業務上線預設選項,支撐全部業務執行以及中介軟體、資料庫等。此外,在經歷了從 OpenStack 到 Kubernetes 的遷移轉變之後,京東容器引擎平臺已經從 1.0 迭代到 2.0 版本,並且於今年陸續開源數個專案。

羅馬不是一天建成的。

積累如此久並且支撐過 618 大促的京東容器技術是怎樣的?有哪些革新又有哪些值得業界學習呢?已經開源的專案是怎樣的呢?

容器技術整體概況

今年隨著京東業務的飛速發展,京東容器數量上也對應迅速增加。不僅在去年完成京東業務全面執行在 JDOS 容器之上,並且在資料庫,中介軟體等系統也全面容器化。同時,在這一年,京東上線了 JDOS 2.0 系統,開始了從 OpenStack 向 Kubernetes 的遷移。截止到 6 月 7 日,已經有 60% 的業務執行在了 JDOS 2.0 平臺中。
此外不得不提及發生的主要變化:業務系統全面基於容器映象全量上線釋出;全面使用叢集編排;在生產環境嘗試和執行搶佔式排程,並自研單層單體全域性排程器 SchedulerX;讓業務系統與硬體解耦與資源完全解耦,海量資源,從容大促。

自研單層單體全域性排程器

正如上文所述,京東在生產環境嘗試和執行搶佔式排程,並自研單層單體全域性排程器 SchedulerX。
SchedulerX 屬於 JDOS 彈性計算專案,主要目的是從更高的層面來加強計算資源排程,以提供服務更強的彈性計算能力,提升資料中心資源利用率。

JDOS2.0 主要通過以下三個維度對業務進行優先順序分類歸集,並實施搶佔式排程。

  • 從業務負載層面來對業務分類,根據業務是長時間執行的任務 (long time running) 還是離線計算任務 (offline),採用不同的資源佔用優先順序和排程模式。
  • 從業務高峰時間段會對各個業務進行歸類,例如區分是否白天高峰期還是夜間高峰期,將任務進行混合排程,實現資源的錯峰利用。
  • 從資源區域層面對業務分類,例如 GPU 資源、CPU 資源、SSD 資源等。根據業務對於資源的實際需求進行排程。

在保證各個業務 80% 的資源的情況下,20% 的資源在不同時間段可以互相搶佔借用。(此比例可以根據實際運營進行調配。例如 618、雙 11 大促時,則不允許業務相互搶佔,保證資源足夠)
在當前沒有空閒資源的情況下,JDOS 會根據每個機器上執行的業務的分類對機器打分,如果該機器的分數較低,那麼搶佔就會發生,低優先順序的業務首先會被驅逐 (Eviction) 搶佔。被搶佔的作業重新回到 PENDING 佇列裡等待重新排程。

SchedulerX 確保關鍵業務不會由於資源不足而停止執行,也會重新排程其他業務使其獲得更好的安置。

OpenStack No, Kubernetes Yes!

應用容器化遇到的瓶頸

JDOS 1.0 解決了應用容器化的問題,但是依然存在很多不足。

首先是編譯打包、自動部署等工具脫胎於物理機時代,與容器的開箱即用理念格格不入。容器啟動之後仍然需要配套工具系統為其分發配置、部署應用等等。應用啟動的速度受到了制約。其次線上線下環境仍然存在不一致的情況,應用執行的操作環境,依賴的軟體棧線上下自測時仍然需要進行單獨搭建。線上線下環境不一致也造成了一些線上問題難於線上下復現。更無法達到映象的“一次構建,隨處執行”的理想狀態。

再次,JDOS 1.0 時代的容器體量太重,應用需要依賴工具系統進行部署,導致業務的遷移仍然需要工具系統人工運維去實現,難以在通用的平臺層實現靈活的擴容縮容與高可用。另外,容器的排程方式較為單一,只能簡單根據物理機剩餘資源是否滿足要求來進行篩選排程。在提升應用的效能和平臺的使用率方面存在天花板。

OpenStack PK Kubernetes

Kubernetes 方案與 OpenStack 方案相比,架構更為簡潔。OpenStack 整體運營成本較高,因為牽涉多個專案,每個專案各自有多個不同的元件,元件之間通過 RPC(一般使用 MQ) 進行通訊。為提高可用性和效能,還需要考慮各個元件的擴充套件和備份等。這些都加劇了整體方案的複雜性。問題的排查和定位難度也相應提升,對於運維人員的要求也相應提高。

與之相比,Kubernetes 的元件較少,功能清晰。其核心理念 (對於資源,任務的理解),靈活的設計 (標籤) 和宣告式的 API 是對 Google 多年來 borg 系統的最好總結。而其提供的豐富的功能,使得京東可以投入更多精力在平臺的整個生態上,比如網路效能的提升、容器的精準排程上,而不是容器管理平臺本身。尤其是,副本控制的功能受到了業務線上應用運維工程師的追捧,應用的擴容縮容和高可用實現了秒級完成。

改造之路

有了 1.0 的大規模穩定運營作為基礎,業務對於使用容器已經給予了相當的信任和支援。但是平臺化的容器和基礎設施化的容器對於應用的要求也不盡相同。比如,平臺化的應用容器IP 並不是固定的,因為當一個容器失效,平臺會自動啟動另一個容器來替代。新的容器 IP 可能與原 IP 不同。這就要求服務發現不能再以容器 IP 作為主要標識,而是需要採用域名,負載均衡或者服務自注冊等方式。因此,在 JDOS 2.0 推廣過程中,京東也推動了業務的微服務化,服務框架的升級改造等。

在近兩年隨著大資料、人工智慧等研發規模的擴大,消耗的計算資源也隨之增大。因此, 京東將大資料、深度學習等離線計算服務也遷移進入 JDOS 2.0。目前是主要採用單獨劃分區域的方式,各自的服務仍然使用相對獨立的計算資源,但是已經納入 JDOS 2.0 平臺進行統一管理。未來,京東將在此基礎上,通過排程將離線計算服務在叢集資源充足 (如夜晚) 時給予計算資源擴充,提高計算的效率。

研發成果,兩大開源專案

分散式高效能 DNS 專案

JDOS 是如何支援業務的彈性伸縮的?

對於業務的擴充套件,直接通過調整副本數,橫向擴充容器的例項個數。業務如果是 L4/L7 型別的, 使用一個負載均衡來進行流量的分導。 負載均衡專案 ContainerLB 是京東自研的一套基於 DPDK 實現的高效能 L4 負載均衡服務,主要負責 JDOS2.0 的 service 中 LoadBalancer 的實現。

而與 ContainerLB 專案非常密切的還有分散式高效能 DNS 專案 ContainerDNS。(https://github.com/ipdcode/skydns) 為容器提供了內部的 DNS 解析服務。業務如果是微服務型別京東叫 JSF,即需要在 JSF 上進行服務註冊與發現的型別,京東則是在容器擴充後,通過服務中間層監聽到容器已經啟動成功,則對應 Notify JSF。
ContainerDNS,作為京東商城軟體定義資料中心的關鍵基礎服務之一,具有以下特點:

  • 高可用
  • 支援自動發現服務域名
  • 支援後端 IP+Port,以及 URL 探活
  • 易於維護和橫向動態擴充套件

ContainerDNS 包括四大元件 DNS server、service to DNS 、user API 、IP status check。這四個元件通過 etcd 資料庫叢集結合在一起,彼此獨立,降低了耦合性,每個模組可以單獨部署。DNS server 用於提供 DNS 查詢服務的主體,目前支援了大部分常用的查詢型別(A、AAAA、SRV、NS、TXT、MX、CNAME 等)。service to DNS 元件是 k8s 叢集與 DNS server 的中間環節,會實時監控 k8s 叢集的服務的建立,將服務轉化為域名資訊,存入 etcd 資料庫中。

user API 元件提供 restful api,使用者可以建立自己的域名資訊,資料同樣保持到 etcd 資料庫中。IP status check 模組用於對系統中域名所對應的 ip 做探活處理,資料狀態也會存入到 etcd 資料庫中。如果某一個域名對應的某一個 ip 地址不能對外提供服務,DNS server 會在查詢這個域名的時候,將這個不能提供服務的 ip 地址自動過濾掉。(關於 ContainerDNS 的更多內容詳見本系列的另外一篇文章《京東商城分散式智慧容器 DNS 實踐》)。

分散式共享儲存 ContainerFS 專案

JDOS 是如何支援有狀態服務和無狀態服務的?

無狀態業務的支援相對容易一些,可以直接通過排程自動調整副本數來實現服務的彈性伸縮。對於有狀態的業務,原生的 Kubernetes 有 StatefulSet 進行支援,但是 StatefulSet 需要容器一個個啟動, 另外社群在這個方面開發進度緩慢。 因此京東選擇了自己定製 Kubernetes 進行支援,主要是為本集 (RC/RS/deployment) 提供了 IP 保持不變和儲存自動遷移的功能來進行支援。

通過對於每個副本集維護一個小的 IP 池。當副本數調整時,也對應增加或者減少 IP 池中的IP 的數量。副本集中的容器建立時,則使用這個 IP 池中的 IP 進行建立;容器刪除時,則將IP 返回到副本集的 IP 池中。

儲存也是類似, 對於一個副本集有一個對應的持久化儲存 (persistent volume) 的集合。當副本集中的容器建立時,則使用這個 PV 集合中的一個 PV 進行繫結核儲存掛載。容器刪除時,則對應進行解除安裝和解除繫結。

針對於容器的儲存, 京東沒有選用社群已有的 glusterfs 等方案。而是自研一套分散式共享儲存 ContainerFS (https://github.com/ipdcode/ContainerFS) 的專案來專門提供容器的儲存。
Container File System (簡稱 ContainerFS)是為 JDOS2.0 系統針對性開發的一個分散式檔案系統,同時適用於原生 Kubernetes 叢集以及其他應用場景。

ContainerFS 的核心概念是:

a volume = a metadata table + multiple block groups

ContainerFS 的架構圖如下:

ContainerFS 的產品特性:

  • 無縫整合 : 支援標準的檔案訪問協議,支援 fuse 掛載,業務應用無需任何修改即可無縫使用
  • 共享訪問:共享訪問幫助多個業務應用獲得相同的資料來源
  • 彈性伸縮 : 可滿足業務增長對檔案儲存的容量訴求
  • 線性擴充套件的效能:線性擴充套件的儲存效能,非常適合資料吞吐型的應用

ContainerFS 典型應用:

做為 JDOS2.0 的資料儲存引擎,ContainerFS 提供了獨享、共享等型別的 volume,並通過 PV 機制掛載給 POD 或者容器使用。

使用效果:

目前 ContainerDNS, ContainerFS 已經開源,ContainerLB 會近期在 GitHub 上開源。

寫在最後

為什麼要將京東底層技術開源呢?主要兩個方面原因:

在底層技術方面,開源是大勢所趨。Google 的 borg 系統在過去十餘年間一直處於保密狀態,但是現在不但公開了,而且利用起核心思想,孵化出了 Kubernetes 專案。而 Kubernetes 專案一經發布,也立即受到了熱捧。同時,社群的完善也為 Kubernetes 和 Google 的 borg 提供了更為有益的建議和幫助。當然,不僅僅是 Google,CoreOS、OpenStack、Docker 等等公司和專案的開源大熱也說明了這一趨勢。

在容器平臺實踐路上,京東是走的比較早也是比較堅定的。在實踐過程中有很多理解和技術視野。比如我們認為容器技術本質是 linux kernel 技術,容器技術需要資料中心底層基礎軟體全力配合,如分散式域名解析,高效能負載均衡,分散式共享儲存,精確授時等等。因此京東在這方面不希望閉門造車,而是能夠更多的同業界來分享我們的經驗。一方面,為許多底層技術還在摸索中的業內同仁提供一點借鑑和幫助,另一方面,也是希望獲取業界的指導,提升京東的基礎平臺系統和技術思路。

作者介紹

鮑永成,京東商城 基礎平臺部技術總監。2013 年加入京東,負責京東容器叢集平臺(JDOS)研發,帶領團隊完成京東容器大規模落地戰略專案,有效承載京東全部業務系統和 80% 資料庫,特別在大促期間 scale up 秒級彈性應對高峰流量。目前聚焦在京東容器叢集 JDOS 2.0 以及京東敏捷智慧資料中心研發。服務過土豆網(TUDOU.COM),思科(CRDC)等,在分散式、虛擬化、容器、資料中心建設有豐富的實踐經驗。