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

Borg、Omega、K8s:Google 十年三代容器管理系統(tǒng)的設(shè)計(jì)與思考

開發(fā) 架構(gòu)
業(yè)界這幾年對(duì)容器的興趣越來越大,但其實(shí)在 Google,我們十幾年前就已經(jīng)開始大規(guī)模容器實(shí)踐了, 這個(gè)過程中也先后設(shè)計(jì)了三套不同的容器管理系統(tǒng)。這三代系統(tǒng)雖然出于不同目的設(shè)計(jì),但每一代都受前一代的強(qiáng)烈影響。本文介紹我們開發(fā)和運(yùn)維這些系統(tǒng)所學(xué)習(xí)到的經(jīng)驗(yàn)與教訓(xùn)。

1 十年三代容器管理系統(tǒng)

業(yè)界這幾年對(duì)容器的興趣越來越大,但其實(shí)在 Google,我們十幾年前就已經(jīng)開始大規(guī)模容器實(shí)踐了, 這個(gè)過程中也先后設(shè)計(jì)了三套不同的容器管理系統(tǒng)。這三代系統(tǒng)雖然出于不同目的設(shè)計(jì),但每一代都受前一代的強(qiáng)烈影響。本文介紹我們開發(fā)和運(yùn)維這些系統(tǒng)所學(xué)習(xí)到的經(jīng)驗(yàn)與教訓(xùn)。

1.1 Borg

Google 第一代統(tǒng)一容器管理系統(tǒng),我們內(nèi)部稱為 Borg 7。

1.1.1 在線應(yīng)用和批處理任務(wù)混布

Borg 既可以管理 long-running service 也可以管理 batch job;在此之前,這兩種類型的任務(wù)是由兩個(gè)系統(tǒng)分別管理的,

  • Babysitter
  • Global Work Queue

Global Work Queue 主要面向 batch job,但它強(qiáng)烈影響了 Borg 的架構(gòu)設(shè)計(jì);

1.1.2 早于 Linux cgroups 的出現(xiàn)

需要說明的是,不論是我們?cè)O(shè)計(jì)和使用 Global Work Queue 還是后來的 Borg 時(shí), Linux cgroup 都還沒有出現(xiàn)。

1.1.3 好處:計(jì)算資源共享

Borg 實(shí)現(xiàn)了 long-running service 和 batch job 這兩種類型的任務(wù)共享計(jì)算資源, 提升了資源利用率,降低了成本。

在底層支撐這種共享的是Linux 內(nèi)核中新出現(xiàn)的容器技術(shù)(Google 給 Linux 容器技術(shù)貢獻(xiàn)了大量代碼),它能實(shí)現(xiàn)延遲敏感型應(yīng)用和 CPU 密集型批處理任務(wù)之間的更好隔離。

1.1.4 自發(fā)的 Borg 生態(tài)

隨著越來越多的應(yīng)用部署到 Borg 上,我們的應(yīng)用與基礎(chǔ)設(shè)施團(tuán)隊(duì)開發(fā)了大量圍繞 Borg 的管理工具和服務(wù),功能包括:

  • 配置或更新 job;
  • 資源需求量預(yù)測(cè);
  • 動(dòng)態(tài)下發(fā)配置到線上 jobs;
  • 服務(wù)發(fā)現(xiàn)和負(fù)載均衡;
  • 自動(dòng)擴(kuò)縮容;
  • Node 生命周期管理;
  • Quota 管理

也就是產(chǎn)生了一個(gè)圍繞 Borg 軟件生態(tài),但驅(qū)動(dòng)這一生態(tài)發(fā)展的是 Google 內(nèi)部的不同團(tuán)隊(duì), 因此從結(jié)果來看,這個(gè)生態(tài)是一堆異構(gòu)、自發(fā)的工具和系統(tǒng)(而非一個(gè)有設(shè)計(jì)的體系), 用戶必須通過幾種不同的配置語言和配置方式來和 Borg 交互。

雖然有這些問題,但由于其巨大的規(guī)模、出色的功能和極其的健壯性,Borg 當(dāng)前仍然是 Google 內(nèi)部主要的容器管理系統(tǒng)。

1.2 Omega

為了使 Borg 的生態(tài)系統(tǒng)更加符合軟件工程規(guī)范,我們又開發(fā)了 Omega6,

1.2.1 架構(gòu)更加整潔一致

Omega 繼承了許多已經(jīng)在 Borg 中經(jīng)過驗(yàn)證的成功設(shè)計(jì),但又是完全從頭開始開發(fā), 以便架構(gòu)更加整潔一致。

  • Omega 將集群狀態(tài)存儲(chǔ)在一個(gè)基于 Paxos 的中心式面向事務(wù) store(數(shù)據(jù)存儲(chǔ))內(nèi);

  • 控制平面組件(例如調(diào)度器)都可以直接訪問這個(gè) store;

  • 用樂觀并發(fā)控制來處理偶發(fā)的訪問沖突。

1.2.2 相比 Borg 的改進(jìn)

這種解耦使得 Borgmaster 的功能拆分為了幾個(gè)彼此交互的組件, 而不再是一個(gè)單體的、中心式的 master,修改和迭代更加方便。Omega 的一些創(chuàng)新(包括多調(diào)度器)后來也反向引入到了 Borg。

1.3 Kubernetes

Google 開發(fā)的第三套容器管理系統(tǒng)叫 Kubernetes4。

1.3.1 為什么要設(shè)計(jì) K8s

開發(fā)這套系統(tǒng)的背景:

全球越來越多的開發(fā)者也開始對(duì) Linux 容器感興趣,Google 已經(jīng)把公有云基礎(chǔ)設(shè)施作為一門業(yè)務(wù)在賣,且在持續(xù)增長(zhǎng);因此與 Borg 和 Omega 不同的是:Kubernetes 是開源的,不是 Google 內(nèi)部系統(tǒng)。

1.3.2 相比 Omega 的改進(jìn)

  • 與 Omega 類似,k8s 的核心也是一個(gè)共享持久數(shù)據(jù)倉(cāng)庫(kù)(store), 幾個(gè)組件會(huì)監(jiān)聽這個(gè) store 里的 object 變化;

  • Omega 將自己的 store 直接暴露給了受信任的控制平面組件,但 k8s 中的狀態(tài) 只能通過一個(gè) domain-specific REST API 訪問,這個(gè) API 會(huì)執(zhí)行 higher-level versioning, validation, semantics, policy 等操作,支持多種不同類型的客戶端;

  • 更重要的是,k8s 在設(shè)計(jì)時(shí)就非常注重應(yīng)用開發(fā)者的體驗(yàn):首要設(shè)計(jì)目標(biāo)就是在享受容器帶來的資源利用率提升的同時(shí),讓部署和管理復(fù)雜分布式系統(tǒng)更簡(jiǎn)單。

1.4 小結(jié)

接下來的內(nèi)容將介紹我們?cè)谠O(shè)計(jì)和使用以上三代容器管理系統(tǒng)時(shí)學(xué)到的經(jīng)驗(yàn)和教訓(xùn)。

2 底層 Linux 內(nèi)核容器技術(shù)

容器管理系統(tǒng)屬于上層管理和調(diào)度,在底層支撐整個(gè)系統(tǒng)的,是 Linux 內(nèi)核的容器技術(shù)。

2.1 發(fā)展歷史:從 chroot 到 cgroups

  • 歷史上,最初的容器只是提供了 root file system 的隔離能力 (通過 chroot);

  • 后來 FreeBSD jails 將這個(gè)理念擴(kuò)展到了對(duì)其他 namespaces(例如 PID)的隔離;Solaris 隨后又做了一些前沿和拓展性的工作;

  • 最后,Linux control groups (cgroups) 吸收了這些理念,成為集大成者。內(nèi)核 cgroups 子系統(tǒng)今天仍然處于活躍開發(fā)中。

2.2 資源隔離

容器技術(shù)提供的資源隔離(resource isolation)能力,使 Google 的資源利用率遠(yuǎn)高于行業(yè)標(biāo)準(zhǔn)。例如,Borg 能利用容器實(shí)現(xiàn)延遲敏感型應(yīng)用和CPU 密集型批處理任務(wù)的混布(co-locate), 從而提升資源利用率,業(yè)務(wù)用戶為了應(yīng)對(duì)突發(fā)業(yè)務(wù)高峰和做好 failover, 通常申請(qǐng)的資源量要大于他們實(shí)際需要的資源量,這意味著大部分情況下都存在著資源浪費(fèi);通過混布就能把這些資源充分利用起來,給批處理任務(wù)使用。

容器提供的資源管理工具使以上需求成為可能,再加上強(qiáng)大的內(nèi)核資源隔離技術(shù), 就能避免這兩種類型任務(wù)的互相干擾。我們是開發(fā) Borg 的過程中,同步給 Linux 容器做這些技術(shù)增強(qiáng)的。

但這種隔離并未達(dá)到完美的程度:容器無法避免那些不受內(nèi)核管理的資源的干擾,例如三級(jí)緩存(L3 cache)、 內(nèi)存帶寬;此外,還需要對(duì)容器加一個(gè)安全層(例如虛擬機(jī))才能避免公有云上各種各樣的惡意攻擊。

2.3 容器鏡像

現(xiàn)代容器已經(jīng)不僅僅是一種隔離機(jī)制了:還包括鏡像 —— 將應(yīng)用運(yùn)行所需的所有文件打包成一個(gè)鏡像。

在 Google,我們用 MPM (Midas Package Manager) 來構(gòu)建和部署容器鏡像。隔離機(jī)制和 MPM packages 的關(guān)系,就像是 Docker daemon 和 Docker image registry 的關(guān)系。在本文接下來的內(nèi)容中,我們所說的“容器”將包括這兩方面, 即運(yùn)行時(shí)隔離和鏡像。

3 面向應(yīng)用的基礎(chǔ)設(shè)施

隨著時(shí)間推移,我們意識(shí)到容器化的好處不只局限于提升資源利用率。

3.1 從“面向機(jī)器”到“面向應(yīng)用”的轉(zhuǎn)變

容器化使數(shù)據(jù)中心的觀念從原來的面向機(jī)器(machine oriented) 轉(zhuǎn)向了面向應(yīng)用(application oriented),

容器封裝了應(yīng)用環(huán)境(application environment), 向應(yīng)用開發(fā)者和部署基礎(chǔ)設(shè)施屏蔽了大量的操作系統(tǒng)和機(jī)器細(xì)節(jié),每個(gè)設(shè)計(jì)良好的容器和容器鏡像都對(duì)應(yīng)的是單個(gè)應(yīng)用,因此 管理容器其實(shí)就是在管理應(yīng)用,而不再是管理機(jī)器。

Management API 的這種從面向機(jī)器到面向應(yīng)用的轉(zhuǎn)變,顯著提升了應(yīng)用的部署效率和問題排查能力。

3.2 應(yīng)用環(huán)境(application environment)

3.2.1 資源隔離 + 容器鏡像:解耦應(yīng)用和運(yùn)行環(huán)境

資源隔離能力與容器鏡像相結(jié)合,創(chuàng)造了一個(gè)全新的抽象:

內(nèi)核 cgroup、chroot、namespace 等基礎(chǔ)設(shè)施的最初目的是保護(hù)應(yīng)用免受 noisy、nosey、messy neighbors 的干擾。

而這些技術(shù)與容器鏡像相結(jié)合,創(chuàng)建了一個(gè)新的抽象, 將應(yīng)用與它所運(yùn)行的(異構(gòu))操作系統(tǒng)隔離開來。

這種鏡像和操作系統(tǒng)的解耦,使我們能在開發(fā)和生產(chǎn)環(huán)境提供相同的部署環(huán)境;這種環(huán)境的一致性提升了部署可靠性,加速了部署。這層抽象能成功的關(guān)鍵,是有一個(gè)hermetic(封閉的,不受外界影響的)容器鏡像,這個(gè)鏡像能封裝一個(gè)應(yīng)用的幾乎所有依賴(文件、函數(shù)庫(kù)等等);

那唯一剩下的外部依賴就是 Linux 系統(tǒng)調(diào)用接口了 —— 雖然這組有限的接口極大提升了鏡像的可移植性, 但它并非完美:應(yīng)用仍然可能通過 socket option、/proc、ioctl 參數(shù)等等產(chǎn)生很大的暴露面。我們希望 Open Container Initiative 等工作可以進(jìn)一步明確容器抽象的 surface area。

雖然存在不完美之處,但容器提供的資源隔離和依賴最小化特性,仍然使得它在 Google 內(nèi)部非常成功, 因此容器成為了 Google 基礎(chǔ)設(shè)施唯一支持的可運(yùn)行實(shí)體。這帶來的一個(gè)后果就是, Google 內(nèi)部只有很少幾個(gè)版本的操作系統(tǒng),也只需要很少的人來維護(hù)這些版本, 以及維護(hù)和升級(jí)服務(wù)器。

3.2.2 容器鏡像實(shí)現(xiàn)方式

實(shí)現(xiàn) hermetic image 有多種方式,在 Borg 中,程序可執(zhí)行文件在編譯時(shí)會(huì)靜態(tài)鏈接到公司托管的特定版本的庫(kù)5;

但實(shí)際上 Borg container image 并沒有做到完全獨(dú)立:所有應(yīng)用共享一個(gè)所謂的 base image,這個(gè)基礎(chǔ)鏡像是安裝在每個(gè) node 上的,而非打到每個(gè)鏡像里去;由于這個(gè)基礎(chǔ)鏡像里包含了 tar libc 等基礎(chǔ)工具和函數(shù)庫(kù), 因此升級(jí)基礎(chǔ)鏡像時(shí)會(huì)影響已經(jīng)在運(yùn)行的容器(應(yīng)用),偶爾會(huì)導(dǎo)致故障。

Docker 和 ACI 這樣的現(xiàn)代容器鏡像在這方面做的更好一些,它們地消除了隱藏的 host OS 依賴, 明確要求用戶在容器間共享鏡像時(shí),必須顯式指定這種依賴關(guān)系,這更接近我們理想中的 hermetic 鏡像。

3.3 容器作為基本管理單元

圍繞容器而非機(jī)器構(gòu)建 management API,將數(shù)據(jù)中心的核心從機(jī)器轉(zhuǎn)移到了應(yīng)用,這帶了了幾方面好處:

  • 應(yīng)用開發(fā)者和應(yīng)用運(yùn)維團(tuán)隊(duì)無需再關(guān)心機(jī)器和操作系統(tǒng)等底層細(xì)節(jié);
  • 基礎(chǔ)設(shè)施團(tuán)隊(duì)引入新硬件和升級(jí)操作系統(tǒng)更加靈活, 可以最大限度減少對(duì)線上應(yīng)用和應(yīng)用開發(fā)者的影響;
  • 將收集到的 telemetry 數(shù)據(jù)(例如 CPU、memory usage 等 metrics)關(guān)聯(lián)到應(yīng)用而非機(jī)器, 顯著提升了應(yīng)用監(jiān)控和可觀測(cè)性,尤其是在垂直擴(kuò)容、 機(jī)器故障或主動(dòng)運(yùn)維等需要遷移應(yīng)用的場(chǎng)景。

3.3.1 通用 API 和自愈能力

容器能提供一些通用的 API 注冊(cè)機(jī)制,使管理系統(tǒng)和應(yīng)用之間無需知道彼此的實(shí)現(xiàn)細(xì)節(jié)就能交換有用信息。

在 Borg 中,這個(gè) API 是一系列 attach 到容器的 HTTP endpoints。例如,/healthz endpoint 向 orchestrator 匯報(bào)應(yīng)用狀態(tài),當(dāng)檢測(cè)到一個(gè)不健康的應(yīng)用時(shí), 就會(huì)自動(dòng)終止或重啟對(duì)應(yīng)的容器。這種自愈能力(self-healing)是構(gòu)建可靠分布式系統(tǒng)的最重要基石之一。

K8s 也提供了類似機(jī)制,health check 由用戶指定,可以是 HTTP endpoint 也可以一條 shell 命令(到容器內(nèi)執(zhí)行)。

3.3.2 用 annotation 描述應(yīng)用結(jié)構(gòu)信息

容器還能提供或展示其他一些信息。例如,Borg 應(yīng)用可以提供一個(gè)字符串類型的狀態(tài)消息,這個(gè)字段可以動(dòng)態(tài)更新;

K8s 提供了 key-value annotation, 存儲(chǔ)在每個(gè) object metadata 中,可以用來傳遞應(yīng)用結(jié)構(gòu)(application structure)信息。這些 annotations 可以由容器自己設(shè)置,也可以由管理系統(tǒng)中的其他組件設(shè)置(例如發(fā)布系統(tǒng)在更新完容器之后更新版本號(hào))。

容器管理系統(tǒng)還可以將 resource limits、container metadata 等信息傳給容器, 使容器能按特定格式輸出日志和監(jiān)控?cái)?shù)據(jù)(例如用戶名、job name、identity), 或在 node 維護(hù)之前打印一條優(yōu)雅終止的 warning 日志。

3.3.3 應(yīng)用維度 metrics 聚合:監(jiān)控和 auto-scaler 的基礎(chǔ)

容器還能用其他方式提供面向應(yīng)用的監(jiān)控:例如, cgroups 提供了應(yīng)用的 resource-utilization 數(shù)據(jù);前面已經(jīng)介紹過了, 還可以通過 export HTTP API 添加一些自定義 metrics 對(duì)這些進(jìn)行擴(kuò)展。

基于這些監(jiān)控?cái)?shù)據(jù)就能開發(fā)一些通用工具,例如 auto-scaler 和 cAdvisor3, 它們記錄和使用這些 metrics,但無需理解每個(gè)應(yīng)用的細(xì)節(jié)。由于應(yīng)用收斂到了容器內(nèi),因此就無需在宿主機(jī)上分發(fā)信號(hào)到不同應(yīng)用了;這更簡(jiǎn)單、更健壯, 也更容易實(shí)現(xiàn)細(xì)粒度的 metrics/logs 控制,不用再 ssh 登錄到機(jī)器執(zhí)行 top 排障了 —— 雖然開發(fā)者仍然能通過 ssh 登錄到他們的 容器,但實(shí)際中很少有人這樣做。

  • 監(jiān)控只是一個(gè)例子。面向應(yīng)用的轉(zhuǎn)變?cè)诠芾砘A(chǔ)設(shè)施(management infrastructure)中產(chǎn)生漣漪效應(yīng):

  • 我們的 load balancer 不再針對(duì) machine 轉(zhuǎn)發(fā)流量,而是針對(duì) application instance 轉(zhuǎn)發(fā)流量;

  • Log 自帶應(yīng)用信息,因此很容易收集和按應(yīng)用維度(而不是機(jī)器維度)聚合;從而更容易看出應(yīng)用層面的故障,而不再是通過宿主機(jī)層的一些監(jiān)控指標(biāo)來判斷問題;

從根本上來說,實(shí)例在編排系統(tǒng)中的 identity 和用戶期望的應(yīng)用維度 identity 能夠?qū)?yīng)起來, 因此更容易構(gòu)建、管理和調(diào)試應(yīng)用。

3.3.4 單實(shí)例多容器(pod vs. container)

到目前為止我們關(guān)注的都是 application:container = 1:1 的情況, 但實(shí)際使用中不一定是這個(gè)比例。我們使用嵌套容器,對(duì)于一個(gè)應(yīng)用:

  • 外層容器提供一個(gè)資源池;在 Borg 中成為 alloc,在 K8s 中成為 pod;

  • 內(nèi)層容器們部署和隔離具體服務(wù)。

實(shí)際上 Borg 還允許不使用 allocs,直接創(chuàng)建應(yīng)用 container;但這導(dǎo)致了一些不必要的麻煩, 因此 K8s 就統(tǒng)一規(guī)定應(yīng)用容器必須運(yùn)行在 pod 內(nèi),即使一個(gè) pod 內(nèi)只有一個(gè)容器。常見方式是一個(gè) pod hold 一個(gè)復(fù)雜應(yīng)用的實(shí)例。

應(yīng)用的主體作為一個(gè) pod 內(nèi)的容器。其他輔助功能(例如 log rotate、click-log offloading)作為獨(dú)立容器。相比于把所有功能打到一個(gè)二進(jìn)制文件,這種方式能讓不同團(tuán)隊(duì)開發(fā)和管理不同功能,好處:

  • 健壯:例如,應(yīng)用即使出了問題,log offloading 功能還能繼續(xù)工作;

  • 可組合性:添加新的輔助服務(wù)很容易,因?yàn)椴僮鞫际窃谒约旱?container 內(nèi)完成的;

  • 細(xì)粒度資源隔離:每個(gè)容器都有自己的資源限額,比如 logging 服務(wù)不會(huì)占用主應(yīng)用的資源。

3.4 編排是開始,不是結(jié)束

3.4.1 自發(fā)和野蠻生長(zhǎng)的 Borg 軟件生態(tài)

Borg 使得我們能在共享的機(jī)器上運(yùn)行不同類型的 workload 來提升資源利用率。但圍繞 Borg 衍生出的生態(tài)系統(tǒng)讓我們意識(shí)到,Borg 本身只是開發(fā)和管理可靠分布式系統(tǒng)的開始, 各團(tuán)隊(duì)根據(jù)自身需求開發(fā)出的圍繞 Borg 的不同系統(tǒng)與 Borg 本身一樣重要。下面列舉其中一些, 可以一窺其廣和雜:

  • 服務(wù)命名(naming)和服務(wù)發(fā)現(xiàn)(Borg Name Service, BNS);
  • 應(yīng)用選主:基于 Chubby2;
  • 應(yīng)用感知的負(fù)載均衡(application-aware load balancing);
  • 自動(dòng)擴(kuò)縮容:包括水平(實(shí)例數(shù)量)和垂直(實(shí)例配置/flavor)自動(dòng)擴(kuò)縮容;
  • 發(fā)布工具:管理部署和配置數(shù)據(jù);
  • Workflow 工具:例如允許多個(gè) job 按 pipeline 指定的依賴順序運(yùn)行;
  • 監(jiān)控工具:收集容器信息,聚合、看板展示、觸發(fā)告警。

3.4.2 避免野蠻生長(zhǎng):K8s 統(tǒng)一 API(Object Metadata、Spec、Status)

開發(fā)以上提到的那些服務(wù)都是為了解決應(yīng)用團(tuán)隊(duì)面臨的真實(shí)問題,

  • 其中成功的一些后來得到了大范圍的采用,使很多其他開發(fā)團(tuán)隊(duì)的工作更加輕松有效;

  • 但另一方面,這些工具經(jīng)常使用非標(biāo)準(zhǔn) API、非標(biāo)準(zhǔn)約定(例如文件位置)以及深度利用了 Borg 內(nèi)部信息, 副作用是增加了在 Borg 中部署應(yīng)用的復(fù)雜度。

K8s 嘗試通過引入一致 API 的方式來降低這里的復(fù)雜度。例如,每個(gè) K8s 對(duì)象都有三個(gè)基本字段:

Object Metadata:所有 object 的 Object Metadata 字段都是一樣的,包括

  • object name
  • UID (unique ID)
  • object version number(用于樂觀并發(fā)控制)
  • labels
  • Spec:用于描述這個(gè) object 的期望狀態(tài);Spec and Status 的內(nèi)容隨 object 類型而不同。
  • Status:用于描述這個(gè) object 的當(dāng)前狀態(tài);

這種統(tǒng)一 API 提供了幾方面好處:

  • 學(xué)習(xí)更加簡(jiǎn)單,因?yàn)樗?object 都遵循同一套規(guī)范和模板;
  • 編寫適用于所有 object 的通用工具也更簡(jiǎn)單;
  • 用戶體驗(yàn)更加一致。

3.4.3 K8s API 擴(kuò)展性和一致性

基于前輩 Borg 和 Omega 的經(jīng)驗(yàn),K8s 構(gòu)建在一些可組合的基本構(gòu)建模塊之上,用戶可以方便地進(jìn)行擴(kuò)展, 通用 API 和 object-metadata 設(shè)計(jì)使得這種擴(kuò)展更加方便。例如,pod API 可以被開發(fā)者、K8s 內(nèi)部組件和外部自動(dòng)化工具使用。

為了進(jìn)一步增強(qiáng)這種一致性,K8s 還進(jìn)行了擴(kuò)展,支持用戶動(dòng)態(tài)注冊(cè)他們自己的 API, 這些 API 和它內(nèi)置的核心 API 使用相同的方式工作。另外,我們還通過解耦 K8s API 實(shí)現(xiàn)了一致性(consistency)。API 組件的解耦考慮意味著上層服務(wù)可以共享相同的基礎(chǔ)構(gòu)建模塊。一個(gè)很好的例子:replica controller 和 horizontal auto-scaling (HPA) 的解耦。

Replication controller 確保給定角色(例如,”front end”)的 pod 副本數(shù)量符合預(yù)期;Autoscaler 這利用這種能力,簡(jiǎn)單地調(diào)整期望的 pod 數(shù)量,而無需關(guān)心這些 pod 是如何創(chuàng)建或刪除的。autoscaler 的實(shí)現(xiàn)可以將關(guān)注點(diǎn)放在需求和使用量預(yù)測(cè)上,而無需關(guān)心這些決策在底層的實(shí)現(xiàn)細(xì)節(jié)。

解耦確保了多個(gè)相關(guān)但不同的組件看起來和用起來是類似的體驗(yàn),例如,k8s 有三種不同類似的 replicated pods:

ReplicationController: run-forever replicated containers (e.g., web servers).
DaemonSet: ensure a single instance on each node in the cluster (e.g., logging agents).
Job: a run-to-completion controller that knows how to run a (possibly parallelized) batch job from start to finish.

這三種 pod 的策略不同,但這三種 controller 都依賴相同的 pod object 來指定它們希望運(yùn)行的容器。

3.4.4 Reconcile 機(jī)制

我們還通過讓不同 k8s 組件使用同一套設(shè)計(jì)模式來實(shí)現(xiàn)一致性。Borg、Omega 和 k8s 都用到了 reconciliation controller loop 的概念,提高系統(tǒng)的容錯(cuò)性。

首先對(duì)觀測(cè)到的當(dāng)前狀態(tài)(“當(dāng)前能找到的這種 pod 的數(shù)量”)和期望狀態(tài)(“l(fā)abel-selector 應(yīng)該選中的 pod 數(shù)量”)進(jìn)行比較;如果當(dāng)前狀態(tài)和期望狀態(tài)不一致,則執(zhí)行相應(yīng)的行動(dòng) (例如擴(kuò)容 2 個(gè)新實(shí)例)來使當(dāng)前狀態(tài)與期望相符,這個(gè)過程稱為 reconcile(調(diào)諧)。

由于所有操作都是基于觀察(observation)而非狀態(tài)機(jī), 因此 reconcile 機(jī)制非常健壯:每次一個(gè) controller 掛掉之后再起來時(shí), 能夠接著之前的狀態(tài)繼續(xù)工作。

3.4.5 舞蹈編排(choreography)vs. 管弦樂編排(orchestration)

K8s 的設(shè)計(jì)綜合了 microservice 和 small control loop 的理念,這是 choreography(舞蹈編排)的一個(gè)例子 —— 通過多個(gè)獨(dú)立和自治的實(shí)體之間的協(xié)作(collaborate)實(shí)現(xiàn)最終希望達(dá)到的狀態(tài)。

  • 舞蹈編排:場(chǎng)上沒有指揮老師,每個(gè)跳舞的人都是獨(dú)立個(gè)體,大家共同協(xié)作完成一次表演。代表分布式、非命令式。

我們特意這么設(shè)計(jì),以區(qū)別于管弦樂編排中心式編排系統(tǒng)(centralized orchestration system),后者在初期很容易設(shè)計(jì)和開發(fā), 但隨著時(shí)間推移會(huì)變得脆弱和死板,尤其在有狀態(tài)變化或發(fā)生預(yù)期外的錯(cuò)誤時(shí)。

  • 管弦樂編排:場(chǎng)上有一個(gè)指揮家,每個(gè)演奏樂器的人都是根據(jù)指揮家的命令完成演奏。代表集中式、命令式。

4 避坑指南

這里列舉一些經(jīng)驗(yàn)教訓(xùn),希望大家要犯錯(cuò)也是去犯新錯(cuò),而不是重復(fù)踩我們已經(jīng)踩過的坑。

4.1 創(chuàng)建 Pod 時(shí)應(yīng)該分配唯一 IP,而不是唯一端口(port)

在 Borg 中,容器沒有獨(dú)立 IP,所有容器共享 node 的 IP。因此, Borg 只能在調(diào)度時(shí),給每個(gè)容器分配唯一的 port。當(dāng)一個(gè)容器漂移到另一臺(tái) node 時(shí),會(huì)獲得一個(gè)新的 port(容器原地重啟也可能會(huì)分到新 port)。這意味著,

  • 類似 DNS(運(yùn)行在 53 端口)這樣的傳統(tǒng)服務(wù),只能用一些內(nèi)部魔改的版本;

  • 客戶端無法提前知道一個(gè) service 的端口,只有在 service 創(chuàng)建好之后再告訴它們;

  • URL 中不能包含 port(容器重啟 port 可能就變了,導(dǎo)致 URL 無效),必須引入一些 name-based redirection 機(jī)制;

  • 依賴 IP 地址的工具都必須做一些修改,以便能處理 IP:port。

  • 因此在設(shè)計(jì) k8s 時(shí),我們決定給每個(gè) pod 分配一個(gè) IP,這樣就實(shí)現(xiàn)了網(wǎng)絡(luò)身份(IP)與應(yīng)用身份(實(shí)例)的一一對(duì)應(yīng);

  • 避免了前面提到的魔改 DNS 等服務(wù)的問題,應(yīng)用可以隨意使用 well-known ports(例如,HTTP 80);

  • 現(xiàn)有的網(wǎng)絡(luò)工具(例如網(wǎng)絡(luò)隔離、帶寬控制)也無需做修改,直接可以用;

此外,所有公有云平臺(tái)都提供 IP-per-pod 的底層能力;在 bare metal 環(huán)境中,可以使用 SDN overlay 或 L3 routing 來實(shí)現(xiàn)每個(gè) node 上多個(gè) IP 地址。

4.2 容器索引不要用數(shù)字 index,用 labels

用戶一旦習(xí)慣了容器開發(fā)方式,馬上就會(huì)創(chuàng)建一大堆容器出來, 因此接下來的一個(gè)需求就是如何對(duì)這些容器進(jìn)行分組和管理。

4.2.1 Borg 基于 index 的容器索引設(shè)計(jì)

Borg 提供了 jobs 來對(duì)容器名字相同的 tasks 進(jìn)行分組。

每個(gè) job 由一個(gè)或多個(gè)完全相同的 task 組成,用向量(vector)方式組織,從 index=0 開始索引。

這種方式非常簡(jiǎn)單直接,很好用,但隨著時(shí)間推移,我們?cè)絹碓桨l(fā)覺它比較死板。例如,

  • 一個(gè) task 掛掉后在另一臺(tái) node 上被創(chuàng)建出來時(shí),task vector 中對(duì)應(yīng)這個(gè) task 的 slot 必須做雙份的事情:識(shí)別出新的 task;在需要 debug 時(shí)也能指向老的 task;
  • 當(dāng) task vector 中間某個(gè) task 正常退出之后,vector 會(huì)留下空洞;
  • vector 也很難支持跨 Borg cluster 的 job;
  • 應(yīng)用如何使用 task index(例如,在 tasks 之間做數(shù)據(jù)的 sharding/partitioning) 和 Borg 的 job-update 語義(例如,默認(rèn)是滾動(dòng)升級(jí)時(shí)按順序重啟 task)之間,也存在一些不明朗之處:如果用戶基于 task index 來設(shè)計(jì) sharding,那 Borg 的重啟策略就會(huì)導(dǎo)致數(shù)據(jù)不可用,因?yàn)樗际前?task 順序重啟的;
  • Borg 還沒有很好的方式向 job 添加 application-relevant metadata, 例如 role (e.g. “frontend”)、rollout status (e.g. “canary”), 因此用戶會(huì)將這些信息編碼到 job name 中,然后自己再來解析 job name。

4.2.2 K8s 基于 label 的容器索引設(shè)計(jì)

作為對(duì)比,k8s 主要使用 labels 來識(shí)別一組容器(groups of containers)。

  • Label 是 key/value pair,包含了可以用來鑒別這個(gè) object 的信息;例如,一個(gè) pod 可能有 role=frontend 和 stage=production 兩個(gè) label,表明這個(gè)容器運(yùn)行的是生產(chǎn)環(huán)境的前端應(yīng)用;

  • Label 可以動(dòng)態(tài)添加、刪除和修改,可以通過工具或用戶手動(dòng)操作;

  • 不同團(tuán)隊(duì)可以管理各自的 label,基本可以做到不重疊;

  • 可以通過 label selector (例如,stage==production && role==frontend)來選中一組 objects;

  • 組可以重合,也就是一個(gè) object 可能出現(xiàn)在多個(gè) label selector 篩選出的結(jié)果中,因此這種基于 label 的方式更加靈活;

  • label selector 是動(dòng)態(tài)查詢語句,也就是說只要用戶有需要,他們隨時(shí)可以按自己的需求編寫新的查詢語句(selector);

  • Label selector 是 k8s 的 grouping mechanism,也定義了所有管理操作的范圍(多個(gè) objects)。

在某些場(chǎng)景下,能精確(靜態(tài))知道每個(gè) task 的 identity 是很有用的(例如,靜態(tài)分配 role 和 sharding/partitioning), 在 k8s 中,通過 label 方式也能實(shí)現(xiàn)這個(gè)效果,只要給每個(gè) pod 打上唯一 label 就行了, 但打這種 label 就是用戶(或 k8s 之上的某些管理系統(tǒng))需要做的事情了。

Labels 和 label selectors 提供了一種通用機(jī)制, 既保留了 Borg 基于 index 索引的能力,又獲得了上面介紹的靈活性。

4.3 Ownership 設(shè)計(jì)要格外小心

  • 在 Borg 中,task 并不是獨(dú)立于 job 的存在:

  • 創(chuàng)建一個(gè) job 會(huì)創(chuàng)建相應(yīng)的 tasks,這些 tasks 永遠(yuǎn)與這個(gè) job 綁定;

  • 刪除這個(gè) jobs 時(shí)會(huì)刪除它所有的 tasks。

這種方式很方便,但有一個(gè)嚴(yán)重不足:Borg 中只有一種 grouping 機(jī)制,也就是前面提到的 vector index 方式。例如,一個(gè) job 需要存儲(chǔ)某個(gè)配置參數(shù),但這個(gè)參數(shù)只對(duì) service 或 batch job 有用,并不是對(duì)兩者都有用。當(dāng)這個(gè) vector index 抽象無法滿足某些場(chǎng)景(例如, DaemonSet 需要將一個(gè) pod 在每個(gè) node 上都起一個(gè)實(shí)例)時(shí), 用戶必須開發(fā)一些 workaround。

Kubernetes 中,那些 pod-lifecycle 管理組件 —— 例如 replication controller —— 通過 label selector 來判斷哪些 pod 歸自己管;但這里也有個(gè)問題:多個(gè) controller 可能會(huì)選中同一個(gè) pod,認(rèn)為這個(gè) pod 都應(yīng)該歸自己管, 這種沖突理應(yīng)在配置層面解決。

label 的靈活性帶來的好處:例如, controller 和 pod 分離意味著可以 "orphan" 和 "adopt" container。考慮一個(gè) service, 如果其中一個(gè) pod 有問題了,那只需要把相應(yīng)的 label 從這個(gè) pod 上去掉, k8s service 就不會(huì)再將流量轉(zhuǎn)發(fā)給這個(gè) pod。這個(gè) pod 不再接生產(chǎn)流量,但仍然活在線上,因此就可以對(duì)它進(jìn)行 debug 之類的。而與此同時(shí),負(fù)責(zé)管理這些 pod 的 replication controller 就會(huì)立即再創(chuàng)建一個(gè)新的 pod 出來接流量。

4.4 不要暴露原始狀態(tài)

Borg、Omega 和 k8s 的一個(gè)核心區(qū)別是它們的 API 架構(gòu)。

  • Borgmaster 是一個(gè)單體組件,理解每個(gè) API 操作的語義:

  • 包含集群管理邏輯,例如 job/task/machine 的狀態(tài)機(jī);

運(yùn)行基于 Paxos 的 replicated storage system,用來存儲(chǔ) master 的狀態(tài)。Omega 除了 store 之外沒有中心式組件,

  • store 存儲(chǔ)了 passive 狀態(tài)信息,執(zhí)行樂觀并發(fā)控制;
  • 所有邏輯和語義都下放到了操作 store 的 client 上,后者會(huì)直接讀寫 store 內(nèi)容;

實(shí)際上,每個(gè) Omega 組件都使用了同一套 client-side library 來與 store 交互, 這個(gè) liabrary 做的事情包括 packing/unpacking of data structures、retries、 enforce semantic consistency。

k8s 在 Omega 的分布式架構(gòu)和 Borg 的中心式架構(gòu)之間做了一個(gè)折中,在繼承 Omega 分布式架構(gòu)的靈活性和擴(kuò)展性的同時(shí),對(duì)系統(tǒng)級(jí)別的規(guī)范、策略、數(shù)據(jù)轉(zhuǎn)換等方面還是集中式的;實(shí)現(xiàn)方式是在 store 前面加了一層集中式的 API server,屏蔽掉所有 store 實(shí)現(xiàn)細(xì)節(jié), 提供 object validation、defaulting 和 versioning 服務(wù)。與 Omega 類似,客戶端組件都彼此獨(dú)立,可以獨(dú)立開發(fā)、升級(jí)(在開源場(chǎng)景尤其重要), 但各組件都要經(jīng)過 apiserver 這個(gè)中心式服務(wù)的語義、規(guī)范和策略。

5 開放問題討論

雖然我們已經(jīng)了十幾年的大規(guī)模容器管理經(jīng)驗(yàn),但仍然有些問題還沒有很好的解決辦法。本節(jié)介紹幾個(gè)供討論,集思廣益。

5.1 應(yīng)用配置管理

在我們面臨的所有問題中,耗費(fèi)了最多腦力、頭發(fā)和代碼的是管理配置(configurations)相關(guān)的。這里的配置指的是應(yīng)用配置,即如何把應(yīng)用的參數(shù)在創(chuàng)建容器時(shí)傳給它, 而不是 hard-code。這個(gè)主題值得單獨(dú)一整篇文章來討論,這里僅 highlight 幾方面。

  • 首先,Borg 仍然缺失的那些功能,最后都能與應(yīng)用配置(application configuration)扯上關(guān)系。這些功能包括:

  • Boilerplate reduction:例如,根據(jù) workload 類型等信息為它設(shè)置默認(rèn)的 restart policy;

  • 調(diào)整和驗(yàn)證應(yīng)用參數(shù)和命令行參數(shù);

  • 實(shí)現(xiàn)一些 workaround,解決容器鏡像管理 API 缺失的問題;

  • 給應(yīng)用用的函數(shù)庫(kù)和配置魔板;

  • 發(fā)布管理工具;

  • 容器鏡像版本規(guī)范;

為了滿足這些需求,配置管理系統(tǒng)傾向于發(fā)明一種 domain-specific 語言, 并希望最終成為一門圖靈完備的配置語言:解析配置文件,提取某些數(shù)據(jù),然后執(zhí)行一些計(jì)算。例如,根據(jù)一個(gè) service 的副本數(shù)量,利用一個(gè)函數(shù)自動(dòng)調(diào)整分給一個(gè)副本的內(nèi)存。用戶的需求是減少代碼中的 hardcode 配置,但最終的結(jié)果是一種難以理解和使用的“配置即代碼”產(chǎn)品,用戶避之不及。它沒有減少運(yùn)維復(fù)雜度,也沒有使配置的 debug 變得更簡(jiǎn)單;它只是將計(jì)算從一門真正的 編程語言轉(zhuǎn)移到了一個(gè) domain-specific 語言,而后者通常的配置開發(fā)工具更弱 (例如 debuggers, unit test frameworks 等)。

我們認(rèn)為最有效的方式是接受這個(gè)需求,承認(rèn) programmatic configuration 的不可避免性, 在計(jì)算和數(shù)據(jù)之間維護(hù)一條清晰邊界。表示數(shù)據(jù)的語言應(yīng)該是簡(jiǎn)單、data-only 的格式,例如 JSON or YAML, 而針對(duì)這些數(shù)據(jù)的計(jì)算和修改應(yīng)該在一門真正的編程語言中完成,后者有 完善的語義和配套工具。

有趣的是,這種計(jì)算與數(shù)據(jù)分離的思想已經(jīng)在其他領(lǐng)域開始應(yīng)用,例如一些前端框架的開發(fā), 比如 Angular 在 markup (data) 和 JavaScript (computation) 之間。

5.2 依賴管理

上線一個(gè)新服務(wù)通常也意味著需要上線一系列相關(guān)的服務(wù)(監(jiān)控、存儲(chǔ)、CI/CD 等等)。如果一個(gè)應(yīng)用依賴其他一些應(yīng)用,那由集群管理系統(tǒng)來自動(dòng)化初始化后者(以及它們的依賴)不是很好嗎?

但事情并沒有這么簡(jiǎn)單:自動(dòng)初始化依賴(dependencies)并不是僅僅啟動(dòng)一個(gè)新實(shí)例 —— 例如,可能還需要將其注冊(cè)為一個(gè)已有服務(wù)的消費(fèi)者, (e.g., Bigtable as a service),以及將認(rèn)證、鑒權(quán)和賬單信息傳遞給這些依賴系統(tǒng)。

但幾乎沒有哪個(gè)系統(tǒng)收集、維護(hù)或暴露這些依賴信息,因此即使是一些常見場(chǎng)景都很難在基礎(chǔ)設(shè)施層實(shí)現(xiàn)自動(dòng)化。上線一個(gè)新應(yīng)用對(duì)用戶來說仍然是一件復(fù)雜的事情,導(dǎo)致開發(fā)者構(gòu)建新服務(wù)更困難, 經(jīng)常導(dǎo)致最新的最佳實(shí)踐無法用上,從而影響新服務(wù)的可靠性。

一個(gè)常見問題是:如果依賴信息是手工提供的,那很難維持它的及時(shí)有效性, 與此同時(shí),自動(dòng)判斷(例如,通過 tracing accesses)通常會(huì)失敗,因?yàn)闊o法捕捉理解相應(yīng)結(jié)果的語義信息。(Did that access have to go to that instance, or would any instance have sufficed?)

一種可能的解決方式是:每個(gè)應(yīng)用顯式聲明它依賴的服務(wù),基礎(chǔ)設(shè)施層禁止它訪問除此之外的所有服務(wù) (我們的構(gòu)建系統(tǒng)中,編譯器依賴就是這么做的1)。好處就是基礎(chǔ)設(shè)施能做一些有益的工作,例如自動(dòng)化設(shè)置、認(rèn)證和連接性。

不幸的是,表達(dá)、分析和使用系統(tǒng)依賴會(huì)導(dǎo)致系統(tǒng)的復(fù)雜性升高, 因此并沒有任何一個(gè)主流的容器管理系統(tǒng)做了這個(gè)事情。我們?nèi)匀幌M?k8s 能成為一個(gè)構(gòu)建此類工具的平臺(tái),但這一工作目前仍困難重重。

6 總結(jié)

過去十多年開發(fā)容器管理系統(tǒng)的經(jīng)歷教會(huì)了我們很多東西,我們也將這些經(jīng)驗(yàn)用到了 k8s —— Google 最新的容器管理系統(tǒng) —— 的設(shè)計(jì)中, 它的目標(biāo)是基于容器提供的各項(xiàng)能力,顯著提升開發(fā)者效率,以及使系統(tǒng)管理(不管是手動(dòng)還是自動(dòng))更加方便。希望大家能與我們一道,繼續(xù)完善和優(yōu)化它。

參考資料

  1. Bazel: {fast, correct}—choose two; http://bazel.io.
  2. Burrows, M. 2006. The Chubby lock service for loosely coupled distributed systems. Symposium on Operating System Design and Implementation (OSDI), Seattle, WA.
  3. cAdvisor; https://github.com/google/cadvisor.
  4. Kubernetes; http://kubernetes.io/.
  5. Metz, C. 2015. Google is 2 billion lines of code—and it’s all in one place. Wired (September); http://www.wired.com/2015/09/google-2-billion-lines-codeand-one-place/.
  6. Schwarzkopf, M., Konwinski, A., Abd-el-Malek, M., Wilkes, J. 2013. Omega: flexible, scalable schedulers for large compute clusters. European Conference on Computer Systems (EuroSys), Prague, Czech Republic.
  7. Verma, A., Pedrosa, L., Korupolu, M. R., Oppenheimer, D., Tune, E., Wilkes, J. 2015. Large-scale cluster management at Google with Borg. European Conference on Computer Systems (EuroSys), Bordeaux, France.
責(zé)任編輯:武曉燕 來源: 云原生技術(shù)愛好者社區(qū)
相關(guān)推薦

2015-08-10 14:59:37

MesosOmegaBorg

2013-09-03 11:12:19

災(zāi)難恢復(fù)災(zāi)備萬國(guó)數(shù)據(jù)

2011-08-23 10:49:44

算法

2022-06-01 09:38:36

KubernetesPod容器

2014-08-25 15:01:03

Google

2022-09-09 08:11:23

IT科技生態(tài)系統(tǒng)

2021-05-10 07:30:33

Google技術(shù)谷歌

2023-07-04 07:30:03

容器Pod組件

2015-04-30 11:11:47

硅谷動(dòng)力

2023-09-07 08:58:36

K8s多集群

2012-06-19 09:50:16

2010-11-17 11:02:49

思科Juniper

2019-12-13 16:08:57

戴爾

2014-10-10 13:57:17

程序員

2022-04-22 13:32:01

K8s容器引擎架構(gòu)

2023-11-06 07:16:22

WasmK8s模塊

2009-11-30 09:16:30

Windows 7電池續(xù)航

2017-11-21 10:11:19

陌陌K8sDocker

2023-01-04 17:42:22

KubernetesK8s
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品国产精品国产专区不卡 | 人操人人干人 | 亚洲免费观看视频网站 | 国产片网站 | 亚洲成人午夜电影 | 国产一区二区三区日韩 | 色视频网站免费 | 成人国产一区二区三区精品麻豆 | 在线中文视频 | av在线黄 | 免费看黄色视屏 | 天天综合永久 | www国产成人免费观看视频,深夜成人网 | 香蕉大人久久国产成人av | 日韩视频一区二区在线 | 午夜视频在线免费观看 | 91亚洲国产成人精品一区二三 | 亚洲视频在线免费观看 | 国产乱一区二区三区视频 | 国产成人在线一区二区 | 人人干人人干人人干 | 国产欧美日韩在线观看 | 国产成人高清 | av免费网 | 国产精品1区 | 欧美黄色一区 | 久久久久亚洲 | 亚洲深夜福利 | 91av久久久 | 国产精品成人一区二区三区 | 亚洲国产精品一区二区久久 | 久久久91精品国产一区二区三区 | 欧美激情精品久久久久 | 在线看亚洲 | 一级a性色生活片久久毛片波多野 | 免费国产一区 | 日韩午夜在线观看 | 亚洲一区二区三区久久 | av电影一区| 欧美8一10sex性hd | 国产小视频在线 |