Borg、Omega 和 Kubernetes:谷歌十幾年來從這三個容器管理系統中獲得的經驗教訓

從2000年以來,谷歌基於容器研發三個容器管理系統,分別是Borg、Omega和Kubernetes。這篇論文由這三個容器集羣管理系統終年開發維護的谷歌工程師Brendan Burns、Brian Grant、David Oppenheimer、Eric Brewer和John Wilkes於近日發表,闡述了谷歌從Borg到Kubernetes這個旅程中所得到的知識和經驗教訓。前端

儘管對軟件容器普遍傳播的興趣是最近的現象,但在谷歌咱們大規模使用Linux容器已經有10多年了,並且期間咱們建了三種不一樣的容器管理系統。每個系統都受以前的系統影響頗深,儘管它們的誕生是出於不一樣緣由。這篇文章描述了咱們在研發和使用它們的過程當中獲得的經驗教訓。程序員

第一個在谷歌被開發出來的統一的容器管理系統,在咱們內部稱之爲「Borg」,它管理着長時間運行的生產服務和批處理服務。這兩類任務以前是由兩個分離開的系統來管理的:Babysitter和Global Work Queue。Global Work Queue的構架極大地影響了Borg,但卻只是針對批量服務的,且二者都在Linux control groups誕生以前。Borg將這兩種應用所用的機器統一成一個池子,這樣得以提升資源利用率,進而下降成本。之因此能夠實現這樣的機器資源共享,是由於能夠拿到Linux內核的容器支持(確實,Google對Linux內核的容器代碼貢獻了不少),這使得在對時限敏感的、且面對用戶的服務和佔用不少CPU資源的批處理進程提供了更好的隔離。web

因爲愈來愈多的應用被開發並運行在Borg上,咱們的應用和底層團隊開發了一個普遍的工具和服務的生態系統。這些系統提供了配置和更新job的機制,可以預測資源需求,動態地對在運行中的程序推送配置文件、服務發現、負載均衡、自動擴容、機器生命週期的管理、額度管理以及更多。這個生態系統的發展源自谷歌內部不一樣團隊的需求,發展的結果成爲了異構的、ad-hoc系統的集合,Borg的使用者可以用幾種不一樣的配置語言和進程來配置和溝通。因爲Borg的規模、功能的普遍性和超高的穩定性,Borg在谷歌內部依然是主要的容器管理系統。express

Omega,做爲Borg的延伸,它的出現是出於提高Borg生態系統軟件工程的願望。Omega應用到了不少在Borg內已經被認證的成功的模式,可是是從頭開始來搭建以期更爲一致的構架。Omega存儲了基於Paxos、圍繞transaction的集羣的狀態,可以被集羣的控制面板(好比調度器)接觸到,使用了優化的進程控制來解決偶爾發生的衝突。這種分離容許Borgmaster的功能被區分紅幾個並列的組建,而不是把全部變化都放到一個單獨的、巨石型的master裏。許多Omega的創新(包括多個調度器)都被收錄進了Borg。編程

谷歌研發的第三個容器管理系統是Kubernetes。Kubernetes的研發和認知背景,是針對在谷歌外部的對Linux容器感興趣的開發者以及谷歌在公有云底層商業增加的考慮。和Borg、Omega徹底是谷歌內部系統相比,Kubernetes是開源的。像Omega同樣,Kubernetes在其核心有一個被分享的持久存儲,有組件來檢測相關ojbect的變化。跟Omega不一樣的是,Omega把存儲直接暴露給信任的控制面板的組件,而在Kubernete中,是要徹底由domain-specific的提供更高一層的版本控制認證、語義、政策的REST API來接觸,以服務更多的用戶。更重要的是,Kubernetes是由一支在集羣層面應用開發能力更強的開發者開發的,他們主要的設計目標是用更容易的方法去部署和管理複雜的分佈式系統,同時仍然能經過容器所提高的使用效率來受益。安全

這篇文章描述了谷歌從Borg到Kubernetes這個旅程中所得到知識和經驗教訓。服務器

容器

歷史上,第一個容器提供的僅僅是root file system的隔離(經過chroot),再加上FreeBSD jails提供額外的例如process ID這樣的namespaces。Solaris後來成爲先鋒而且作了不少增強的探索。Linux control groups(cgroups)運用了不少這些想法,在這個領域的發展一直延續到今天。網絡

容器的資源隔離特性使得谷歌的資源使用率遠遠高出業界同行。例如,Borg使用容器將對延遲敏感、面向用戶的任務和批量任務放在相通的物理機上,並會爲它們預留更多的資源,這樣能夠解決load spikes、fail-over等問題。容器提供的資源管理工具使這些得以實現,穩定的內核層面的資源隔離也使進程之間不互相干擾。咱們經過在研發Borg的同時增強Linux容器的方式來得到成功。然而,隔離並非完美的,容器在內核操做系統不能管理的資源隔離方面鞭長莫及,好比level 3 processor caches、內存帶寬、以及容器須要被一個額外的安全層支持以抵抗雲端的各類惡意攻擊。數據結構

現代的容器不只僅是隔離機制:它也包括鏡像,即包含了在容器內可以讓應用跑起來的文件。在谷歌內部,MPM(Midas Package Manager)被用來建造和部署容器鏡像。在隔離機制和MPM之間一樣的共生關係,也能夠在Docker daemon和Docker鏡像之間被發現。在這篇文章剩餘的篇幅中,咱們會使用「容器」這個詞來包含這兩方面:運行時隔離和鏡像。架構

面向應用的架構(Application-oriented infrastructure)

隨着時間的推移,咱們愈來愈清楚容器在更高一層使用時的好處。容器化能使數據中心從面向機器轉爲面向應用。這個部分討論兩個例子:

  1. 容器封裝了應用環境,把不少機器和操做系統的細節從應用開發者和部署底層那裏抽象了出來。

  2. 由於設計良好的容器和鏡像的做用範圍是一個很小的應用,所以管理容器意味着管理應用而非機器,極大簡化了應用的部署和管理。

應用環境

Linux內核裏的cgroup、chroot和namespace的本來是爲了保護應用不受周邊雜亂鄰里的影響。把這些和容器鏡像組合起來建立一個抽象事物把應用從運行它們的(紛雜的)操做系統裏隔離出來,提升了部署可靠性,也經過減小不一致性和衝突而加快了開發速度。

能讓這個抽象事物得以實現的關鍵在於有一個自包含的鏡像,它把一個應用幾乎全部的依賴環境都打包而後部署在一個容器裏。

若是這個過程作的正確,本地的外部環境就只剩下Linux內核的system-call interface. 這個有限制的interface極大提升了鏡像的便攜性,它並不完美:應用仍然暴露給了OS interface,尤爲是在socket選項的普遍表面上、/proc、和給ioctl call的所傳參數上。咱們但願後面相似Open Container Initiative(OCI:點這裏)的努力能繼續把容器抽象的表層能理清。

然而,容器提供的隔離和對環境依賴的最低性在谷歌內部頗爲有效,容器也是谷歌內部底層惟一支持的應用程序運行實體。這樣的好處之一就是在任什麼時候候,谷歌在它一整臺機器上只有不多量的OS版本部署,只須要不多量的人員來管理或升級。

有不少種方式能夠實現這些自包含的鏡像。在Borg裏,程序的二進制文件在構建時靜態地鏈接到公司範圍內repo庫裏已知的library版本。即使這樣,Borg容器鏡像也並不是100%的自包含:由於應用會共享一個所謂的基礎鏡像,而不是將這個基礎鏡像打包在每一個容器中。這個基礎鏡像包含了一些容器須要用到的utilities,好比tar和libc library,所以對基礎鏡像的升級會影響運行中的應用,偶爾也會變成一個比較嚴重的問題產生來源。

如今的容器鏡像格式,好比Docker和ACI把容器進一步抽象,經過消除內在的主機OS環境依賴和要求外在的user命令來共享容器之間的鏡像數據,使得距離理想的自包含性又近了一步。

容器做爲管理的單位

搭建面向容器而非機器的管理API把數據中心的關鍵字從機器轉向了應用。這樣有不少好處:(1)減輕應用開發者和運維團隊操心機器和系統具體細節的壓力;(2)提供底層團隊彈性,得以升級新硬件和操做系統,但同時對在跑的應用和開發者影響甚小;(3)它把管理系統收集的telemetry(好比CPU和內存用量的metrics)和應用而非機器綁在一塊兒,極大提高了應用監測和檢查,尤爲是在擴容、機器失敗或者運維致使應用實例遷移的時候。

容器可以註冊通用的API使得管理系統和應用之間儘管互相不甚明瞭對方的實現細節,但也能信息流通。在Borg裏,這個API是一系列HTTP終端銜接到每個容器上。舉例來講,/healthz終端對編排器報告應用的健康狀態。當一個不健康的應用被發現,它就被自動終止和重啓。這種自我修復對可靠的分佈式系統而言是一個關鍵的磚頭塊。(Kubernetes提供了相似的功能;健康檢查使用了一個用戶指定的HTTP終端或者跑在容器裏的exec命令。)

容器也能提供其餘面向應用的監測:舉例來講,Linux內核cgroups提供關於應用的資源利用數據,這些能夠和先前提到的由HTTP API導出的客戶metrics一塊兒被延伸。這些數據可以實現例如自動擴容或cAdvisor這樣通常工具的開發,這些開發記錄或者使用這些metrics,不須要理解每一個應用的細節。由於容器就是應用,就再也不須要從在一個物理機或者虛擬機上跑的多個應用來多路分配信號。這個更簡單、更穩定一些,並且也容許對metrics和日誌進行更細粒度的報告和控制。拿這個跟須要ssh到一臺機器去跑top去比一下。儘管對開發者來講,ssh到他們的容器是可能的,但程序員不多會須要這麼去作。

監測,只是一個例子。面向應用的這個變化在管理底層上是有連帶效果的。咱們的負載均衡器並不平衡機器間的傳輸,它們是針對應用實例來平衡。日誌也是根據應用,而非機器,所以它們能夠很容易的被收集以及在實例之間集合,而不受到多個應用或者操做系統的影響。咱們能夠查探到應用失敗,更容易對這些失敗的緣由來歸類,而不須要對它們進行機器層面信號的分離。

最後,儘管到目前爲止,咱們對應用的關注和對容器的關注是1:1,但在現實中咱們使用在同一臺機器上聯動的容器:最外面的容器提供一個資源池,裏面的這些容器提供部署隔離。在Borg,最外面那層容器被稱爲資源調配器(或者alloc),在Kubernetes裏,被稱爲pod。Borg也容許最頂端的應用容器跑在alloc的外面,這個帶來了不少不方便,因此Kubernetes把這些規範化而且老是在一個頂端的pod裏來跑應用容器,即使這個pod只有單一的一個容器。

一個廣泛的使用樣式,是用一個pod來裝一個複雜應用的實例。應用的主要部分在它其中一個容器(child containers)裏,其餘容器跑着支持功能,例如日誌處理。跟把這些功能組合到一個單一的二進制相比,這使得開發團隊開發不一樣功能的部件容易不少,也提升了穩定性(即使主體應用有新的東西進來,日誌發送依然能夠繼續運行)和可編輯性。

編排只是開始,不是結束

原始的Borg系統能夠在共享的機器上跑不一樣的工做負荷來提升資源利用率。但在Borg內支持服務的迅速進化顯示,容器管理的本質只是開發和管理可靠的分佈式系統的開始,不少不一樣的系統在Borg上和周邊被開發,用來提升Borg所提供的基本的容器管理服務。下面這個不完整的列表給出了這些服務大概的一個範圍和多樣性:

  • 命名和服務發現(Borg Name Service或BNS);

  • Master election(用Chubby);

  • 面向應用的負載均衡;

  • 橫向(實例數量)和縱向(實例尺寸)的自動擴容;

  • 發佈工具,用來管理新二進制和配置數據;

  • 工做流程工具(例如容許跑分析多任務的pipelines在不一樣階段有互相環境依賴);

  • 監測工具用來收集關於容器的信息,集合這些信息、發佈到dashboard上,或者用它來激發預警。

構建這些服務是用來解決應用開發團隊所經歷的問題。成功的服務被普遍採用,那其餘開發者就受益。不幸的是,這些工具經常選一些怪癖的API,conventions(好比文件位置)和Borg的深度結合。一個反作用就是增長了Borg生態系統部署應用的複雜性。

Kubernetes企圖經過對API採用一種一致的方法來避免這種增長的複雜性。好比說,每個Kubernetes的對象在它的描述裏有三個基本的屬性:對象的metadata、spec和狀態(status)。

對象的metadata對系統中的全部對象都是同樣的,它包含了例如對象名稱、UID(特殊標示)、一個對象的版本號碼(爲了樂觀的進程控制)以及標籤(key-value對,見下面描述)。Spec和status的內容根據不一樣的對象類型會不一樣,但它們的概念是同樣的:spec時用來描述對象的理想狀態,而status提供了該對象目前當下的只讀信息。

這種統一的API帶來不少好處,可讓咱們更容易的瞭解系統,由於系統中全部對象都有相似的信息。另外,統一的API能夠更容易地編寫通用的工具來做用於全部對象,這樣反過來也讓使用者感受更爲連貫。經過對Borg和Omega的總結,Kubernetes創建在一整套可自由拆裝的部件之上,能夠由開發者任意延展。一個有共識的API和對象metadata結構可使這個過程更爲簡單。

一致性還能夠經過在Kubernetes API內解構來完成。在API組建之間考慮進行一些分離意味着在更高層的服務上須要共享一些基本的構建組件。一個很好的例子是在Kubernetes的RC(replication controller)和它水平自動擴容系統之間的分離。一個RC保證了對某個角色(好比「前端」)理想的pod數量的存在。自動擴容器,反過來,須要依賴這個能力而且簡單地調整理想的pod數量,不須要擔憂pod如何生成和刪除。自動擴容器的實現可以把精力集中在需求和使用的預測,忽略如何實現這些決定的細節。

分離保證了多個關聯但不一樣的組件共享一個類似的外表和感受。舉個例子,Kubernetes有三個不一樣的pod副本模式:

  • ReplicationController:永遠在運行的容器副本(好比web服務器);

  • DaemonSet:確保在集羣裏的每一個節點上有一個單獨的實例(例如日誌代理);

  • Job:一個知道如何從開始到結束運行一個(多是並行的)批處理任務的run-to-completion的控制器。

儘管在規則上有區別,全部這三個控制器都依賴共同的pod對象來制定它們想要運行在上面的容器。

一致性也能夠經過不一樣Kubernetes組件上共同的設計形式來達到。在Borg、Omega和Kubernetes上用來提升系統彈性,有一個概念:「reconciliation controller loop」(清理控制器循環),這個概念是來比較一個理想的狀態(好比須要多少個pod才能來達到一個標籤選擇的query,即 label-selector query),和相對於觀測到的狀態(能夠發現的這樣的pod數量)來進行比較,而後採起行動去把這兩個狀態作到一致。

須要避免的事情

在研發這些系統的時候,咱們也學到了許多關於哪些事情不應作,哪些事情值得去作的經驗。咱們把其中的一些寫出來,指望後來者再也不重蹈覆轍,而是集中精力去解決新問題

別讓容器系統來管理port端口

全部跑在Borg機器上的容器都共享主機的IP地址,因此Borg給容器分發了獨特的port端口做爲調度過程的一部分。一個容器當它移到一個新的機器上(有時候)在一樣的機器上重啓的話,會拿到一個新的端口號碼。這意味着傳統的例如像DNS(Domain Name System)網絡服務須要被home-brew版本取代;由於服務的客戶不會先驗地知道給到服務的port端口,須要被告知;port端口號碼不能被嵌在URL裏,就須要以名字爲基礎的再次導向(redirection)機制;並且依賴於簡單的IP地址的工具須要被重寫來搞定IP:端口對的形式(port pairs)。

從咱們在Borg的經驗來看,咱們決定Kubernetes能夠來給每一個pod制定IP地址,這樣把網絡身份(即IP地址)和應用身份能統一塊兒來。這會使得在Kubernetes上跑現成的軟件容易的多:應用能夠隨意使用靜態已知的端口(好比80做爲HTTP端口),已經存在的、熟悉的工具能夠被用來作網絡分段、帶寬調節管理。全部流行的雲平臺提供網絡的基礎層,可以有每一個pod的IP,在裸機上,可使用SDN覆蓋層或者配置L3路由來管理每一個機器上的多個IP.

別僅僅只是給容器編號:給它們打標籤

若是你讓用戶很容易地建立容器,他們會傾向於建立不少,那麼很快就會須要一種方式來管理和組織它們。Borg對於羣組的相同的task提供了jobs(對於容器而言任務的名稱)。一個job是一個壓縮的容器(vector)裝了一個或多個相同的task,從0開始計數。這提供了許多能量,並且很簡單直白,但時間長了咱們又會後悔它過於死板。好比說,當一個task死掉了,須要在另外一臺機器上被從新啓動,在task這個vector上的相同的slot就要雙倍的工做:既要指認這個新的備份,同時還要指向舊的那個,萬一可能須要作debug。當task出如今vector的當中,那vector就有洞。所以vector很難去支持在Borg的一層上跨越多個集羣的job.同時,也有潛在的、不期而遇的在Borg更新job的語意上(典型的是在作滾動升級的時候按照index標記來重啓)和應用使用的task index標記(好比作一些sharding活着跨task的數據的分區)的互動:若是應用使用基於task index的range sharding,那麼Borg的重啓政策會致使拿不到數據,由於它會拉掉附近的任務。Borg也沒有簡單的辦法去job裏面增長跟應用有關的metadata,好比角色屬性(好比「前端」)或者展現的狀態(好比是canary),因此人們要把這些信息寫到job名稱裏,這樣他們能夠用常規表達式(regular expression)來解析。

相比之下,Kubernetes主要使用標籤(labels)來識別成組的容器。一個標籤是一對key/value組,包含着容器信息能夠用來識別對象。一個pod可能有這樣的標籤:role=frontend 和 stage=production,代表這個容器服務於前端生產。標籤能夠動態地被自動工具、用戶來添加、移除和修改,也能夠被其餘不一樣的團隊獨立地來管理他們本身的標籤。成組的對象,能夠由label selectors來定義(好比 stage==production && role==frontend)。這些組(set)能夠重疊,並且一個對象能夠在多個的組(set)裏,所以標籤自己要比明確的對象列表或簡單靜態的屬性更靈活。由於一個組(set)是由一個動態隊列來定義的,一個新的組能夠在任什麼時候候被生成。在Kubernetes裏label selectors是grouping(成組)的機制,來定義跨越多個實體的管理操做的範圍。

即使在那樣的環境裏知道在一個set裏的一個task的身份是頗有幫助的(好比說靜態角色的分配和工做分區或分片),適當的每一個pod有標籤能夠被用來再次產生任務標示的效果,儘管這個是應用的責任(或者一些其餘在Kubernetes外部的管理系統的責任)來提供這樣的標籤。標籤和標籤選擇器提供了一個對這二者的最好的通用機制。

對全部權要謹慎

在Borg裏,tasks並非獨立於jobs存在的。生成一個job,也會生成它的task,那些tasks永遠和特定的job是有關聯的,若是刪除job,也會刪除task。這樣很方便,但也會有一個主要的缺點:由於只有一個成組的機制,須要來解決全部出現的狀況。舉例來講,一個job須要存儲參數,這些參數或者是對應服務(service)或者是對應批量工做(batch job)但不會是二者同時,並且用戶必需要寫出workarounds當job的抽象沒法來解決某個狀況的時候(好比一個DaemonSet對這個集羣裏的全部節點都去複製一個簡單的pod)。

在Kubernetes裏,pod生命週期的管理組件例如RC決定了哪一個pod它們有責任要用標籤選擇器,所以多個控制器均可能會認爲它們本身對於一個單一的pod有管轄權。經過適當的配置選擇來預防這樣的衝突就很是重要。可是標籤的彈性也有額外的好處,好比說,控制器和pod的分離意味着能夠孤立和啓用一些容器。考慮到一個負載均衡的服務使用一個標籤選擇器去標示一組pod去發送請求。若是這些pod中的一個行爲異常,那這個pod的被Kubernetes服務負載均衡器識別出來的標籤會被刪除、這個pod被隔離再也不進行服務。這個pod再也不服務接受請求,但它會保持線上的狀態,在原處能夠被debug.同時,管理pod的RC自動實現服務,爲有問題的pod建立一個複製的pod.

不要暴露raw state

Borg、Omega和Kubernetes之間一個關鍵的差異在於它們的API構架。Borgmaster是一個單一的組件,它知道每個API運做的語義。它包含了諸如關於jobs、tasks和機器的狀態機器的集羣管理的邏輯;它跑基於Paxos的複製存儲系統用來記錄master的狀態。反觀Omega,Omega除了存儲以外沒有集中的部件,存儲也是簡單地聚集了被動的狀態信息以及增強樂觀的並行進程控制:全部的邏輯和語義都被推動存儲的client裏,直接讀寫存儲的內容。在實踐中,每個Omega的部件爲了存儲使用一樣的客戶端library,來打包或者解體數據結構、從新嘗試活着增強語義的一致性。

Kubernetes選擇了一箇中間地提供了像Omega部件結構的彈性和可擴容性,同時還能增強系統層面的無變化、政策和數據傳輸。它經過強制全部存儲接觸必須經過一箇中央的API服務器來隱藏存儲的實現細節和給對象驗證、版本控制提供服務來作到這些。在Omega裏,client的部件互相之間是分離的,能夠進化或者單獨被替換(這對開源環境而言尤爲重要),但中央化對增強共同語義、不變性和政策會容易不少。

一些開放性的難題

有了八年的容器管理經驗,咱們感受依然還有大量的問題咱們沒有很好的解決方案。這個部分描述了一些咱們感到特別棘手的問題,做爲拋磚引玉吧。

配置

在全部咱們面對的問題中,最多的心思和筆墨涉及到的都是關於管理配置,即一整套的提供給應用的配置,而非硬生生寫進應用裏去。咱們徹底能夠把整篇文章都拿來寫這個主題(可能都說不完)。下面這些是一些咱們想要強調的內容。

首先,應用配置變成了一個關聯一切的抓手,來實現全部的東西,全部這些容器管理系統(尚且)不作的事情,包括:

  • 樣板化簡約(好比把tast重啓的政策調整到相適應的負載工做量,例如服務或者批處理工做);

  • 調整和驗證應用參數以及command-line參數;

  • 實現例如打包鏡像管理的缺失API抽象的替代解決方法;

  • 應用配置模版的library;

  • 發佈管理工具;

  • 鏡像版本說明。

爲了解決這些要求、配置管理系統趨向於發明一個domain-specific的配置語言,最終具備圖靈完備性,起源於但願可以在配置的數據裏進行計算(好比對一個服務調整給它的內存,做爲在一個服務裏進行分區的功能)。結果就產生一個難以理解的「配置是代碼」,你們都經過不在應用當中hardcode參數來儘可能避免的這種狀況。它並無減小操做上的複雜性或者使得配置更容易debug或改變,它只是把計算從一個真正的編程語言挪到了一個特殊領域。

咱們相信最有效的方法是去接受這個需求,擁抱無所不在的程序配置和在計算和數據之間保持一個清楚的界線。表明數據的語言應該是簡單的、僅數據格式的,好比像JSON或者YAML,對這種數據的程序化修改應該在一個真實的編程語言裏,有被很好理解的語義和工具。有趣的是,一樣的在計算和數據之間的分離在前端開發的不一樣領域是雷同的,好比像Angular在markup(數據)和JavaScript(計算)之間是有清晰的劃分的。

依賴條件的管理

起一個服務每每也意味着提供一系列相關的服務(監控、存儲、CI/CD等等)。若是一個應用對其餘應用有依賴,其餘這些依賴條件(和任何它們可能有涉及的依賴條件)可以被集羣系統自動管理,是否是很好呢?

更麻煩的是,對依賴條件的實例化不多會像起一個新的備份這麼簡單,好比說,它可能會須要對現有的服務註冊一個新的消費者(好比Bigtable as a service)而後經過這些間接的依賴環境來傳遞認證、受權以及帳號信息。然而,基本上沒有系統會抓、保持或者透露這些依賴信息,因此在底層自動化這些即使是很是常見的狀況都是近乎不可能的。起來一個新的應用對用戶來講就很複雜,對開發者而言來建新的服務就變難,常常致使一些最佳實踐沒法進行,影響服務的可靠性。

一個標準的問題是:若是是手動更新,很難保持依賴信息的及時更新。並且同時,能自動地(好比跟蹤access)決定它的這種企圖也沒法掌握須要瞭解結果的語義信息。(好比是否這個acess要給那個實例?或者任何一個實例就足夠了?)一個可以改進的多是要求應用枚舉它所依賴的服務,而後讓底層拒絕對其餘服務的接觸(咱們在咱們的build system裏對compiler imports這麼作過)。這個動機是讓底層作有用的事情,好比自動的setup、認證和鏈接。

不幸的是,咱們所觀察到的系統在表達、分析和使用系統依賴這方面的複雜性都過高,因此它們尚未被夾到一個主流的容器管理系統裏。咱們依然但願Kubernetes可能能夠成爲一個這樣的平臺,在這個平臺上有這樣的工具,但這麼作是一個很大的挑戰。

結語

十多年搭建容器管理系統的經驗教會了咱們不少。並且咱們把不少已有的經驗融入進了Kubernetes,谷歌最近的這個容器管理系統。它的目標是基於容器的能力來提供編程生產力方面的極大收穫,簡化人工和自動化系統管理。咱們但願你會來加入咱們來延伸和提升這個項目。

(若是須要轉載,請聯繫咱們哦,尊重知識產權人人有責;)

相關文章
相關標籤/搜索