如何平(優(yōu))滑(雅)的拋棄 CentOS7
背景
CentOS 7 自身的生命周期截止到 2024年6月30日。在2020年底,CentOS 社區(qū)宣布修改現(xiàn)有的發(fā)布模式,將 CentOS 從作為 RHEL 的下游改為 CentOS Stream,即 RHEL 的上游,更導(dǎo)致 CentOS8的生命周期短的可憐,這讓社區(qū)中原本就對 CentOS 不滿的開發(fā)者/使用者不滿,從而出現(xiàn)了拋棄 CentOS 轉(zhuǎn)投其他發(fā)行版的情況。
大家選擇使用 CentOS ,雖然都在說穩(wěn)定,但是我理解更看重的是 RedHat 在身后背書,CentOS 作為 RHEL 的下游,所有的軟件版本都是經(jīng)過 RedHat 測試驗證的,且后期維護也是有 RedHat 的身影在,不擔(dān)心維護的問題。
CentOS 原有的模式也是有問題的,用戶很難參與到 RHEL 的研發(fā)周期。用戶發(fā)現(xiàn)了 CentOS 某個版本存在問題,想要給 CentOS 進行貢獻,讓 CentOS 下一個版本修復(fù)該問題。此時只有一條路,就是貢獻給開源組件自身,但是這樣也只是存在修復(fù)的可能,最終是否可能修復(fù)還是看 RedHat 開發(fā)人員的決定(畢竟 RHEL/CentOS 中存在大量開源組件自身不包含,但是 RHEL/CentOS 通過 rpm spec 中進行 Patch 的方式包含的 Patch)。在引入了 CentOS Stream 之后,用戶就可以通過貢獻給 CentOS 社區(qū),來保證 CentOS 下一個版本包含該 Patch,至于 RHEL 是否包含,用戶并不關(guān)心,那是 RedHat 關(guān)心的問題。
Fedora 更關(guān)注于上游社區(qū)最新的代碼,包含最豐富的功能,作為先驅(qū)者;CentOS Stream 作為 RHEL 的上游,提供穩(wěn)定可靠的持續(xù)交付版本,保證更多的貢獻者可以參與進來;RHEL 給企業(yè)用戶使用,有 RedHat 提供完整的維護服務(wù)。
在現(xiàn)有的模式下,CentOS Stream 已經(jīng)與原有采用 CentOS 的用戶初衷背離,已有的 CentOS7 用戶需要尋找新的替代品,在國產(chǎn)化的浪潮下,選擇的方向也發(fā)生了一定的變化。
社區(qū)替代品
Rocky Linux
Rocky Linux aims to function as a downstream build as CentOS had done previously, building releases after they have been added to the upstream vendor, not before.
AlmaLinux
AlmaLinux OS is replacing CentOS as the downstream rebuild of RedHat Enterprise Linux.
在 CentOS 宣布策略改變之后,社區(qū)中出現(xiàn)了兩個替代品,分別是 Rocky Linux 和 AlmaLinux,它倆的目的都是一樣的,作為RHEL 的下游來構(gòu)建發(fā)布,且發(fā)布模式和發(fā)布周期采用 CentOS 原有模式。
通過 AlmaLinux 官方提供的發(fā)行版比較)可以看到,AlmaLinux 和 Rocky Linux 兩者對于用戶來說沒什么差別,如果一定要較真,那就是 AlmaLinux 大部分人員是來自 CloudLinux 公司,而 Rocky Linux 是 Greg 公司。
國產(chǎn)替代品
Anolis OS(阿里巴巴)
Anolis OS 8 是 OpenAnolis 社區(qū)推出的完全開源、中立、開放的發(fā)行版,它支持多計算架構(gòu),也面向云端場景優(yōu)化,兼容 CentOS 軟件生態(tài)。Anolis OS 8 旨在為廣大開發(fā)者和運維人員提供穩(wěn)定、高性能、安全、可靠、開源的操作系統(tǒng)服務(wù)。
openEuler(華為)
openEuler是一款開源操作系統(tǒng)。當(dāng)前openEuler內(nèi)核源于Linux,支持鯤鵬及其它多種處理器,能夠充分釋放計算芯片的潛能,是由全球開源貢獻者構(gòu)建的高效、穩(wěn)定、安全的開源操作系統(tǒng),適用于數(shù)據(jù)庫、大數(shù)據(jù)、云計算、人工智能等應(yīng)用場景。同時,openEuler是一個面向全球的操作系統(tǒng)開源社區(qū),通過社區(qū)合作,打造創(chuàng)新平臺,構(gòu)建支持多處理器架構(gòu)、統(tǒng)一和開放的操作系統(tǒng),推動軟硬件應(yīng)用生態(tài)繁榮發(fā)展。
銀河麒麟操作系統(tǒng)
銀河麒麟高級服務(wù)器操作系統(tǒng)V10是針對企業(yè)級關(guān)鍵業(yè)務(wù),適應(yīng)虛擬化、云計算、大數(shù)據(jù)、工業(yè)互聯(lián)網(wǎng)時代對主機系統(tǒng)可靠性、安全性、性能、擴展性和實時性等需求,依據(jù)CMMI5級標準研制的提供內(nèi)生本質(zhì)安全、云原生支持、自主平臺深入優(yōu)化、 高性能、易管理的新一代自主服務(wù)器操作系統(tǒng)
在國產(chǎn)化浪潮下,如果產(chǎn)品需要滿足信創(chuàng)標準,那么操作系統(tǒng)的選擇需要考慮國產(chǎn)替代品,目前(個人了解)符合信創(chuàng)標準的操作系統(tǒng)只有銀河麒麟,openEuler 和 Anolis OS 目前還無法完全通過信創(chuàng)評審。在這一系列的替代品中, Rocky Linux, AlmaLinux, Anolis OS 所采用的發(fā)布模式和版本控制方式,都維持 CentOS原有模式,即 8.1, 8.2, 8.3 發(fā)布方式。openEuler 和銀河麒麟操作系統(tǒng)雖然也采用 RPM 作為包管理器并且大部分組件版本與社區(qū)中的 CentOS 8 相同,但是不能完全等價,這里需要注意。
比較選擇
如果要滿足信創(chuàng)要求,那么只能選擇銀河麒麟作為替代品;如果從使用角度考慮,選擇 Rocky Linux/AlmaLinux/Anolis OS 是更好的選擇,有良好的社區(qū)支持,版本控制也與 CentOS 保持一致,心智負擔(dān)更低;如果從國產(chǎn)硬件支持考慮,openEuler 是不錯的選擇。
上述討論的各個發(fā)行版,當(dāng)前所采用的包管理器均為 RPM,所有軟件均已 RPM 為粒度安裝,在 RPM 之上,會存在 Yum/DNF 包含 RPM 依賴管理、沖突管理、升降級等功能的基于 RPM 的包管理器。其中 CentOS 7 系列所采用的基于RPM 的包管理器是 Yum,其他發(fā)行版當(dāng)前維護版本所采用的基于 RPM 包管理器是 DNF(Dandified Yum)。
升級轉(zhuǎn)換
在現(xiàn)有使用了 CentOS 7 的環(huán)境中,需要使用替代品將 CentOS 7 升級轉(zhuǎn)換為目標發(fā)行版。
如果應(yīng)用環(huán)境都是單體應(yīng)用,且可以有下線維護時間,進行數(shù)據(jù)備份然后完整的重裝 OS 是一個穩(wěn)妥的選擇。如果應(yīng)用環(huán)境是集群,且大部分應(yīng)用都已經(jīng)容器化了,那么依次進行單節(jié)點重裝 OS 需要認真測試驗證,不同的發(fā)行版版本的默認系統(tǒng)參數(shù)可能存在差異,哪怕上層基礎(chǔ)平臺保證了版本一致(如 Kubernetes,containerd,runc 的版本一致),也可能導(dǎo)致異常情況。
如果選擇不重裝 OS,原地升級轉(zhuǎn)換的話有兩種方式:自動和手動。其中 Rocky Linux/AlmaLinux/Anolis OS 提供自動升級轉(zhuǎn)換方式,openEuler 和銀河麒麟可以采用手動轉(zhuǎn)換方式。
自動流程
自動升級轉(zhuǎn)換依賴于 Leapp),Leapp 由 Redhat 員工開發(fā)的開源工具,Leapp 自身只是一個工作流框架,其中包含 Actor、Model、Message、Workflow 等概念。其中 workerflow 包含多個 phase,每個 phase 含有3個 stage:Before,Main,After,每個 stage 中包含多個 Actors,其中 Actors 之間沒有嚴格的順序,而是靠 Message 通信,Message 遵循 Model 的定義,如果 ActorA 依賴了 ActorB 產(chǎn)生的 MessageB,那么 ActorA 會在 ActorB 之后執(zhí)行,沒有 MessageB 依賴的 ActorC 會按照加載順序執(zhí)行,沒有嚴格順序依賴。
目前 Leapp 主要使用場景是用于 RedHat 系發(fā)行版升級、不同發(fā)行版之間的升級切換等。
在完整的升級流程中,使用統(tǒng)一定義的 Workflow,不同階段(如預(yù)升級、升級、Firstboot)都是調(diào)用的同一個 Workflow,只是根據(jù)指定的不同的 Tag、參數(shù)來決定執(zhí)行的 Phase 不同。
預(yù)升級(preupgrade),進行環(huán)境信息的收集與檢查,將檢查結(jié)果以報告的形式提供給用戶,這里進行的信息收集及檢查項數(shù)量很大,包含了很多細節(jié),除了包含一些基礎(chǔ)組件的檢查:CPU 架構(gòu)、openssh 配置變更、PAM 模塊變更、Driver 支持、NTP 變更等之外,還包含一些第三方應(yīng)用的檢查:SAP HANA、Memcached、寶塔等。
升級(upgrade),升級的主要動作,與預(yù)檢查使用的是相同 Workflow。
configuration_phase
FactsCollection
Checks
TargetTransactionFactsCollection,生成臨時 minimal 環(huán)境,包含完整的目標版本的運行環(huán)境,用于使用目標版本的工具棧,比如 DNF、RPM 高級特性等,該環(huán)境還會用來生成下一步驟所需的initramfs image
TargetTransactionCheck,通過上述生成的 minimal 環(huán)境,使用其中的 dnf 工具,dnf - rhel-upgrade check 來檢查當(dāng)前節(jié)點是否可以進行升級
Reports
Download,升級所需軟件包下載步驟, dnf rhel-upgrade download
InterimPreparation,生成下一步驟所需的 initramfs,在前述步驟中的minimal 環(huán)境中安裝 dracut 相關(guān)工具包,使用 dracut 生成 initramfs image,生成完成后調(diào)整系統(tǒng)啟動項,將其置為第一個啟動項
臨時環(huán)境升級(Interim Upgrade),真正執(zhí)行 RPM 升級的步驟,與預(yù)檢查使用的是相同的 Workflow
在系統(tǒng)reboot 后,系統(tǒng)引導(dǎo)到前置步驟生成的 initramfs 中,系統(tǒng)正常引導(dǎo),dracut hook 中,增加了兩個 hook,分別是 85sys-upgrade-redhat 和 90sys-upgrade, 其中 85 是真正執(zhí)行節(jié)點軟件包升級的動作(leapp upgrade –resume),90 配置 systemd upgrade unit (與重啟相關(guān))
InitRamStart,移除啟動項設(shè)置
LateTests
Preparation
RPMUpgrade,dnf rhel-upgrade upgrade 升級 RPM
Applications
ThirdPartyApplications
Finalization
升級后動作(Firstboot),系統(tǒng)升級完成會,會自動 reboot 進入到目標版本系統(tǒng)中,此時會執(zhí)行 Firstboot 階段,在執(zhí)行完成后,系統(tǒng)升級完成
FirstBoot,執(zhí)行清理動作,修改部分配置(NM)等 完整升級流程共執(zhí)行 4次 Workflow,其中采用臨時環(huán)境執(zhí)行升級動作的目的是:升級動作執(zhí)行工具鏈是目標環(huán)境對應(yīng)版本的工具鏈。
自動實現(xiàn)方式
項目列表:
leapp
leapp-repository
leapp-data
其中 leapp 是框架自身,leapp-repository 是 Leapp 的應(yīng)用實現(xiàn),也就是升級中所執(zhí)行的 Actor 實現(xiàn),leapp-data 是升級中所用到的基礎(chǔ)配置信息。不同發(fā)行版會維護自己的 leapp-repository,比如Anolis OS 就維護了自己的 Git 倉庫(在 Gitee 上),并針對性的增加了自己的檢查項。在 Leapp 的架構(gòu)中,因為最終的應(yīng)用會以獨立的插架形式安裝,所以 Python 的 syspath 可能會發(fā)生變化,在查看代碼的時候需要對應(yīng)的修改一下路徑地址。以 NTP 檢查為例:
NTP 檢查的 Actor 實現(xiàn):
Actor 中調(diào)用的 check_ntp 函數(shù)實現(xiàn):
手動流程
對于 Linux 發(fā)行版來說,整體是由無數(shù)個 RPM 組成的,最終系統(tǒng)中看到的最小粒度就是 RPM,我們可以通過 RPM 的升級來完成整體的發(fā)行版的升級變更。但是對于部分 RPM 來說,RPM 之間的依賴阻礙了我們無法通過依次升級部分 RPM 的方式來完成完整的升級替換,其中一些關(guān)鍵組件,如 glibc、glib2、openssl 等等都是強依賴的,我們必須要找到一個方式來完成整體的升級。在 Yum 中,存在 distribution-synchronization 命令用來同步當(dāng)前 OS 中所有的 RPM到目標 Repository 中的版本,但是用 Yum 可能會存在無法識別 rpmlib 的情況。RPM 作為基礎(chǔ)包管理器,自身會存在部分高級特性以 rpmlib 的依賴形式提供,如果當(dāng)前系統(tǒng)的包管理器無法識別 rpmlib,那么就會在同步過程中出現(xiàn)無法解決的依賴沖突。
舉例:目標 RPM 為 dnf-4.2.23-6.oe1.noarch.rpm ,升級提示依賴 rpmlib(RichDependencies) <= 4.12.0-1 沖突。這是因為 dnf-4.2.23 這個 RPM 在構(gòu)建的階段,所使用的 rpm 環(huán)境(可能是在 openEuler 20.03 或更高版本)比當(dāng)前 OS 的 RPM 版本(CentOS 7)高,所以當(dāng)前 rpm 無法滿足這個依賴條件。
我們可以使用 DNF 的 distro-sync 并配合部分的 RPM 修改,來完成手動升級轉(zhuǎn)換。流程如下:
將當(dāng)前 CentOS7 升級到 CentOS 7.x 系列最新版本;
停止節(jié)點上運行的所有應(yīng)用
配置 CentOS7 Repository ,安裝 DNF(DNF依賴于 glib2 的執(zhí)行版本,但是未在 spec 中聲明,需要單獨升級 glib2)
移除 Yum 管理器,防止與 DNF 產(chǎn)生沖突
配置目標發(fā)行版 Repository
使用 dnf distro-sync 進行升級轉(zhuǎn)換
使用 dnf remove 移除無用 RPM
重啟主機生效
手動實現(xiàn)方式
當(dāng)前 CentOS7 包管理器是 Yum,在目標版本中包管理器是 DNF,在通過 Yum 安裝 DNF ,在保證 Yum(DNF) Repository 配置是目標版本的前提下,使用 dnf distro-sync 命令來進行 RPM 的升級和同步,該命令會將當(dāng)前 OS 已經(jīng)安裝的 RPM 與 Yum Repository 中的 RPM 進行匹配。RPM 版本匹配存在以下幾種情況:
當(dāng)前 RPM 版本低于目標 Repository 中包含的 RPM版本,則會升級;
當(dāng)前 RPM 版本高于目標 Repository 中包含的 RPM 版本,則會降級;
當(dāng)前 RPM 被目標 Repository 中包含的 RPM 所替代(指定 Obsolete),則會安裝新 RPM,原有RPM 被卸載(替代);
當(dāng)前 RPM 版本與目標 Repository 中包含的 RPM 版本相同,但 dist 等其他 RPM 元數(shù)據(jù)不同,則會重新安裝;
當(dāng)前 RPM 是被其他 RPM 依賴引入的,但是其他 RPM 已經(jīng)被替代,則該 RPM 會被卸載;
當(dāng)前 RPM 在目標 Repository 中不包含,則不會進行處理;
總結(jié)
通過自動或者手動的方式,我們可以原地將 CentOS 7 升級轉(zhuǎn)換為我們想要的目標發(fā)行版。社區(qū)的 Rocky Linux/AlmaLinux/Anolis OS 可以采用自動的方式完成 ,國產(chǎn)非等價替代的 openEuler 可以采用控制 Repository 的方式手動完成,減少發(fā)行版變更帶來的工作量。