TAP 系列文章5 | 雲原生構建服務
背景
通常的應用開發過程,是由開發人員使用某種計算機語言,比如Java,開發特定專案然後提交到程式碼倉庫。緊接著,原始碼會被編譯成二進位制程式碼,被放置於特定的環境中執行,比如Java執行時或者Web Server等。隨著容器以及容器編排技術的發展和成熟,越來越多的應用將從傳統的虛擬機器部署方式改為容器部署模式。這就增加了一個關鍵的步驟:把應用打包成容器映象,也稱為應用容器化。
那麼這個步驟還是由開發人員完成嗎?開發人員的內心os:我難道不應該專注於寫業務邏輯嗎?這個打包也要由我來完成?好吧,但是打包寫Dockerfile我沒有經驗啊!要怎麼避開裡面的陷阱呢?以後原始碼或者基礎映象更新了,還要由我來維護嗎?
帶著這些疑問,我們來仔細看看應用容器化的具體過程是怎麼樣的吧。
從原始碼到容器映象
當開發人員完成了一個應用專案並提交程式碼庫之後,為了讓程式碼能在容器環境中執行,需要把原始碼轉換成符合OCI標準的容器映象,這個過程稱為構建(build)。構建過程通常分為兩個子步驟,第一步是將原始碼編譯成二進位制檔案,第二步是加上基礎作業系統和相關依賴(比如Java執行時)合併成標準容器映象。
第一步的編譯取決於應用專案所採用的語言和框架,第二步常規的方法則是以撰寫Dockerfile以及使用docker build來完成的。以使用Spring框架開發的專案為例,我們可以看到常規的構建過程是這樣的:
- 首先,將原始碼下載到本地,使用Maven命令對Spring專案進行Java編譯:
% mvn -Dmaven.test.skip=true package
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------< io.buildpacks.example:sample >--------------------
[INFO] Building sample 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
。。。
[INFO]
[INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) @ sample ---
[INFO] Building jar: /Users/mingjiex/git/samples/apps/java-maven/target/sample-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.18.RELEASE:repackage (repackage) @ sample ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.671 s
[INFO] ------------------------------------------------------------------------
在編譯過程中會自動下載大量的Java依賴包,如果沒有編譯錯誤,那麼最終會在target目錄下生成一個二進位制可執行的sample-0.0.1-SNAPSHOT.jar包。
- 然後,撰寫Dockerfile檔案,宣告構建的步驟和引數,樣本檔案如下:
FROM openjdk:8-jre
ADD ./target/sample-0.0.1-SNAPSHOT.jar /
ENTRYPOINT ["java"]
CMD ["-jar", "/sample-0.0.1-SNAPSHOT.jar"]
EXPOSE 8080
其中FROM語句是引用的基礎映象名稱,該映象包含了底層的作業系統和依賴的Java執行環境,將被從公共或者私有映象庫中下拉。
ADD語句說明在需要加入的檔案,ENTRYPOINT和CMD語句構成了啟動命令,EXPOSE語句說明了暴漏的埠。
這是一個最簡單的Dockerfile樣例,實際的要複雜得多。由於容器映象採用的是Overlay型的檔案系統,Dockerfile中的每一個步驟將在最終映象中產生一個層級(layer),所以Dockerfile撰寫的好壞決定著應用映象的執行效率。
- 最後,執行docker build命令,打包完成後得到最終的應用映象。
% docker build .
[+] Building 4.5s (7/7) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/openjdk:8-jre 4.4s
=> [internal] load build context 0.0s
=> => transferring context: 82B 0.0s
=> [1/2] FROM docker.io/library/openjdk:8-jre@sha256:59c47099aed504b2987fb5eea4376f96cf0f53d2c9081c30fd6a554c7a6 0.0s
=> CACHED [2/2] ADD ./target/sample-0.0.1-SNAPSHOT.jar / 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:8335af64e29a7e69a047e424863ef3706349d5c5d325ff4f84447fa21a9fc496
問題
我們發現,在上述常規使用docker build的構建過程會存在一些問題,包括但不限於:
1.需要為每種不同類別的專案準備合適的編譯環境。
2.不同的人員會撰寫不同風格的Dockerfile,一致性難以保證。
3.撰寫Dockerfile過於自由,可能會引入安全漏洞,包括不安全的基礎映象。
4.如果要對安全漏洞進行修復,則需要更新Dockerfile為引用最新的基礎映象。
5.需要為每個專案單獨寫一個Dockerfile,在微服務架構中可能會有以百計的專案數,維護困難。
6.Dockerfile如果寫的不夠優化,那麼最終產生的層級會很多,容器的執行效率也會打折扣。
。。。
所以我們需要一種更為便捷,安全而且易維護的構建方法來避免以上的各種問題。
Tanzu構建服務
基於雲原生構建開源專案Cloud Native Buildpacks(CNB),Tanzu構建服務(以下簡稱TBS)將為您解決以上提到的各種問題。開發人員將不再需要撰寫Dockerfile,而只需要使用一個簡單的命令,就能把各種型別的原始碼專案打包成最終的應用映象。
而Tanzu構建服務,已經整合在Tanzu Application Platform的平臺裡,作為一個關鍵的企業級特性提供給使用者來實現構建服務。
我們來看一個例子,還是使用上面的樣例Spring專案。在下面使用的命令列裡,kp是Tanzu構建服務的命令列工具,–git引數指明原始碼倉庫地址,–git-revision 引數指明git分支名稱,–sub-path引數指明原始碼子目錄,–tag引數指明最終應用映象的推送倉庫地址:
% kp image create my-image --tag registry.tanzu.online:5000/tbs/test-app --git http://124.222.5.35:8888/mingjiex/samples.git --git-revision master --sub-path ./apps/java-maven --wait
Creating Image Resource...
Image Resource "my-image" created
===> PREPARE
Build reason(s): CONFIG
CONFIG:
resources: {}
- source: {}
+ source:
+ git:
+ revision: 1bf16cdcce9454d4922f20000efa1650c195b53b
+ url: http://124.222.5.35:8888/mingjiex/samples.git
+ subPath: ./apps/java-maven
Loading secret for "registry.tanzu.online:5000" from secret "my-registry-creds" at location "/var/build-secrets/my-registry-creds"
Cloning "http://124.222.5.35:8888/mingjiex/samples.git" @ "1bf16cdcce9454d4922f20000efa1650c195b53b"...
Successfully cloned "http://124.222.5.35:8888/mingjiex/samples.git" @ "1bf16cdcce9454d4922f20000efa1650c195b53b" in path "/workspace"
===> ANALYZE
Previous image with name "registry.tanzu.online:5000/tbs/test-app" not found
===> DETECT
7 of 34 buildpacks participating
paketo-buildpacks/ca-certificates 2.4.2
paketo-buildpacks/bellsoft-liberica 8.9.0
paketo-buildpacks/maven 5.7.0
paketo-buildpacks/executable-jar 5.3.1
paketo-buildpacks/apache-tomcat 6.4.0
paketo-buildpacks/dist-zip 4.3.0
paketo-buildpacks/spring-boot 4.7.0
。。。
。。。
。。。
Paketo Executable JAR Buildpack 5.3.1
http://github.com/paketo-buildpacks/executable-jar
Class Path: Contributing to layer
Writing env/CLASSPATH.delim
Writing env/CLASSPATH.prepend
Process types:
executable-jar: java org.springframework.boot.loader.JarLauncher (direct)
task: java org.springframework.boot.loader.JarLauncher (direct)
web: java org.springframework.boot.loader.JarLauncher (direct)
Paketo Spring Boot Buildpack 4.7.0
http://github.com/paketo-buildpacks/spring-boot
Launch Helper: Contributing to layer
Creating /layers/paketo-buildpacks_spring-boot/helper/exec.d/spring-cloud-bindings
Spring Cloud Bindings 1.8.0: Contributing to layer
Reusing cached download from buildpack
Copying to /layers/paketo-buildpacks_spring-boot/spring-cloud-bindings
Web Application Type: Contributing to layer
Servlet web application detected
Writing env.launch/BPL_JVM_THREAD_COUNT.default
TBS會下載原始碼,自動識別程式碼專案的型別而採用合適的編譯打包工具,並編譯打包成容器映象,最終推送入指定的映象倉庫。
那麼TBS究竟是如何完成這系列構建步驟的呢?我們來看一下TBS的元件。
TBS依賴於幾類關鍵資源:
- ClusterStore:是雲原生構建包的倉庫,基於開源社群專案(Cloud Native Buildpacks,CNB)。
- ClusterStack:是用於構建和執行的作業系統映象,需要不斷更新以修復安全漏洞。
- ClusterBuilder:是ClusterStore和ClusterStack的組合所形成的構建器。
TBS釋出版自帶了這些資源,以供客戶開箱即用。如果客戶有特殊需求,則可以根據要求定製。使用TBS的命令列工具kp檢視可用資源,這些資源需要在準備就緒(Ready=True)的狀態:
% kp clusterstore list
NAME READY
default True
% kp clusterstack list
NAME READY ID
base True io.buildpacks.stacks.bionic
default True io.buildpacks.stacks.bionic
full True io.buildpacks.stacks.bionic
tiny True io.paketo.stacks.tiny
% kp clusterbuilder list
NAME READY STACK IMAGE
base true io.buildpacks.stacks.bionic registry.tanzu.online:5000/tbs/build-service:clusterbuilder-base@sha256:f7600c5e5864fa14bc1a6ba31fdd932cb2cec128d3d42cf0537f7d29e63c09d0
default true io.buildpacks.stacks.bionic registry.tanzu.online:5000/tbs/build-service:clusterbuilder-default@sha256:f7600c5e5864fa14bc1a6ba31fdd932cb2cec128d3d42cf0537f7d29e63c09d0
full true io.buildpacks.stacks.bionic registry.tanzu.online:5000/tbs/build-service:clusterbuilder-full@sha256:bb9b938e5534fe06279bfdeafb351d1c0466af50c2082495eeed258a7cb580f7
tiny true io.paketo.stacks.tiny registry.tanzu.online:5000/tbs/build-service:clusterbuilder-tiny@sha256:0c8c05b28fb57e69c0fe7c821d22634dc9fe42cd5368a02dc7f619560e44a69a
有了可用的構建器,就可以如同一開始使用的樣例專案,使用kp image create命令建立Image Resource,對原始碼執行構建。
% kp image create my-image --tag registry.tanzu.online:5000/tbs/test-app --git
http://124.222.5.35:8888/mingjiex/samples.git --git-revision master --sub-path ./apps/java-maven --wait
檢視Image Source列表,後續可以執行更改、刪除操作:
mingjiex@mingjiex-a01 java-maven % kp image list
NAME READY LATEST REASON LATEST IMAGE NAMESPACE
my-image True CONFIG registry.tanzu.online:5000/tbs/test-
app@sha256:5fabc1e1f968f5ad09566ce1cf74a28a67d65815b7e6518604160daa8abcd86a default
當Image Resource被建立後,如果原始碼有新的提交,或者基礎映象發生更新,或者Image Resource引數發生變化的時候(各種REASON),新的構建任務將會被觸發。每次構建都會產生一個build號,成功的構建會產生新的應用映象並推送到應用映象倉庫。我們可以使用kp build命令檢視每次build生成的映象:
% kp build list
BUILD STATUS BUILT IMAGE REASON IMAGE RESOURCE
1 SUCCESS registry.tanzu.online:5000/tbs/test-app@sha256:0b660ee0af25b0bba80a76b31d82537eafd649c15bcb0ff08b0c06f8f6d40317 CONFIG my-image
2 SUCCESS registry.tanzu.online:5000/tbs/test-app@sha256:72a19a7c37158a8fc56da7c4a36cc78bd33336a91d0b220cef17a7282d167eef COMMIT my-image
3 SUCCESS registry.tanzu.online:5000/tbs/test-app@sha256:5fabc1e1f968f5ad09566ce1cf74a28a67d65815b7e6518604160daa8abcd86a CONFIG my-image
為了達到優化目的,還可以對Image Resource施加特定引數來干預構建過程,比如指定構建器,改變預設的Java版本,建立cache以加速後續的構建,等等。這些需要您在實踐中去體會了。
Tanzu構建服務和CI/CD整合
Tanzu構建服務和持續整合/持續交付(CI/CD)工具非常容易整合。通過CI/CD工具設定Image Resource,然後觸發TBS對提交入程式碼庫的原始碼專案執行構建服務,最後推入容器映象倉庫。通常的整合方式如下圖:
TBS包含在Tanzu Application Platform(簡稱TAP)的發行版內,而且已經作為預製件整合進了TAP的軟體供應鏈Choreograph裡面,成為了開箱即用的構建工具。如下圖所示,Tanzu構建服務是TAP軟體供應鏈的第一步,而和後續的安全掃描,部署,執行等等連線在一起組成完整的應用安全運維過程:
Tanzu構建服務之價值總結
對於試圖在商業環境中構建和部署容器的開發人員和運維人員來說,構建容器映象並通過所需的依賴關係(例如執行庫/二進位制檔案和基本作業系統映象)對其進行修補是一件困難的事情。在大型企業環境中,挑戰尤為嚴峻,在這種環境中,許多開發人員會構建各種應用,而這些應用必須嚴格遵守安全性和稽核政策。
由於 IT 運維人員需要全面重新設計他們的系統以對容器的維護進行管理,因此,從基於虛擬機器或基於 PaaS 的部署過程遷移到 Kubernetes 往往十分複雜。
Tanzu構建服務在Kubernetes的固有物件之上添加了抽象層,以提高企業開發人員和 IT 運維人員的工作效率。客戶通過持續整合/持續交付 (CI/CD) 系統使構建過程自動化,並可從 Tanzu Network 獲取最新的堆疊和生成包版本。VMware 旨在遵循行業最佳實踐,及時提供 CVE 補丁,保障客戶系統的安全。對於開發人員而言,這減輕了通過新的依賴關係來更新容器所造成的負擔。對於運維人員而言,它可以集中控制所有容器的依賴關係,從而更好地滿足安全性、合規性和稽核需求。
作者簡介:
熊銘傑,VMware大中華區應用現代化部門高階解決方案架構師,在加入VMware之前,曾先後任職BEA System、IBM、Redhat等企業。多年來一直從事企業級軟體開發、中介軟體和雲原生相關領域工作,對企業級軟體開發和架構設計、微服務架構設計以及容器平臺的架構設計、軟體開發、實施和運維等工作具有豐富的經驗積累;CNCF認證CKA工程師;VMware認證Spring Professional工程師。
來源|公眾號:VMwareTanzu雲原生
- 虛擬雲網絡系列 | Antrea 應用於 VMware 方案功能簡介(二)
- 虛擬雲網絡系列 | Antrea 應用於 VMware 方案功能簡介(一)
- 精選部落格系列|為雲服務商提供遠邊緣無線接入網路架構的選擇和靈活性
- 精選部落格系列|面向公共安全的SD-WAN Edge:重新整理VMware邊緣計算棧
- 精選部落格系列|將基於決策樹的Ensemble方法用於邊緣計算
- 精選部落格系列|加速基於同態加密的隱私保護機器學習
- 雲原生安全檢測器 Narrows(CNSI)的部署和使用
- 雲原生安全檢測器 Narrows釋出,在Harbor上增加容器安全的動態掃描
- FedLCM:統一的聯邦學習生命週期管理平臺
- TAP 文章系列-13 | 基於 Knative 的 TAP 雲原生執行時
- 大V科技談 | VMware雲和邊緣基礎架構創新實現突破性的效能提升
- TAP 文章系列-11 | 利用 TAP 實現應用雲除錯與面向開發者的應用執行狀態監控
- TAP 文章系列-12 | 小步快跑的程式碼掃描,實現質量左移
- TAP 系列文章5 | 雲原生構建服務
- 系列文章|雲原生時代下微服務架構進階之路 - Event Storming
- 系列文章|雲原生時代下微服務架構進階之路—微服務簡介
- 聯合解決方案系列|VMware MultiCloud Lab多雲大資料聯合方案展示
- TAP 系列文章2 | Tanzu Application Platform v1.1 安裝配置步驟
- 聯合解決方案系列|VMware和星雲Clustar聯合釋出多雲聯邦學習解決方案
- TAP 系列文章 | Tanzu Application Platform 的技術概覽