99精品免费久久久久久久久日本|日韩精品首页|日本三级免费电影|国产成人高清亚洲一区app|狠狠操社区

數(shù)千臺(tái)設(shè)備的軟件和操作系統(tǒng),每?jī)芍苌?jí)一次,這是怎么做到的

2019-09-30

1000 (1).jpg


任何曾經(jīng)管理過幾十上百臺(tái)物理服務(wù)器的人都知道:確保所有服務(wù)器始終安裝最新安全更新,或者保證所有服務(wù)器的配置和狀態(tài)相一致,這始終是一件很難完成的任務(wù)。為了解決這個(gè)問題,系統(tǒng)管理員通常會(huì)使用 Puppet 、 Salt 等工具,或?qū)?yīng)用程序部署到容器中。如果整個(gè)環(huán)境都能由你控制,這些當(dāng)然都是很棒的方法,但如果你使用了類似 BCDR 一體機(jī)之類的設(shè)備(或者任何未部署在自己基礎(chǔ)架構(gòu)內(nèi)的一體機(jī) / 服務(wù)器設(shè)施),這些方法往往就不怎么實(shí)用了。除此之外,替換系統(tǒng)內(nèi)核、安裝大型系統(tǒng)升級(jí),或安裝其他需要重啟的大型補(bǔ)丁,此時(shí)也無法適用這些方法。

當(dāng)我們使用的 BCDR 設(shè)備面臨這些問題后,我們開始尋找其他更可行的方法,并且真的有所收獲。近兩年來,我們?yōu)槌^ 80,000 臺(tái)設(shè)備使用了這種方法,效果一直很穩(wěn)定。本文我將談?wù)勎覀兪侨绾瓮ㄟ^鏡像、回環(huán)設(shè)備(Loop device)以及大量和 Grub 有關(guān)的“魔法”解決這個(gè)問題的。如果對(duì)此話題感興趣,歡迎繼續(xù)閱讀下去。

1

從頭到尾使用 Debian 軟件包?

我們的 BCDR 一體機(jī)始終運(yùn)行了 Ubuntu,因此在更新軟件時(shí),最自然的方法就是使用 Debian 軟件包。過去很長(zhǎng)時(shí)間以來都是這樣做的:每?jī)芍埽覀儠?huì)為 Ubuntu 10.04/12.04(沒錯(cuò),我知道你有疑問,請(qǐng)繼續(xù)讀下去!)構(gòu)建所需的發(fā)布,經(jīng)過全面測(cè)試后將其正式部署出去。

很長(zhǎng)時(shí)間以來這樣做完全沒問題,但這種做法有一些很明顯的不足之處:

第三方依賴項(xiàng)的更新:使用少量 Debian 軟件包,這容易讓人覺得只需要為自己的軟件負(fù)責(zé),而不需要為一體機(jī)中運(yùn)行的其他軟件負(fù)責(zé)。如果你只使用了自己的 datto.deb,但此時(shí) Apache、Samba、libc 甚至 PHP 的更新管理工作其實(shí)同樣重要。鑒于我們作為 Datto,本身所銷售的就是完整的一體機(jī),當(dāng)然也就需要負(fù)責(zé)管理整個(gè)棧,尤其是第三方軟件的安全補(bǔ)丁等內(nèi)容。

服務(wù)重啟動(dòng) / 重引導(dǎo):對(duì)于一些需要重啟動(dòng)服務(wù)甚至重引導(dǎo)計(jì)算機(jī)的大型更新,依賴項(xiàng)問題也會(huì)變得異常棘手。當(dāng)然,Debian 軟件包自己就應(yīng)該能處理服務(wù)重啟動(dòng)問題,但實(shí)際上并非所有軟件包都能妥善搞定。并且一旦需要重引導(dǎo)(例如需要升級(jí)系統(tǒng)內(nèi)核),還需要確保不會(huì)打斷重要的設(shè)備任務(wù)(例如備份、虛擬化……),此外還要保證設(shè)備最終能引導(dǎo)成功(這事情并不像你想的那么容易,下文將會(huì)詳細(xì)介紹!)。

發(fā)行版升級(jí):如果整個(gè)操作系統(tǒng)的版本需要升級(jí),這才是最麻煩的地方。舉例來說,如果只使用 apt-get dist-upgrade 命令以及 reboot 命令將 Ubuntu 10.04 升級(jí)到 16.04,整個(gè)過程將變得漫長(zhǎng)無比,并且很多時(shí)候可能會(huì)升級(jí)失敗(只要你用過 usedapt-get dist-upgrade,那么肯定會(huì)明白)。

數(shù)千個(gè)版本和狀態(tài):在 Debian 的升級(jí)模型中,“設(shè)備”的實(shí)際行為其實(shí)和普通計(jì)算機(jī)無異:剛剛創(chuàng)建好鏡像并部署后,一切都是嶄新的,一切都可以正常運(yùn)轉(zhuǎn)。但隨著鏡像越來越老,操作系統(tǒng)退化的問題就變得越嚴(yán)峻,導(dǎo)致不同設(shè)備的狀態(tài)產(chǎn)生巨大差異。能嚴(yán)重到什么程度?我們的設(shè)備(在切換到 KVM 前)曾經(jīng)使用了 40 個(gè)不同版本的 VirtualBox、25 個(gè)不同的 ZFS 版本,以及超過 80 個(gè)不同的 Linux 內(nèi)核!

其實(shí),實(shí)際遇到的問題遠(yuǎn)比上面列出的更多,不過這里就不拿更多問題來給大家添堵了。快速開始介紹最有趣的內(nèi)容:如何解決!

2

使用鏡像,而非軟件包!

鑒于會(huì)遇到這么多問題,很明顯,我們需要用更好的解決方案來管理設(shè)備狀態(tài)和配置。產(chǎn)品中不同的設(shè)備配置 / 軟件包 / 版本數(shù)量不僅要降至最低,并且在每次升級(jí)時(shí)必需能保證能夠升級(jí)整個(gè)棧:不僅要能升級(jí)我們自己的軟件,還要能升級(jí)第三方軟件,甚至諸如 Libc 或系統(tǒng)內(nèi)核等系統(tǒng)庫。

3

前提要求

隨后我們開始確定這個(gè)解決方案的前提要求,其實(shí)這些要求并不多:

所有設(shè)備沿用相同的升級(jí)路徑,并且只存在一個(gè)升級(jí)路徑。

所有設(shè)備均可通過這種方式升級(jí)(哪怕操作系統(tǒng)盤較小的老設(shè)備)。

從一個(gè)版本切換到另一個(gè)版本的過程必需滿足原子性要求(或盡可能滿足這種要求)。(如果升級(jí)失敗)能夠回滾到上一個(gè)版本。而這些要求還暗含了一個(gè)最重要的前提條件:不能繼續(xù)使用基于軟件包的升級(jí)方法了,并且(從字里行間也能體會(huì)到)在升級(jí)過程中重引導(dǎo)一體機(jī),這是可以接受的。

這些都是很大膽的念頭。我們確實(shí)做出了一個(gè)重大決定!

4

那么鏡像到底是什么?

為了減少配置的數(shù)量,我們決定不再將我們的軟件及其所有依賴項(xiàng)看作不同個(gè)體,而是將所有這一切組合成一個(gè)統(tǒng)一的可交付物:鏡像。

那么鏡像到底是什么?鏡像(在我們的環(huán)境中)是指一種 EXT4 文件系統(tǒng),其中包含了引導(dǎo)和運(yùn)行 BCDR 一體機(jī)所需的一切,例如:

Ubuntu 基礎(chǔ)操作系統(tǒng)(內(nèi)核、系統(tǒng)庫……)

必需的第三方工具和庫(Apache、KVM、ZFS……)

Datto 設(shè)備軟件(我們的營(yíng)銷團(tuán)隊(duì)將其稱之為 IRIS)

下圖就顯示了一個(gè)這種鏡像所包含的內(nèi)容:


我們對(duì)這種想法非常激動(dòng),因?yàn)橥ㄟ^使用鏡像,只需要一個(gè)數(shù)字,也就是鏡像的版本號(hào)(例如上圖中的“415”)就可以定義所安裝的每個(gè)軟件的具體版本。再也不用針對(duì)多種 ZFS 版本測(cè)試我們的軟件,更不用暗自祈禱我們的軟件能兼容所有 KVM 版本。太棒了!

5

基于鏡像的升級(jí)

做出所有這些重要決定后,我們依然需要通過某種方法來構(gòu)建、分發(fā),并在設(shè)備上引導(dǎo)這些鏡像。具體怎么做呢?

構(gòu)建鏡像

通常來說,每次標(biāo)記了一個(gè)新的發(fā)布(或發(fā)布候選)后,我們會(huì)自動(dòng)構(gòu)建鏡像:每次在 Git 中推送標(biāo)簽后,一個(gè) CI 工作進(jìn)程會(huì)開始構(gòu)建鏡像。構(gòu)建過程本身也挺有趣,不過已經(jīng)超出了本文的范圍,但為了不吊大家胃口,下文將簡(jiǎn)單介紹這個(gè)過程:

我們首先會(huì)為自己的軟件構(gòu)建 Debian 軟件包,并將其發(fā)布至一個(gè) Debian 倉庫。隨后使用 aptly (參閱“Datto packages”一圖)為這個(gè) Debian 倉庫創(chuàng)建快照,同時(shí)還會(huì)定期對(duì)一個(gè)上游 Ubuntu 倉庫(“Upstream packages”)執(zhí)行類似操作。隨后使用 debootstrap 創(chuàng)建一個(gè) Ubuntu 基準(zhǔn)系統(tǒng),并將我們的所有軟件及其依賴項(xiàng)安裝到一個(gè) Chroot 中。一旦完成這些操作,會(huì)對(duì)其創(chuàng)建 Tar 歸檔并 Rsync 到我們自己的鏡像服務(wù)器。在鏡像服務(wù)器上,我們會(huì)提取出 Tarball 并 Rsync 給最新鏡像,這個(gè)最新鏡像位于一個(gè)格式化為 EXT4 文件系統(tǒng)的 ZFS 卷(zvol)中。在將所有未使用的 EXT4 塊歸零后,會(huì)對(duì)包含該文件系統(tǒng)的 zvol 創(chuàng)建最終快照。

因此在鏡像服務(wù)器上可以看到類似下圖所示的內(nèi)容:

上述 zvol 包含了我們 BCDR 一體機(jī)的 EXT4 文件系統(tǒng)。這就是一個(gè)鏡像,也是我們唯一需要交付的東西。它可以作為一個(gè)整體進(jìn)行測(cè)試,一旦通過了 QA 流程,就可以分發(fā)到客戶的 BCDR 設(shè)備中了。

分發(fā)鏡像

在成功構(gòu)建鏡像后,又該如何將其從我們的數(shù)據(jù)中心發(fā)送給超過 8 萬臺(tái)設(shè)備?很簡(jiǎn)單,我們使用了 ZFS send/recv !

我們的所有設(shè)備都具備 ZFS 池,其中存儲(chǔ)了設(shè)備的鏡像備份,并且之前我們就在大量使用 ZFS send/recv 為這些備份提供離場(chǎng)保存能力。而此時(shí)只不過是換種方向使用這種技術(shù)。

我們是這樣做的:需要升級(jí)時(shí),會(huì)讓一部設(shè)備通過 HTTPS 下載 ZFS sendfile diff(之前曾經(jīng)嘗試過直接通過 SSH 使用 ZFS send/recv,但這種方式無法進(jìn)行緩存):

從上圖中可以看到,通常并不需要下載完整鏡像,因?yàn)樵O(shè)備以前就升級(jí)過,已經(jīng)在本地池中保存了鏡像的一個(gè)版本。這就很棒了:通過這種技術(shù),我們可以進(jìn)行差異化的操作系統(tǒng)升級(jí),也就是說,設(shè)備只需要下載鏡像中有變化的塊。

這是一種雙贏的結(jié)果,因?yàn)椴粫?huì)過多占用客戶網(wǎng)絡(luò)帶寬,而我們自己的數(shù)據(jù)中心也可以節(jié)約一筆帶寬費(fèi)用。

下載好的鏡像會(huì)被導(dǎo)入本地 ZFS 池。這對(duì)于下一次升級(jí)很必要(可以確保只需要下載有變化的內(nèi)容):

引導(dǎo)鏡像

拿到鏡像后,如何引導(dǎo)至這個(gè)新的文件系統(tǒng)?如果我們構(gòu)建的每個(gè)鏡像版本都是全新操作系統(tǒng),又該如何從一個(gè)版本引導(dǎo)至下一個(gè)版本?

6

ZFS-on-root、A/B 分區(qū)和 A/B 文件夾

毫無疑問,這些問題的答案并不只有一種。我們可以通過多種方法使用鏡像生成可引導(dǎo)的系統(tǒng),因此需要多次實(shí)驗(yàn)找出一種最佳方法。

這個(gè)過程也很有趣,因此我準(zhǔn)備簡(jiǎn)要介紹每種方法,以及最終未選擇這些方法的原因:

ZFS-on-root 和 A/B 數(shù)據(jù)集:我們的鏡像備份操作中大量使用了 ZFS,因此一開始很自然就覺得也可以將 ZFS 用作一體機(jī)的根文件系統(tǒng)。為此可以將 BCDR 一體機(jī)的鏡像作為一個(gè) ZFS 數(shù)據(jù)集(而非上文提到的 zvol)來進(jìn)行分發(fā),對(duì)其進(jìn)行克隆并直接引導(dǎo)至 ZFS 的克隆副本。由于 Grub 的新版本已經(jīng)可以支持讀取 ZFS,此外還提供了 ZFS initramfs 模塊,ZFS-on-root 絕對(duì)是可行的。如果要從一個(gè)鏡像升級(jí)到下一個(gè)(例如從一個(gè) ZFS 數(shù)據(jù)集升級(jí)到下一個(gè)),只需要更新 Grub 的配置并重引導(dǎo)就行。這種方式可以正常起效,但因?yàn)橐龑?dǎo)至 ZFS,這是一種比較新的做法,我們認(rèn)為其成熟度還不足以滿足我們產(chǎn)品的需求。不予考慮。

簡(jiǎn)單的 A/B 分區(qū):有些一體機(jī)和手機(jī)會(huì)使用兩個(gè)分區(qū),其中一個(gè)包含當(dāng)前系統(tǒng),另一個(gè)包含下一個(gè)系統(tǒng)。這種思路也很簡(jiǎn)單:下載新鏡像,將其 Rsync 到不活躍分區(qū),更新 Grub,然后重引導(dǎo)。然而這種做法的問題在于,我們的有些設(shè)備不具備額外創(chuàng)建一個(gè)分區(qū)所需的存儲(chǔ)空間(或者至少需要重建分區(qū))。我們?cè)趯?shí)驗(yàn)中嘗試過在首次重引導(dǎo)過程中,從 initramfs 內(nèi)部將活躍根分區(qū)拆分為兩個(gè)并且成功了(挺酷的對(duì)吧),但考慮到這將要用于我們的主要產(chǎn)品,該方法風(fēng)險(xiǎn)太大。不予考慮。

引導(dǎo)至 A/B 目錄:由于一些設(shè)備缺乏備用分區(qū),我們還實(shí)驗(yàn)過將鏡像的兩個(gè)副本保存到根分區(qū)中的兩個(gè)文件夾中(例如一個(gè) /images/412 和一個(gè) /images/415),隨后修改 initramfs 引導(dǎo)至 /images/415,而非引導(dǎo)至 /。不管你信不信,雖然聽起來挺瘋狂,但這樣做竟然也成功了,并且整個(gè)方法也超級(jí)簡(jiǎn)單,只要對(duì) initramfs 進(jìn)行少量修改:mount --bind /images/415 /root 改成這樣就行。一切都可以正常運(yùn)轉(zhuǎn),不過很多 Linux 工具(df、mount……)會(huì)因?yàn)楦夸洸皇?/ 而遇到一些問題,所以這個(gè)方法也不予考慮。

7

循環(huán)往復(fù),這就夠了!

在嘗試過用多種方法引導(dǎo)鏡像后,我們最終采取的做法似乎感覺有些無趣。不過無趣也是好事對(duì)吧!

我們發(fā)現(xiàn),如果要引導(dǎo)一個(gè)鏡像,最簡(jiǎn)單可靠的方法是利用 Grub 的回環(huán)引導(dǎo)(Loopback booting)機(jī)制,并配合 initramfs 對(duì) Loop 的支持(請(qǐng)參閱 loop=…參數(shù)):

眾所周知,Grub 是種引導(dǎo)加載器(Boot loader)。它的責(zé)任是加載初始的 RAM 磁盤和內(nèi)核。為此,Grub 內(nèi)置了對(duì)很多文件系統(tǒng)的讀取能力,并能通過 loopback 命令支持稍后將要提到的“文件系統(tǒng)中的文件系統(tǒng)”。loopback 命令可在根分區(qū)找到鏡像文件并對(duì)其進(jìn)行環(huán)回(Loop),這樣就可以照常使用 linux 和 initrd 命令找到內(nèi)核和 RAM 磁盤。例如我們?cè)谠O(shè)備 grub.cfg 文件中(通過 /etc/grub.d 中的鉤子)生成的菜單項(xiàng)范例如下所示:

在這個(gè)例子中,Grub 首先會(huì)通過 search 以及 UUID 尋找根分區(qū)(就像對(duì)常規(guī)安裝的 Ubuntu 做的那樣)。隨后會(huì)發(fā)現(xiàn)根分區(qū)中的鏡像文件 /images/415.0.img,最后找到鏡像中的內(nèi)核((loop)/vmlinuz)和 RAM 磁盤((loop)/initrd.img)。

整個(gè)過程異常簡(jiǎn)單,但同時(shí)卻非常酷:引導(dǎo)加載器竟然能這樣做,這一點(diǎn)讓我大為驚奇。

當(dāng) Grub 找到內(nèi)核和初始 RAM 磁盤后,會(huì)將 RAM 磁盤載入內(nèi)存(震驚!),隨后掛載根文件系統(tǒng),最后將控制權(quán)轉(zhuǎn)交給 init 進(jìn)程。

在 Ubuntu 中,initramfs-tools 軟件包提供了創(chuàng)建和修改初始 RAM 磁盤的工具。幸虧該軟件包已經(jīng)可以支持回環(huán)引導(dǎo)機(jī)制,因此一般來說除了需要在內(nèi)核行傳遞 loop= 參數(shù),其他什么都不用做。如果設(shè)置了該參數(shù),initramfs 會(huì)用回環(huán)的方式,使用 mount -o loop(參閱源代碼)將根文件系統(tǒng)加載至鏡像。考慮到代碼中有一條相當(dāng)嚇人的 FIXME 消息(# FIXME This has no error checking),我們認(rèn)為最好能提高它的彈性,為其增加錯(cuò)誤處理和 fsck 能力。不過大部分情況下,使用 initramfs 都可以順利引導(dǎo)并且不顯示任何信息。

就是這樣,一個(gè)簡(jiǎn)單的解決方案,洋洋灑灑寫了這么多。

這種方法在實(shí)踐中用起來是這樣的。如圖所示,該設(shè)備的根文件系統(tǒng)位于 /dev/loop0,該回環(huán)設(shè)備在 initramfs 中設(shè)置而來,指向了一個(gè)鏡像文件:

本例中,鏡像是位于根分區(qū)(如 /dev/sda1)下的 /images/412.0.img。請(qǐng)注意,如果鏡像中存在空的 /host 文件夾,initramfs 會(huì)將根分區(qū)掛載在這里:

8

鏡像間的升級(jí)

我們已經(jīng)可以構(gòu)建、分發(fā)并引導(dǎo)鏡像。如果將這一切結(jié)合在一起就會(huì)發(fā)現(xiàn),從一個(gè)鏡像到下一個(gè)鏡像的升級(jí)其實(shí)一點(diǎn)也不難:

清理老鏡像,下載新鏡像,導(dǎo)入到池,導(dǎo)出到鏡像文件。

將配置從當(dāng)前鏡像遷移到下一個(gè)鏡像。

更新 Grub 以指向新鏡像。

重引導(dǎo)。

我們所做的就是這樣。為此還開發(fā)了一個(gè)名為 upgradectl 的工具:


upgradectl 通常可由我們的簽入進(jìn)程遠(yuǎn)程觸發(fā):在設(shè)備正常運(yùn)轉(zhuǎn)的過程中,它可以下載并導(dǎo)出鏡像(第 1 步),借此在后臺(tái)為升級(jí)過程做準(zhǔn)備。需要進(jìn)行升級(jí)時(shí)(通常是夜間的設(shè)備閑置時(shí)段),實(shí)際的升級(jí)過程將非常快速地完成,因?yàn)橹恍枰w移配置,更新 Grub 并重引導(dǎo)(第 2-4 步)即可。一般來說,升級(jí)過程中的設(shè)備停機(jī)時(shí)間約為 5-10 分鐘,并且這主要取決于重引導(dǎo)所需的時(shí)間(大型設(shè)備可能需要更久,因?yàn)樾枰?IPMI/BMC 初始化)。

當(dāng)然,這一過程中也有數(shù)不勝數(shù)的問題和邊緣案例需要考慮:聽起來確實(shí)簡(jiǎn)單,但想要做對(duì)其實(shí)并不容易,尤其是考慮到我們現(xiàn)有的 8 萬臺(tái)一體機(jī)中,有些在生產(chǎn)環(huán)境中連續(xù)運(yùn)轉(zhuǎn)已經(jīng)有超過 7 年時(shí)間了。

但這也造就了一些有趣的挑戰(zhàn):我們已經(jīng)將數(shù)千臺(tái)設(shè)備從 Ubuntu 12.04(甚至 10.04)直接升級(jí)至 Ubuntu 16.04。如果升級(jí)過程因?yàn)槟承┰蚴。瑫?huì)通過一些邏輯來處理老鏡像的回滾。我們處理了完整的操作系統(tǒng)盤、有故障的硬件(磁盤、IPMI、RAM……)、配置為 RAID 的操作系統(tǒng)盤以及 Grub 無法向其中寫入的問題,當(dāng)然還有 ZFS 池出錯(cuò)、Linux 進(jìn)程掛起(D 狀態(tài))、重引導(dǎo)掛起等各種問題。

但是你猜怎樣:這一切都是值得的。這就好像結(jié)束了一場(chǎng)為期 7 年的寒冬之后進(jìn)行的春季大掃除。我們讓這些設(shè)備重新煥發(fā)了生機(jī),并且這樣的工作還將繼續(xù),每?jī)芍苓M(jìn)行一次!

9

總結(jié)

本文介紹了如何將 BCDR 一體機(jī)的部署流程由基于 Debian 軟件包的方法改為基于鏡像的方法。此外還介紹了構(gòu)建、分發(fā)鏡像的方法,以及如何使用 Grub 的 loopback 機(jī)制引導(dǎo)鏡像的做法。

雖然這種基于鏡像的升級(jí)方法的誕生有我的全程參與,但這其中最讓人激動(dòng)的一點(diǎn)在于:借助這種機(jī)制,我們甚至可以在不同內(nèi)核,以及不同的操作系統(tǒng)大版本之間切換。每次發(fā)布升級(jí)后,我們都可以有效地引導(dǎo)至一個(gè)全新操作系統(tǒng),這意味著系統(tǒng)不會(huì)隨著時(shí)間的延長(zhǎng)而退化,所有手工改動(dòng)都會(huì)被消除,甚至從技術(shù)上來看,還可以在愿意的情況下切換使用不同的 Linux 發(fā)行版。

并且這一切都是在后臺(tái)進(jìn)行的,完全無需用戶介入,對(duì)用戶來說完全透明:每?jī)芍軐?duì) 8 萬個(gè)操作系統(tǒng)進(jìn)行升級(jí),這該有多酷啊!

責(zé)任編輯:中山網(wǎng)站建設(shè)
 【網(wǎng)訊網(wǎng)絡(luò)】國(guó)家高新技術(shù)企業(yè)》十年專注軟件開發(fā),網(wǎng)站建設(shè),網(wǎng)頁設(shè)計(jì),APP開發(fā),小程序,微信公眾號(hào)開發(fā),定制各類企業(yè)管理軟件(OA、CRM、ERP、訂單管理系統(tǒng)、進(jìn)銷存管理軟件等)!服務(wù)熱線:0760-88610046、13924923903,http://www.wansion.net

您的項(xiàng)目需求咨詢熱線:0760-88610046(國(guó)家高新技術(shù)企業(yè))

*請(qǐng)認(rèn)真填寫需求,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。