云聯壹云—超詳細的ARM架構適配介紹!
本文主要介紹云聯壹云平臺如何適配ARM,并運行在ARM CPU架構的機器上。
背景介紹
1、平臺服務運行架構
云聯壹云平臺采用容器化,分布式的架構運行在 Kubernetes(K8s)之上。下面是平臺服務運行的架構圖:

在多個節點之上,我們會構建Kubernetes的集群 ,它是一個容器管理的平臺。
在Kubernetes的平臺之上,后端服務都是容器化的,是以容器的方式去分布式運行。
通過K8s去做調度的管理,然后將服務自動地打散到多個節點上運行,總結兩點是服務容器化,并依靠K8s來提供容器分布式運行的環境。
另外,底層的節點是有類型的,控制層面的服務運行在控制節點,平臺內置了一個私有云,提供了完整的私有云功能。
若要使用私用云這個功能,則還需要一些計算節點,計算節點上會跑虛擬化相關的軟件,提供私有云虛擬化的功能,總結來說就是計算節點運行私有云的虛擬機。
2、CPU架構簡介
大家熟悉的服務器或者臺式機都是X86架構的CPU,X86架構的CPU特點是性能高,并且軟件的兼容性很好。
大家平常工作中使用的大部分是英特爾等提供的X86架構的CPU,對于英特爾和AMD大家都不陌生,這兩家廠商專門生產X86架構CPU。
另外X86 64位這種架構的CPU存在別名,例如x86_64或者amd64都代表X86架構的64位CPU。

與X86不同的是還有另一種稱為ARM的架構,這是本文的主題,那么ARM架構的CPU和X86架構的CPU相比有何不同?
它的制造成本更低,ARM架構的芯片的功耗也很低,代表性的廠商和使用者是蘋果和華為。
蘋果將生產的ARM芯片用到筆記本或IMAC上,ARM架構的CPU越來越普及。
國內的華為會生產基于ARM架構的服務器,64位ARM架構CPU也有別名,例如arm64、aarch64,這兩種叫法表達同一個意思。
3、為什么適配ARM
因為ARM的CPU普及是大環境下的發展趨勢,例如在國際上,蘋果將ARM架構的CPU投入到筆記本和臺式機上,在國產化方面,國內有鯤鵬和飛騰CPU,國產的基于ARM架構的服務器,現在市場上主流的是鯤鵬和飛騰。 在國產化上,使用ARM架構也是一個趨勢。
另外是適配了ARM架構能夠提升產品的競爭力,競爭力體現在能夠支持管理基于ARM64位和X86_64架構的虛擬化混合部署。

這種混合部署的意思是可以同時把服務運行在ARM和X86的服務器上,同時運行各自的虛擬化,可以通過我們平臺統一部署和管理。
如何適配ARM64?

1、需要解決的關鍵問題
第一個方面是怎樣把服務運行在64位的ARM架構上?
還有一方面是因為我們內置了一個私有云,上層的私有云業務如何支持64位的ARM架構?
通過架構圖可以了解到服務是容器化運行在K8s之上的,再由K8s幫我們將服務分布式地運行在各個節點上,所以第一步是要部署異構CPU架構的K8s集群,異構CPU架構的意思是K8s集群要運行在X86和ARM架構的機器上。
具體而言就是要選擇一個支持ARM架構的Linux的發行版。
K8s節點上的操作系統是Linux,首先要選擇支持ARM架構的Linux操作系統,操作系統同時能夠安裝K8s必要的軟件(比如docker-ce、kubelet等)
當我們把K8s集群給部署起來之后,就要將不同架構的容器鏡像統一制作出來。
統一容器鏡像的意思是一個容器鏡像中要包含X86和ARM架構,相當于同一個鏡像名稱中有兩種架構的鏡像。
第二個大的方面是上層私有云業務怎樣支持ARM64。
主要是分為兩個問題,第一個問題是要支持ARM的虛擬機鏡像,同時上層的私有云業務能夠標記宿主機,宿主機就是運行虛擬機的服務器。
要能夠標記這種宿主機是什么架構,同時要在這個宿主機上運行ARM的虛擬化軟件。
平臺使用的虛擬化軟件基于qemu/kvm,網絡方面依賴openvswitch組件,要求這些組件也要能夠在ARM架構上運行。
這就是要介紹的一些關鍵問題,解決好這些關鍵問題,不管是底層的業務還是上層的私有云業務,都能在ARM上運行。
2、Linux發行版選擇
我們選擇的發行版是Debian 10(開源)和統信UOS(國產系統)。

選擇這兩個發行版的第一個原因是客戶業務上要求在ARM64服務器上運行“統信UOS”。
要適配的話也是首先適配國產統信UOS,在適配過程中,UOS中的內核和打包工具與Debian基本一致。
適配UOS之后,發現其工作基本相同,所以又選擇了Debian 10(開源)進行適配。
如此無論是對于開源用戶還是其他客戶,如果不選擇UOS,也可以選擇Debian 10的發型版運行此平臺,Debian系列對ARM64位的支持很好,
Debian發行版的官方軟件倉庫中已經制作好了很多ARM64的包,如果要安裝docker和K8s的軟件包,Debian中已經做好,直接下載安裝即可。
為什么不在ARM架構上面再選擇CentOS7發行版?
原因在于CentOS7官方即將停止維護,所以選擇了Debian系列的發行版。
3、統信UOS適配認證
對統信UOS適配過后,經過其官方測試,為我們頒發了認證證書。

4、統一軟件依賴—包管理工具
選擇好發行版后?怎樣統一安裝這些軟件?
我們能夠使用不同發行版的包管理工具去安裝相同的軟件,例如在X86的CentOS上安裝docker和K8s這些包時調用yum,在Debian上調用apt install 等同樣的包名即可。

上游的軟件倉庫中已經把包做好,只需直接安裝,軟件直接下載即可使用。
在底層軟件方面,ARM和X86的管理,只要發行版是主流的,驗證Debian和X86的包沒有區別,已經將底層的包安裝部署好。
5、部署kubernetes集群
另外一個話題是部署kubernetes集群,如何在ARM上部署K8s集群?

首先,我們寫了名稱為ocboot的部署工具,它的底層原理是調用ansible實現部署ARM64+X86_64的多節點Kubernetes,這個截圖的意思是通過這個工具部署過后的混布的就是異構的K8s集群的節點的資源。
從截圖中可以發現,第一個節點是centos-x86-64,發行版名稱是centos7,內核是3.10,K8s會通過打標簽的方式標記這個節點,它是amd64。
amd64代表它是X86架構的一個節點,另外一個節點是uos-arm64,它的發行版是uos,內核是4.19.0-arm64的內核。K8s會通過打標簽標記它是ARM64的一個節點,這就代表是一個同時基于X86和ARM64的節點構建的K8s集群。
使用K8s集群的好處是K8s 集群提供了不同CPU架構節點的統一管理,通過一個API能夠把所有架構的節點拿到,能夠基于這些節點提供容器服務的運行。
6、服務統一鏡像運行
部署好K8s集群之后如何運行云聯壹云的服務?

例如K8s中有daemonset的資源,這種資源表示在每一個K8s節點上都會運行pod容器。
它要求在這個資源中寫好服務容器鏡像的地址,即紅框中所標記的。
只要按照這樣的格式寫,寫好之后創建到k8s集群中,K8s就會將提供的鏡像以容器化的方式運行到各個節點上。
從圖中可以了解到,在centos X86的節點上和UOS ARM架構的節點上都同時運行host的服務,這是如何做到的呢?
這就要求統一服務的進項,要在host:v3.6.10的鏡像中包含兩種架構的鏡像格式,它的底層同時將X86和ARM的格式捆綁到一起,在實際運行過程中,在不同的架構的節點上,docker會根據當前節點的架構拉取鏡像中不同架構的格式的鏡像運行。
7、私有云業務如何支持ARM64?

在運行虛擬機的宿主機上去標記宿主機的架構類別,云平臺的前端界面可以看到,給宿主機列表上面加了CPU架構的屬性,ARM架構服務器的宿主機,會給它一個稱為aarch64的CPU架構來標記,X86則會標記x86_64的CPU架構屬性 。
若要運行虛擬機,則需要先提供虛擬機的鏡像,我們在虛擬機的鏡像中也使用了CPU架構的屬性來標記虛擬機鏡像是X86架構還是ARM 64位的架構。

提供宿主機和虛擬鏡像過后,即可創建虛擬機,在創建虛擬機的表單中,會讓用戶去選擇是要創建ARM架構的虛擬機還是X86架構的虛擬機。

創建好虛擬機過后,平臺負責將這些虛擬機根據所提供的CPU架構調入到不同架構的宿主機上,這是一個在平臺同時創建的X86和ARM的虛擬機列表界面。

在此列表中通過CPU架構的字段了解虛擬機的架構類型,這就是在私有云這個業務做的改造并支持ARM64位架構。
技術細節
如何制作統一的容器鏡像(支持X86_64和ARM64)?
docker原生支持的多架構鏡像制作方案
點擊進入官方介紹分別編譯打包出x86_64和arm64的容器鏡像,然后捆綁到一起。
1、統一容器鏡像—docker buildx

docker通過讀取file中的語句,制作出鏡像,Dockerfile先基于一個稱做golang:alpine的鏡像,把它作為一個build容器。
同時,其中會傳兩個參數,分別是TARGETPLATFORM 和BUILDPLATFORM。
TARGETPLATFORM的意思是制作出的鏡像架構,BUILDPLATFORM 是當前制作鏡像機器的架構 ,這里RUN的命令會讀取這兩個環境變量,然后將他們的值打到名稱為log的文件中。
第二步,FROM alpine 的語句是找到alpine這個鏡像,基于這個容器鏡像將build容器中的log文件拷貝出來。
使用buildx 同時制作x86_64和arm64架構的鏡像。

-t的意思是build出的鏡像的名稱,push代表要push到docker鏡像倉庫中,platform參數代表制作出來的鏡像同時代表兩個架構,分別是x86 64位架構和arm64位架構。
運行此命令,docker buildx就會基于dockerfile的步驟,同時拉取ARM架構和X86架構的基礎鏡像。

基于基礎鏡像運行里面相同的語句,例如紅色標記的地方,它同時運行兩個架構的指令,相當于同時拉取了amd64和arm64的alpine 鏡像。
去build時,同一條build語句也在amd64和arm64這兩個架構上運行。
通過build出的結果即可發現RUN的這個命令,是在X86架構的機器上制作的鏡像build出的結果,例如第一條是build出了arm64的鏡像,第二條是build出X86 64位的鏡像。
build完鏡像過后,把它push到鏡像倉庫中,即可通過docker manifest 這個命令去查詢這個鏡像里面的一些元數據,查看剛才制作的鏡像,manifest 中有兩種格式,第一種格式是amd64,表示X86_64架構,第二種格式是ARM64,是能夠運行在ARM上的鏡像,這些都是buildx做好的,我們只需要寫dockerfile。

它默認幫我們制作出來一個多架構的容器鏡像。
buildx 如何在 x86_64的機器上制作arm64的鏡像?
通過binfmt_misc模擬arm64硬件的用戶空間,然后調用qemu的用戶態模式編譯程序。

最終結果是調用buildx的命令過后,編譯進程后,會運行qemu-aarch64 工具,相當于模擬出arm64的硬件環境,然后調用ARM的工具做編譯,截圖中,后端服務都是用Golang編寫,都需要做編譯。
2、統一容器鏡像-交叉編譯
交叉編譯:直接在x86_64開發機上編譯arm64二進制。

圖中的Go代碼,其中寫了main的函數,在X86的機器上直接編譯,調go build工具,然后把它編譯成一個叫做t_x86_64的二進制可執行文件。
然后在操作系統上調用file去看可執行文件的內容,通過信息可知這是一個64位的可執行文件,并且是x86-64架構。
Go中的交叉變異很簡單,指定GOARCH的環境變量,然后把它設置為arm64,然后再運行相同的go build的命令,即可使用交叉編譯,編譯出ARM可執行的文件。
編譯出來之后,再去看t_arm64的二進制文件,即可發現它也是64位的執行文件,但其架構為ARM,此即為交叉編譯的簡單的示例。 相當于在X86的開發機上使用交叉編譯工具編譯出ARM執行文件。
3、如何將不同架構鏡像打包
將交叉編譯后的x86_64和arm64容器鏡像組合到一起。

例如已經有名稱為service:v1_x86_64的容器鏡像和service:v1_arm64的鏡像,如何將其組合為service:v1 = service:v1_x86_64 + service:v1_arm64 的容器鏡像?
首先創建 service:v1 的 manifest 鏡像,然后將x86_64的鏡像和arm64的鏡像捆綁到一起,然后調用docker manifest標記鏡像 service:v1_arm64 的架構為 arm64 ,標記鏡像 service:v1_x86_64 的架構為 amd64 ,再調用docker push將service:v1 鏡像上傳到鏡像倉庫即可,如此制作出來的一個鏡像中即可包含兩個架構。
4、buildx與交叉編譯打包對比

如果使用buildx+binfmt_misc的方式,速度很慢,在本地x86機器上運行,復雜度很低。
如有ARM服務器,可以通知buildx ssh到遠程的ARM機器,會把編譯arm的部分交給遠端的ARM機器,速度很快,環境要求為本地x86+遠端arm64機器,因為一般不會給每個開發人員提供ARM服務器,所以未采用此種方式。
最后是交叉編譯+manifest打包的方式,速度很快,因為編譯器中做了交叉編譯的優化,能夠直接編譯出ARM架構的二進制,此種方式只依賴本地的開發環境,此種方式復雜度較高。
現階段使用的方式是同時使用buildx + binfmt_misc和交叉編譯 + manifest 打包的方式。
前端不需要編譯的服務:使用buildx + binfmt_misc后端編譯型的服務:使用交叉編譯然后打包
5、私有云管理—虛擬化軟件
私有云上層業務支持X86和ARM虛擬化混合管理,要做混布支持,首先要讓虛擬化軟件能夠運行在ARM架構上,主要運行虛擬機的軟件是通過名稱為qemu的虛擬化軟件工具,通過交叉編譯的方式運行在ARM架構上。

在做編譯之前,只需要配置好目標的架構是aarch64即可。
qemu在實際生產使用中要結合KVM虛擬化加速工具,debian 10 4.19.0 aarch64 內核原生支持。
openvswitch 網絡虛擬交換機可以直接在debian 中安裝使用。
6、私有云管理—業務支持
例如在宿主機的資源中加上屬性,標記宿主機是ARM架構還是X86架構,還有在平臺虛擬機鏡像中加上架構的屬性,同時調度器的服務也要做改造,保證用戶創建一臺ARM架構的虛擬機,能夠調度到ARM的宿主機上。

大家可以根據圖中列出的 PR詳細地址了解業務支持詳情。

