無論你用哪一套 DevOps Tool,在設定代理程式 (Agent) 所在的環境都會遇到一個千古難題:隨著時間用久,越來越難管理。Pipeline 執行過程所需要的開發套件,必須要安裝在代理程式所在的伺服器上,讓代理程式具備能力(capability) 才能執行相關的工作。舉例來說,你要執行 .NET (.NET Core) 編譯,必須要安裝 .NET SDK;如果要執行 Java 相關工作,則必須要安裝 JDK;如果要進行安全掃描,就必須安裝相關工具。
如果在組織資源有限情況下,越多越多專案共用代理程式,資安要求測試左移加入許多掃描工作,平台管理人員會漸漸發現代理程式伺服器安裝開發工具越來越多,代理程式開始漸漸不穩定,相關人員花越來越多時間在找那些套件沒裝、那些套件版本互斥,反而更耗時費力。
有些 IT 單位早期為了解決這個問題,或使用虛擬機器印象檔管理方式,代理程式伺服器損壞時快速建立並取代。現在你有更好選擇 - 在 Agent 上透過 Container 來處理 Task,平台維護人員只需要確認代理程式可以執行 Container,跑次 CI 流程都是乾淨的環境。此外,單一 Container 處理單一職責 Task,容易維護也不會造成 Agent 環境過於複雜。
首先,Azure Pipeline YAML 內有個相當重要的語法: resource,它定義了各種來源,包含 Pipeline、Build、Repository、Container、套件和 Webhook,讓 Pipeline 取用。強大的是,你可以訂閱 Resource 觸發事件,達到完全自動化工作流程。在本篇文章,我們將定義多個 Container resources,以提供後 Step/Task 使用,下列是 Container 定義:
resources:
containers:
- container: string # 識別名稱 (A-Z, a-z, 0-9, 與底線)
image: string # Image 名稱
options: string # Container 啟動時帶入的參數
endpoint: string # 使用的 service connection (預先設定好 private registry)
env: { string: string } # 要加入的懷竟變數
ports: [ string ] # expose ports
volumes: [ string ] # mount volumes
mapDockerSocket: bool # 是否在 Docker daemon socket 啟用 map; 預設為 true
下列為一個 Container 範例,我們定義了從公開 dockerhub 下載 python 3.8 與 node:13.2 Image,並從已經設定好的 service connection (private registry) 下載自己做好的 securityTool 7.1,讓後面的 Step 或 Task 使用。
IT 可以包裝持續整合每個步驟所需要的 Image,以方便執行測試、安全掃描或產生報告。
resources:
containers:
- container: python
image: python:3.8
- container: node
image: node:13.2
- container: securityTool
image: securityTool:7.1
endpoint: privateHarbor
Target 定義如下:
實作 | 描述 |
---|---|
target:string | 要在其中執行此步驟或工作的環境 |
target:container、commands、settableVariables | 使用環境設定步驟目標,以及允許的命令和變數清單 |
下列範例是一個定義兩種 Container,在 Job、Step 內使用的範例。隨時可以切換 Container 執行相關語法,相當方便。
resources:
containers:
- container: python
image: python:3.8
- container: node
image: node:13.2
jobs:
- job: example
container: python
steps:
- script: echo Running in the job container
- script: echo Running on the host
target: host
- script: echo Running in another container, in restricted commands mode
target:
container: node
commands: restricted
下列範例是一個定義兩種 Container,並在不同 Task 使用的範例 (理所當然,container 可以在不同的 task 多次被使用)
resources:
containers:
- container: pycontainer
image: python:3.11
- container: node
image: node:13.2
steps:
- task: SampleTask@1
target: node
- task: AnotherTask@1
target: pycontainer