成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

餓了么容器平臺的演進,看這篇文章就夠了!

原創
開發 架構
眾所周知,微服務和容器本身結合較為密切,隨著云服務的普及,它們從企業機房內部的服務器上逐漸延伸到了各種云服務的場景中。

【51CTO.com原創稿件】眾所周知,微服務和容器本身結合較為密切,隨著云服務的普及,它們從企業機房內部的服務器上逐漸延伸到了各種云服務的場景中。

[[240438]]

因此面對常見的混合云服務,我們該如何用基于容器的模式來進行管理呢?

2018 年 5 月 18-19 日,由 51CTO 主辦的全球軟件與運維技術峰會在北京召開。

在“微服務架構設計”分論壇上,來自餓了么計算力交付部門的資深工程師李健帶來了主題為《餓了么基于容器的混合云實踐》的精彩演講。

本文將按照如下四個部分展開分享:

  • 計算力交付
  • 技術選型
  • 基于 Kubernetes 的“算力外賣”
  • Kubernetes 的擴展方案

隨著業務的快速增長,對應的資源規模也在迅速增長之中。而這種增長直接導致了服務器類型的增多、管理任務的加劇、和交付需求的多樣性。

比如在某些場景下,我們需要在交付的服務器上,預安裝某種應用;而有些時候,我們需要交付出一個“有依賴性”的服務、或是一組服務的集合。

計算力交付

盡管我們所面對的物理資源和虛擬機資源的數量是龐大的,但我們運維人員卻是有限的,無法做到無限量地擴張。因此我們需要將物理資源統一抽象出來,從而輸出給開發人員。

而這種標準化式的抽象,能夠給企業帶來兩大好處:極大地減少了成本和增加了服務器管理上的運能。同時,這種統一抽象催生了我們計算力交付部門的出現。

具體而言,平時我們所交付的服務器,包括以云服務 IaaS 形式的交付,實際上與應用的交付,如 SaaS 形式是一樣的。

在如今虛擬化的云時代,我們通過簡單的命令輸入,就能為某個文件系統準備好 CentOS 或 Ubuntu 操作系統。因此,服務器實際上也成為了一種軟件服務、或是一種 App。

通過以抽象的方式對服務器和應用采取標準化,我們可以把所有的物理資源抽象出來,形成一種具有管控能力的計算力,從而達到對于系統的協調能力。可以說,一切交付的行為都屬于應用。

因此我們計算力交付的關鍵也就落腳在了對應用的管理之上,這同時也是我們關注度的轉變。

容器技術的原型始于七十年代末,但直到 2013 年 Docker 的問世,容器才成為了主流的技術。

Docker 對于容器技術的最大貢獻在于:通過真正地面向應用的方式,它具有跨平臺的可移植特性,將所有的服務,統一以 Image 打包的方式來進行應用的交付。

另外,它是應用的一種封裝標準。在此標準之上,我們可以讓應用運行在任何一個平臺之中。

同時,這也進一步促進了自動化運維、AIOps 和大數據等應用的發展。因此,它在降低人力成本的同時,也提高了資源的利用率。

我們將計算力交付分為三大類:

  • 客戶應用的部署。在接到服務請求后,我們會著手部署,并讓服務順利運行起來。
  • 標準服務的一鍵交付。例如某部門的大數據業務需要有一套環境,該環境里所包含的許多種服務,相互之間默認是相互隔離的,但同時也要保證部分服務能夠相互聯系。

那么我們就需要準備好一些可復制的標準化服務模板,以保證就算在復雜的 SOA 體系中,也能實現應用服務的順暢發現。

  • 服務器的交付。如前所述,服務器交付的標準化,正是我們計算力交付部門能力的一種體現。

技術選型

如今,可選的容器技術有很多,包括 Kubernetes、Swarm、和 AWSECS 等,其中 Kubernetes 比較熱門。

因此我們在選型時,需要考慮如下因素:

  • Kubernetes 項目已成為了容器編排的事實標準。由于大家都在普遍使用,如果碰到了問題,可以到社區里去搜尋答案。這無形中帶來了成本下降的優勢。
  • 實際需求情況和技術的契合度。
  • 擴展性與生態發展。一些由大公司的采用作為背書的技術,一般都有著強大的后臺支持和一定的前瞻性,同時也方便建立起一定的生態體系。

基于 Kubernetes 的“算力外賣”

我們開發人員平時對于應用服務類型的需求和本公司所做的點餐服務是極其類似的。上圖中的綠色 Box,實際上就像我們抽象出的一個外賣盒。

其中每一種服務相互之間的調用,都是通過 DomainName 去實現的。而且這些 Box 具有復制性,我們可以依據模板來創建出多個 Box。

而每個 Box 內部在調用不同的服務時,它的域名在系統中是唯一的。因此,它們可以橫跨不同的環境進行調用,從而減少了開發人員的工作量。

過去,在服務啟動的時候,系統會自動生成一個網絡標識,而當 IP 地址或域名發生變化時,他們不得不進行相應的配置修改。

如今,只要容器環境和相應的應用運行起來了,不同服務之間就能夠根據唯一的網絡標識實現相互調用。

在具體實現中,我們利用 Kubernetes 做出了一個底層的容器引擎。在其中的每個 Unit 里,都會包括有 Domain 和 Pod。而且每個 Unit 都有自己的副本,以實現負載均衡。

我們通過使用 Systemd,這種啟動方式去了解各個服務之間的相互依賴關系。

它通過啟動樹,在 Box 中實現了同樣的功能,以保證 Box 在啟動的時候,能夠根據我們既定的依賴描述,按照先后次序將應用啟動運行起來。

雖然從技術發展的角度來說,服務之間不應該存在過多的依賴關系,但是由于我們部門是面向業務部門提供服務的,所以我們需要做的只是去推動標準化,從而去兼容開發的習慣和他們當前的項目。

如上圖所示,每個 Unit 中還有一個 Hook,它可以協助服務的啟/停與初始化。例如,在某些服務完成了之后,它會去調用另外一個 Pod 進行初始化。

當然,我們也涉及到對公共服務的使用。例如,Box1 和 Box2 都要通過一個公共服務來傳遞數據。而公共服務的唯一性網絡 ID,則可能因為重啟等外部因素而發生變化。

因此為了保持一致性,我們嘗試著將上述提到的內部標識轉換為外部標識。實際上,我們的內部標識是永遠不變的,而外面關系則需要通過服務發現的機制,與內部服務動態建立關聯。

這樣一來,內部的服務就不必考慮配置變更、以及服務發現等問題了。上圖就是我們對于外賣服務方式的一種最簡單的抽象。

眾所周知,Kubernetes 的服務主要依賴于 Etcd 的啟動,但是 Etcd 本身在 Kubernetes 的應用場景下并不能支持大量的業務。

因此,考慮到了業務量的逐漸增大和對于服務的穩定性要求,我們需要對 Kubernetes 盡量進行拆分。

在拆分的過程中,我們將原來單個機房網絡中的資源池拆分成三到四個 Kubernetes 集群。

在拆分完成之后,我們曾碰到了一個問題:由于拆分得太細,集群資源出現了利用率不均的情況:有的集群負載不夠、而有的集群則負載過多。

因此,我們運用不同的 Etcd 對應不同的 Kubernetes 集群,通過調度的方式,讓服務能夠在集群之間飄移,從而既解決了資源效率的問題,又解決了可靠性的問題。

在上述簡單的結構中,除了黃色的部分,其他都是 Kubernetes 原生的組件,包括藍色部分里具有調度 Pod 功能的調度器(Scheduler)。

我們根據上述不同 Node 層的屬性和服務信息進行判斷,以確定要調用哪個集群。

由于我們采取的是兩層調度的方式,因此在調到第一層的時候,我們并沒有該集群的實時信息,也無法知道此集群把服務調到了何處。

對此,我們自行開發了一個 Scheduler(如黃色部分所示)。另外,我們還開發了一個類似于 Kubernetes 的 APIServer 服務。

可見,我們的目的就在于:以外圍的方式去擴展 Kubernetes 集群,而不是去改動 Kubernetes 本身。

即:在 Kubernetes 的外圍,增加了一層 APIServer 和 Scheduler。此舉的直接好處體現在:我們節約了在框架上的開發與維護成本。

下面我們來具體看看真實的容器環境:

  • 如前所述,我們是基于 Kubernetes 的。
  • 在網絡上我們使用的是阿里云的虛擬機。如果規模小的話,我們會用 Vroute 的方式;如果是自建機房的話,我們就使用 LinuxBridge 的方式。同時,我們的 Storage Driver 用的是 Overlay2。
  • 在操作系統方面,我們都使用的是 Centos7-3.10.0-693。
  • 在 Docker 的版本上,我們用的是 17.06。值得補充的是:如今社區里傳聞該版本即將被停止維護了,因此我們近期會著手升級。

Registry

說到 Registry,在以前規模小的時候并不存在問題。但是如今我們的規模已大到橫跨幾個機房。

因此我們就需要對 Registry 傳過來的數據進行同步,并“雙寫”到 OSS(Object Storage Service)和 Ceph(一個開源的分布式存儲系統,提供對象存儲、塊存儲和文件系統的存儲機制)之中了。

由于我們在自己的物理機房中都有 Ceph,因此在下載時可以遵循就近下載的原則,而不必跨出本機房。

此舉的好處就在于:降低了在機房之間傳輸所帶來的帶寬瓶頸問題。

那么我們為什么要做同步呢?由于我們的服務一旦被發布出去,它們就會自動去進行異步部署。

但是,有些機房里可能根本沒有所需的鏡像,那么它們在進行“拉取”操作時就會報錯。

因此基于此方面的考慮,我們采用了“同步雙寫”模式,并增加了認證的環節。

想必大家都知道:Registry 在長時間運行后,鏡像里會有越來越多的 Blob。

我們既可以自行清理,也可以根據官方提供的方式來清理,但是清理的時間一般都會非常長。

因此清理工作會帶來服務的運維性中斷,這對于一般公司來說是無法接受的。

對此,我們想到一種“Bucket 輪轉”的方法。由于在 CI(持續集成)的過程中,我們會產生大量的鏡像,因此我們將鏡像以兩個季度為一個保存周期進行劃分,即:

  • 為第一個季度新建一個 Bucket,用來存儲鏡像。
  • 在第二個季度時,將新的鏡像產生到第二個 Bucket 之中。
  • 等到了第三個季度,我們就將第一個 Bucket 里的鏡像清理掉,以存入新的鏡像。

以此類推,通過該方法,我們就能夠限制鏡像,不至于無限地增長下去。

我們當前的 8 臺 Registry 所服務的 Docker 對象具有成千上萬的體量規模。

如果 Registry 一旦出現問題,我們就需要迅速地能夠定位到問題,因此,對于 Registry 采取相關的監控是非常必要的。

同時,我們也需要通過監控來實時了解系統的使用程度,以便做出必要的擴容。

在實現方式上,我們實際上只是稍微加入了一些自己寫的程序,而整體上仍保留著與其他程序的解耦關系。

如圖所示,我們通過上傳、下載的速度,包括 Blob 的數量等監控指標,能夠實時地跟蹤 Registry 的運行狀態。 

Docker

我們使用 Docker syslog driver 將采集到的用戶進程輸出到 ELK 之中進行呈現。不過在日志量過于頻繁的時候,ELK 會出現毫秒級別的亂序。

這樣的亂序會給業務部門帶來無法進行問題排查的困難。因此,我們改動了 Docker 的相關代碼,給每一條日志都人為增加一個遞增的序列號。

針對一些可靠性要求較高的 Log,我們選擇了 TCP 模式。但是在 TCP 模式下,如果某個日志被輸出到一個服務時,其接收服務的 Socket 由于滿載而“夯住”了。

那么該容器就無法繼續,其 Docker ps 命令也就只能停在那兒了。另外就算 TCP 模式開啟了,但是其接收日志 TCPServer 尚未啟動也是無濟于事的。

由此可見,在面對一些具體使用中的問題時,我們的需求與開源項目本身所能提供的服務還是有一定距離的。任何一個開源項目在企業落地時,都不可能是完美的。

開源項目往往提供的是標準化的服務,而我們的需求卻經常是根據自己的具體場景而定制化的。

我們企業的軟件環境,都是根據自身環境一點、一點地長出來的,因此存在差異性是必然的。

我們不可能讓開源軟件為我們而改變,只能通過修改程序,讓開源軟件來適應我們當前的軟件狀態與環境,進而解決各種具體的問題。

上圖是 Docker 的一些監控,它能夠幫助我們發現各種問題、Bug、以及“夯住”的地方。

Init 進程

在將傳統的業務進行容器化轉變的過程中,我們針對容器定制并改進了 Init 進程。

該 Init 進程能夠切換 Image 基礎層管理的一些目錄和環境變量,通過也可以替換基礎配置文件的宏代換。

對于一些遷移過來的服務,其本身就曾帶有配置項,它們通常使用環境變量來讀取配置信息。那么這對于我們將其修改成容器的工作,就無形中增加了成本。

因此我們所提供的方法是:雖然變量被寫在了配置里,但是我們能夠根據容器的環境變量設置,自動去替換服務寫“死”的配置。

Init 進程的這種方法對于在容器尚未啟動,且不知道服務的 IP 地址時尤為有用。

對于容器的管理,我們也啟動了 Command,來持續監聽進程的狀態,以避免僵尸進程的出現。

另外,由于我們公司有著內部的 SOA 體系,在 Docker 產生停止信號之后,需要將流量從公司的整個集群里摘除掉。

因此,我們通過截獲信息,做到了在相關的流量入口予以服務的摘除動作。

同時,我們還通過傳遞停止信號給應用進程,以完成針對軟件的各種掃尾清理操作,進而實現了對傳統業務予以容器化的平滑過渡。

Kubernetes 資源管理擴展

下面通過案例來看看,我們是如何通過擴展來滿足業務需求的。

我們都知道,Kubernetes 的 APIServer 是較為核心的組件,它使得所有的資源都可以被描述和配置。這與 Linux“一切皆文件”的哲學具有異曲同工之妙。

Kubernetes 集群將所有的操作,包括監控和其他資源,都通過讀文件的方式來掌握服務的狀態,并通過寫文件的方式來修改服務的狀態。

借用這種方式,我們相繼開發了不同的組件和 APIServer 的接口,并以 Restful 的接口形式對服務實現了微服務化。

在實際部署中,雖然我們并沒有用到 Kubernetes Proxy,但是這樣反而降低了 APIServer 的負載。

當然如果需要的話,我們完全可以按需加載與部署,從而保證并增強系統整體的擴展性。

Kubernetes APIServer

上圖直觀地展示了 APIServer 的簡單內部結構。所有的資源實際上都要被放入 Etcd 之中。

同時,每一種資源都有一個 InternalObject,它對應著 Etcd 里的一些存儲類 Key/Value,這樣保證了每個對象的唯一性。

當有外面請求來訪問服務時,則需要通過 ExternalObject 和 InternalObject 進行轉換才能實現。

例如:我們可能使用不同版本的 API 進行程序開發,而此時出現了需求變更,需要我們增加一個字段。

而實際上該字段可能已經存在于 InternalObject 之中了,那么我們只需經過一些處理便可直接生成該字段。

可見,我們真正要去實現的只是 ExternalObject,而沒必要去改動 InternalObject。

如此,我們在不修改存儲的基礎上,盡量做到了服務與存儲之間的解耦,以更好地應對外界的各種變化。

當然,這同時也是 Kubernetes APIServer 里對象服務的一個過程。

與此同時,我們也將部分 API 劃歸到了一個 APIGroup 之中。在同一個 APIGroup 里,不同的資源相互之間是解耦、并行的,我們能夠以添加接口的方式進行資源的擴展。

而上述提到的兩個對象之間的轉換,以及類型的注冊,都是在圖中的 Scheme 里面完成的。

如果大家想自己做 APIServer 的話,谷歌官方就擁有該項目的對應方案,并提供了專門的技術支持。如果您感興趣的話,可以參考圖中下方對應的 Github 項目的網址。

另外,谷歌還提供了自動生成代碼的工具。相應地,我們在開發的過程中也做了一個直接通過對象來生成數據庫所有相關操作的小工具,它節約了我們大量的時間。

Kubernetes 落地

最后和大家分享一下,我們在 Kubernetes 落地過程中所遇到的一些問題:

  • Pod 重啟方式。由于 Pod 所謂的重啟實際上是新建一個 Pod,并且放棄以前那個舊的,因此這對于我們的企業環境來說是無法接受的。
  • Kubernetes 無法限制容器文件系統大小。有時候程序員在寫業務代碼時,由于不慎,會導致日志文件在一天之內激增 100 多 GB,從而占滿了磁盤并導致報警。

然而我們發現,在 Kubernetes 里好像并沒有相關的屬性去限制文件系統的大小,因此我們不得不對它進行了略微的修改。

  • DNS 改造。您可以采用自己的 DNS,也可以使用 Kubernetes 的 DNS。不過我們在使用 Kubernetes DNS 之前,專門花時間對它進行了定制與改造。
  • Memory.kmem.slabinfo。當我們創建容器到了一定程度時,會發現容器再怎么也無法被創建了。我們雖然嘗試過釋放容器,但是發現還是受到了內存已滿的限制。

經過分析,我們發現:由于我們使用的 Kernel 版本為 3,而 Kubelet 激活開啟了 cgroupkernel-memory 這一測試屬性特性,同時 Centos7-3.10.0-693 的 Kernel 3 對于該特性支持并不好,因此耗光了所有的內存。

[[240444]]

李健,餓了么 計算力交付部負責人,擁有多年豐富的容器系統建設經驗,并推進了餓了么平臺容器化;擅長將容器的敏捷性和標準化進行企業級落地,是企業內部多個基于容器的云計算項目的開發負責人。熱愛開源,熱衷于用開源項目解決企業問題。

【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】

責任編輯:武曉燕 來源: 51CTO技術棧
相關推薦

2017-03-30 22:41:55

虛擬化操作系統軟件

2022-05-27 08:18:00

HashMapHash哈希表

2021-11-10 07:47:48

Traefik邊緣網關

2019-09-25 09:17:43

物聯網技術信息安全

2019-10-31 09:48:53

MySQL數據庫事務

2024-03-26 00:00:06

RedisZSet排行榜

2018-10-31 17:22:25

AI人工智能芯片

2020-10-13 07:44:40

緩存雪崩 穿透

2024-02-28 08:59:47

2022-08-26 05:22:21

RabbitMQ架構

2017-12-12 12:53:09

2017-03-10 21:04:04

Android適配

2017-03-07 15:35:26

Android適配 界面

2021-04-09 10:03:12

大數據exactly-onc

2021-09-30 07:59:06

zookeeper一致性算法CAP

2019-08-16 09:41:56

UDP協議TCP

2019-07-10 15:15:23

JVM虛擬機Java

2018-07-09 09:30:06

架構師產品經理互聯網

2018-10-12 09:42:00

分布式鎖 Java多線

2021-05-07 07:52:51

Java并發編程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91精品国产自产精品男人的天堂 | 国产色婷婷| 欧美成ee人免费视频 | 91视频进入| 精品国产精品国产偷麻豆 | 一本色道精品久久一区二区三区 | 久久久久久久久久久爱 | 国产一区二区三区在线 | 欧美日本一区二区 | 亚洲精品麻豆 | 99reav | 三级视频在线观看电影 | 欧美精品一区二区三区在线 | 一本色道久久综合亚洲精品高清 | 久久精品手机视频 | 亚洲人成人一区二区在线观看 | 免费在线观看黄色av | 在线免费观看成人 | 狠狠色狠狠色综合系列 | 精品一区二区久久久久久久网精 | 日韩影院一区 | 小h片免费观看久久久久 | 欧美精品91爱爱 | 日韩免费一区二区 | 欧洲精品在线观看 | 午夜电影网站 | 国产精品视频网址 | 成人午夜电影网 | 国产人久久人人人人爽 | 老司机深夜福利网站 | 国产精品一区二区av | 国产高清精品一区二区三区 | 亚洲美女一区二区三区 | 国产视频亚洲视频 | 久久久毛片 | 久久精品一区二区三区四区 | 久久日韩精品一区二区三区 | 午夜日韩 | 国产精品18久久久 | 天天草天天干天天 | 国产精品久久久久久 |