雲端是當今顯學,基於保密及資安考量,許多企業還是會選擇在地端甚至網路隔離環境作業。微軟的版控解決方案 - TFS Server 的繼任者是 Azure DevOps Server,雖有 Azure 之名,但可在安裝在企業內部隔離網路環境,稱職扮演地端版控伺服器角色。

最近嘗試在 Azure DevOps Server 跑 Pipeline 編譯 ASP.NET 專案。我的測試情境是 Azure DevOps Server 2022 配 Self-Hosted Agent 完全在內網解決,連 NuGet 套件都採離線處理,是道道地地的地端戰技演練,這篇記錄過程處理的一些眉角。

我對 TFS (Azure DevOps 前身) 自動編譯的理解還停在 TFS Build Service 2015,動手前先更新了觀念。Azure DevOps 靠 Azure Pipeline 處理自動建置、自動測試、自動部署等作業。而這類作業要交由 Azure Pipelines Agent(代理程式) 執行。若為 Azure DevOps Service 雲端服務,可使用雲端 Agent;若要在地端環境使用,需要 Agent 角色的理由有二,一是建置及測試作業很吃硬體資源,需視需求準備足夠主機安裝 Agent 組成 Agent Pool 消化需求;二則個別專案所需的編譯、測試資源以及部署對象可能位處有特定網段,Agent 可就近安裝執行以克服網路存取限制。


圖片來源

Agent 程式可視需要安裝在 Windows/macOS/Linux 上,執行時只以 HTTPS/HTTP 連上 Azure DevOps Server 接受指令執行作業及回報結果(使用 HTTP Long Polling 等待指令,傳輸內容使用 Agent 專屬公私鑰加密),不需開通 Server 對 Agent 方向的防火牆,部署上還算方便。參考


圖片來源

以下記錄我新手上路有卡頓的地方:

  1. Azure DevOps Server TLS 憑證
    我選擇走 HTTPS 使用 AD CA 發的憑證,上回裝 AD FS 學會從 Local Computer 憑證管理員 Personal / Certificates 右鍵 All Tasks / Request New Certificate 向 CA 申請憑證的密技。學以致用,我省掉製作憑證請求檔、上傳、下載安裝的一串動作,填個 Common Name 跟 DNS 快速裝好 IIS 用的憑證。
  2. 讓 Git 認得 AD CA 根憑證
    技巧之前學過針對特定使用者信任 CA 根憑證,這回學到的新知識是將 CA 根憑證加到 C:\Program Files\Git\mingw64\etc\ssl\certs\ca-bundle.crt 可跨使用者生效,特別適合 Agent 會用 NETWORK SERVICE 或 gMSA 等特殊帳號執行的情境。延伸閱讀:順推使用 gMSA 讓 Windows 排程與服務帳號更安全
  3. 設定 Self-Hosted Windows Agent
    安裝說明可參考官方文件,這裡只補充三點:
    1. 測試階段可採互動執行,實際運轉時建議裝成服務
    2. 對 SERVICE_SID_TYPE_UNRESTRICTED 不是很懂,但感覺是像 IIS APPPOOL\XXX 之類的處擬身分 參考
    3. 服務執行身分建議使用 NETWORK SERVICE 或 MSA
  4. 將 Self-Hosted Windows Agent 裝成服務後,可以在服務管理員看到它:

    Agent 啟動後會自動偵測主機有安裝哪些開發及測試工具,依 Agent 的能力(Capability)判定能執行哪些作業,若事後加裝工具,記得要重啟上述 Agent 服務讓系統重新識別。
  5. 定義 Pipeline 有兩種做法,第一種傳統做法是使用 GUI 介面設定,定義檔為 JSON 格式由 DevOps 主機儲存管理;第二種則是寫成 YAML 檔案跟其他原始碼一起簽入版控,最大優點是當程式改版,編譯、測試、部署設定寫在 YAML 檔可跟著程式碼一起改版,存在同一個 Commit,不會出現程式碼跟 Pipeline 定義版本脫節的狀況。新增 Pipeline 時,可選擇要寫 YAML[1] 還是走 Calssic Editor 用 GUI 操作編譯[2]:

    初學者如我本次是選擇用 GUI 較好上手,但依我偏好 CLI 多於 GUI 的個性,加上 YAML 是主流 (Github Actions 就是用 YAML),YAML 應會是我最終的選擇,這部分留待未來再深入。
  6. .NET Framework 編譯時 NuGet Restore 錯誤
    預設 ASP.NET Pipeline 模板的 Use NuGet 是 4.4.1 版,會出現以下錯誤:
    ##[error]The nuget command failed with exit code(1) and error(Error parsing solution file at C:\Agent\_work\2\s\AspNetWeb\AspNetWeb.sln: Exception has been thrown by the target of an invocation. Could not load file or assembly 'Microsoft.Build.Framework, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.)
    換成 6.7.0 版問題排除
  7. 離線 NuGet 套件庫
    Agent 所在主機可能無法連 Internet 線上下載 NuGet 套件,我的做法是在本機建目錄 C:\LocalNuGetStore 放入用到的 .nupkg 檔,設定一個 NuGet.config 指定來源:
     <?xml version="1.0" encoding="utf-8"?>
     <configuration>
       <packageSources>
         <add key="LocalNuGetStore" value="C:\LocalNuGetStore" />
       </packageSources>
       <packageRestore>
         <add key="enabled" value="True" />
         <add key="automatic" value="True" />
       </packageRestore>
       <bindingRedirects>
         <add key="skip" value="False" />
       </bindingRedirects>
       <packageManagement>
         <add key="format" value="0" />
         <add key="disabled" value="False" />
       </packageManagement>
     </configuration>   
    
    C:\Program Files (x86)\Microsoft Visual Studio\Shared\Packages 目錄有許多基本套件,建議都放進去當基底。使用資料夾管理 .nupkg 檔,好處是簡單且可用 Git 實現簡單的版本管控,但搜尋效能很差。若要重度使用,自建私有 NuGet 伺服器是更完善的解決方案。

ASP.NET Core 及 ASP.NET 專案的 Azure Pipeline 地端編譯首航成功!

Notes of how to deploy and use self-hosted Windows agent for Azure Pipeline in isolated network environment.


Comments

Be the first to post a comment

Post a comment