Artifacts Management


Artifacts 是 CI/CD 很關鍵的點,他承接著接下來整個 Development Pipeline 的樞紐因子,能否有靈活、有彈性的佈署,都仰賴於 Artifacts Management。

Artifact 的目的就如同交付軟體給另一個陌生人,他可以透過取得一個檔案 (通常是壓縮檔),然後解開後,依據 README.md 的說明,不管手動還是自動,可以自行完成部署或者安裝。而這個過程交付的 一個檔案 就稱作 Artifacts,在 github 上來講,就是 releases 上的檔案,像是 awscli

這段整理後來的在社群 Meetup 的分享:聊聊軟體交付的濫觴 談產出物管理 (Artifacts Management)


基本概念

本文延伸 導入 CI/CD 的第一步Designing Test Architecture and Framework 提到的概念,重新整理關於 Artifact Management 的實踐經驗談,也就是如何從 Source Code 經過 Build or Packing 的過程,得到產出物 (Artifact),有了此步驟之後,才有後續的持續整合 (CI)、持續部署 (CD)、各式各樣的整合與自動化測試、然後才是 持續交付價值 (Continuous Delivery Values)

重點是:不只是可以部署到正式環境,而是 任何人 可以自行決定,部署到 任意環境(不管手動、還是自動),目標就是底下張圖:

注意:

  1. 如果這個過程只能自動,卻無法手動,當自動程序有問題的時候就完蛋了。
  2. 如果只能自動部署到正式環境,但測試環境卻無法自行決定如何部署,這表示未來測試會是瓶頸。
  3. 如果無法透過 Artifact 交付部署,未來業務發展會受到影響,換句話說:公司長不大

Learning from Open Source Software (OSS)

談持續交付的實踐,通常建議不要先扯一堆工具,像是 Gitlab CI、Jenkins … 等,這些很重要,但是常常會讓很多不了解的人,抓不到方向,或者陷入技術的陷阱。從怎麼用軟體開始學習交付這件事情,,底下的例子是很常見的安裝方式:

1
2
3
## 安裝 kubectl
# See: https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl

這一段的精神就是下載 最新版本的 Artifact,其中:

  • https://storage.googleapis.com/kubernetes-release/release/stable.txt 取得版本名稱,像是 v1.13.2
  • 再利用版本名稱,組合出實際下載 binary 的路徑

再舉一個例子 kops 的安裝

1
2
# See: https://github.com/kubernetes/kops
curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64

概念則是透過 github release api 取得 Artifact Meta (後述),然後取得關鍵的資訊,例如 tag 名稱,也就是版本。底下是取得 Release Info 的例子:

再舉一個例子是 docker 的安裝,也是一行

1
curl -fsSL https://get.docker.com/ | sh

這些概念基本上都是: Learning from Open Source Software


定義

Artifact 中文翻譯成 產出物,在以前 Release Engineering 慣稱為 Build、Image,主要就是 Source Code 經過 編譯 (Compile)打包 (Packing) 最後的產出物。不管是什麼樣的語言,大致上都要經過這個過程。要注意的是,這個過程產出的東西,不包含 ConfigurationSettings 之類的東西,有也只是 Templates、Sample。

Config Management 和 Settings 的概念,有空另外整理專文。

目的

Artifact 目的就是要讓其他人、或者程式可以獨立部署。人會有以下:

  • 內部的人:包含測試團隊、維運團隊、研究團隊,當然也包含開發團隊自己
    • 跨地域的團隊,像是台灣的團隊,給美國團隊部署
    • 跨團隊的權責切分,開發交付給測試的切點
  • 外部的人:像是交付給其他合作夥伴自行部署
    • 遊戲產業很常是韓國負責開發,台灣則維運。
    • 整併的組織,權責移交
    • 新業務需求部署
    • 給客戶使用的沙箱環境
  • 災難還原

在開發過程會出現的問題案例:

測試測出問題,去跟開發講,開發說我找找。結果偷偷在 local 改了 code,然後跟測試說沒問題。

這個現象,是實務上卻是真的發生過的,同時造成的溝通成本很高。比較切確的做法是:

  1. Tester 回報問題,附上 Artifact Meta 的資訊
  2. Dev 根據回報的內容復現問題

因為 Artifact Meta 會包含像是 git hashcode, branch, version, datetime 等資訊,可以讓雙方精準溝通,而不會有雞同鴨講的狀況。詳細參閱 如何有效的回報問題 (How to Report Problems Effectively)

所以簡單說,透過 Artifact 解偶 (decouple) 整個 pipeline,讓需要的角色可以獨立作業。如果 pipeline 只能是一件部署,而沒有其他的選擇,那麼表示部署流水線是沒有任何彈性的,換言之,部署的主動性只有開發團隊有,其他人都無法自主,造成的現象就是 強耦合 (couple),當有第二、第三環境要部署的時候,就要重新 Pull Code、Build … 實際上是沒有意義的。

Artifact Types

Artifacts 類型很多,整理如下:

  • Application Build: 也就是一般開發者寫的應用程式產出物,可能是透過:
    • Compile: Java, C#, Golang, C, C++ ….
    • Packing: Node.js, Webpack, PHP …
  • Docker Images: Dockerfile 編譯出來的 Images
  • App Libraries:
    • 應用程式依賴的函式庫,通常需要做資安檢測,或者考慮網路頻寬
    • 自行開發的函示庫。像是 npm, NuGet, …
  • VM Images: 虛擬機的 Image, 像是 Vagrant, AWS Machine Image (AMI) … 等。
    • 主要是一些中介軟體的配置管理、應用程式依賴的系統軟體、函式庫等
    • 透過 Image + Auto Scaling 快速更新 OS Patch, Security Issues.
    • Netflix 是使用 AMI 做管理到極致的案例,參見:AMI Creation with Aminator

這些 Artifacts 實際上基於一些因素,像是資安、維運效率化、一致性、部署等因素,需要納管、受控。

具備一定規模的企業,都會有私有的 Artifact Repository,甚至把 Open Source 都複製一份,內部修改過後,檢查資安、安規、移除不必要的依賴,重新 Build 提供 Binary ,並規定只能使用這樣的版本。

Artifact Metadata

Artifact 必須包含以下這些重要的資訊 (Metadata),讓其他人、或者程式可以串接:

  • AppName:應用程式名稱
  • Version:通常是三碼規則 (x.y.z), 詳細參閱 Version Control 或者 Semantic Versioning
  • Timestamp:Packing 的時間,通常是像 20180701-1200 這樣的結構
  • BuildId:簽入 (Commit/Checkin) 的序號:git hash or svn number
  • BuildType:預先為正式環境、測試環境置入的 Configuration,這段依照產品特性,會有不同的作法。正式版通常會有以下:
    • 通常會有 Sign 一些東西,像是版權控管之類的
    • 會有 md5checksun,作為傳輸檢查用
    • 相依的資源都會有
  • Branch:根據產品性質,可能會有特殊 Branch 的編號,像是客製化的版本。
  • Meta:其他 Build 的 Meta 資訊,可以讓 CI/CD 串接使用。

這些資訊是之後持續整合的關鍵資料,不管是自動化測試、還是部署、還是交付給其他單位。相關例子參閱:Version Control。如果要自動化串接,則可以提供 API,像是 github 的 Release API

相關參閱 Version Control

產出物的存放

Artifact 盡可能集中儲存在 Storage Services,讓需要的人透過身份驗證可以自行存取。

這個存放空間通常會規劃底下結構:

  • Release: 每個釋出的版本,通常會有 sign + md5 checksum,樣子大概就是一般下載 open source 時看到的目錄結構
  • Dev: 通常會依照各個 products / roles / components 再細分目錄
    • 每個目錄都會有個叫 LATEST 的 softlink,連結最新的 build
    • 依照產品或者 component 特性,會額外放置其他資料,像是 metadata、sample config

早期我習慣然後透過 Apache Index 方式分享出來,也曾經做過比較複雜的 console 一鍵部署。現代作法應該就是直接提供 API,可以取得 Artifact Meta 串接自動化。

底下是要注意的:

  • Artifacts 會一直長,所以要有 rotation 機制。
  • 如果是放在 AWS S3 則可以透過 Lifecycle 管理。
  • 要注意是否要至少保留一定數量,避免太久沒有 build,最後全被刪光了。

類似的產品有:Artifactory, Nexus

不同目的的部署

Stages in Software Testing 一文提到很多測試方法、策略,其實每種測試都有期目的性,考量的東西不一樣,需要的部署也不一樣,但是在邏輯與抽象架構概念,他們的部署、與架構方法,應該都是一致的!

  • 功能性測試 (FVT):麻雀雖小,五臟俱全
  • 整合性測試 (Integration):有彈性
  • 系統性測試 (System Test):有彈性

不同測試目的,有不同的架構,不同架構有不同的部署方法,他們都需要同樣的 Artifacts

誰來觸發自動部署?

這篇文章:持续交付:当前普遍存在的三个问题与解决方案 最後的表格提到 Dev、Test、Acceptance、Production 四個環境,最後有部署者,其中測試是 CI 自動觸發 (自動部署),這點是有問題的。

真實的測試情境是這樣的,以下是簡單的過程:

  • 測試人員部署指定的版本到指定的環境,透過手動 or 自動跑測試
  • 測試人員發現問題,檢查系統的 Log 找問題、檢查測試資料、情境
    • 測試人員想比較兩個版本的差異,確認問題,指定前一個版本,重新部署環境
    • 測試人員想比較兩個版本的差異,確認問題,指定某個版本,重新部署環境
  • 測試人員確認問題的原因,開始開 Defect,整理測試步驟、蒐集問題的 Log

這些過程是基本的,實際的可能更複雜,因為要跟 Developer or PM 確認問題,甚至要確認環境建置之類的。

如果這個過程,如果測試環境被 CI 自動觸發 (自動部署),整個現場就毀了!測試等於被中斷。


持續整合與部署的第一步

在讀書會 Continuous Delivery 裡,我其實都很強調這個概念:

  1. 你平常怎麼使用別人的軟體?
  2. 哪些人可以部署?
  3. Learning from Open Source Software

我不太強調怎麼部署工具這件事情,因為技術隨時代會不斷改變,不管是 Jenkins、Gitlab CI、Drone、AWS CodeDeploy … 因為這些都做得到我想要的事。但是往往錯誤的觀念,會誤導團隊的前進,嚴重的甚至會影響整個公司的發展。

我很強調要看到下面這張圖四個面向:

如何實踐團隊的自主性

底下的 Youtube 是摘錄我在內部教育訓練的影片,主要說明這段 前提 重要性,以及 讓團隊在技術上自主性 的重要性。相關的關鍵字有:自主性、DevOps, Architecture, CI/CD, Provisioning, Infra as Code, Artifact Management

捨本逐末,一步登天

過去,我一直覺得這應該是每個公司都會做的,所以很少提這段。最近發現,太多人都過於強調所謂 自動化部署,反而忽略最基本的工作:

不知道應該要有 Artifact ,讓其他人可以獨立部署。

這代表什麼?這代表:

  1. 無法完整建立整個測試過程所需要的資源!沒有 Resource Provisioning 的概念
  2. 不知道測試會因目的,而有不同的配置,但架構邏輯是一樣的。表示沒有清楚的系統架構概念!沒有看到全貌!
  3. 測試人員無法自己部署!測試可能隨時被中斷!產品沒有品質
  4. 無法做其他進階測試,像是整合、效能、部署驗證等。

現代太多 CI/CD 工具都強調一鍵佈署,但是佈署到哪卻很少提,所以當要部署不同情境的需求時,因為太自動,反而失去該要有的彈性!

老人當年勇

為什麼我會一直強調這件事情,因為不管在 Artifacts 的建置、管理,或者在帶測試團隊的時候,Artifact 是關鍵點。底下是當年的足跡,也是 Designing Test Architecture and Framework 一文中沒提到的,因為我覺得這是基本功:

下圖是當時自動化測試的 Artifact 管理介面 (用 ZK 寫的),主要會自動 mirror 米國的 build,然後建立 aritfact metadata,重點:

  • 有分 rel / dev 兩種
  • 每組 artifacts 的 metadata 都在資料庫
  • 由需要的人自行選擇要部署的版本 (right click)

底下這張圖是我在 協同合作系統建制與導入 - 以 Redmine 為例 提到的 Build,這段做得比較簡單,但是卻是最常見的做法:

Continuous Delivery – Opening

書開宗明義第一張就講了,這段話就是核心重點:

其他公開討論:

SaaS 平台 (Updated: 2019/01/18)

下圖是 2018/07/24 我在 FB 上隨機問的小題目,這樣的條件是我定義的 產品服務化 的基本要素。而問這問題目的就是想了解大家對於 持續交付 的想像與應用,而這個題目就可直接創造出有意義的價值,交付價值的最大化,而要做到這一步的基本條件就是 Artifact Management 要做好。

符合這樣的產品很多,AWS 的 SaaS 都是,像是 ElastiCache、RDS,外面的產品像是 CloudAMQP、一些 Wordpress 的 Provider 都是。

PS: 圖中文字的 PaaS 應該更正為 SaaS


延伸閱讀

站內文章

延伸閱讀

更新紀錄

  • 2019/01/18: 新增 Learning from Open Source Software (OSS)SaaS 栗子的段落

Comments