前情提要
我目前主要使用 GitLab 進行版本控制和持續集成(CI/CD),
主要整合 Google Cloud Platform (GCP) ,許多專案都運行在 GCP 上。
因商務需求最近開始探索第二朵雲 Azure。
雖然 Azure DevOps 也有提供 CI/CD 與 Repo 的解決方案;
但為了減少邏輯與認知負擔,我希望能將 GitLab 與 Azure DevOps Pipeline 進行整合。
具體來說,這次要在 Azure Functions 上部署 Python 應用程式,
我想要 RD 往 Gitlab 推送並執行 CI/CD 就好,而不用特別因為服務在不同的雲上,而需要推送到不到同 Repo 中 。
面對這樣的需求,下面是我找到的解決方案。
實作
以這次的例子來說,我需要控管 Azure 的 Serverless 解決方案「Azure Functions」的程式。
但是 Azure DevOps Pipeline 有相當高度的整合 Azure Cloud,只要能將程式推送到 Azure DevOps Repo,
部署就會相當簡單,而無需處理繁鎖的授權問題。
CI/CD 流程大致如下
- 建立相對應的權限與憑証並提供給 Gitlab-Runner
- RD 推送新版本程式給 Gitlab,觸發 Gitlab-Runner
- Gitlab-Runner 執行測試、建置等相關作業後,部署到 Azure Functions
設置 Azure DevOps Pipeline:
- 選擇 New pipeline
- Other Git
- 設定連線方式 & 選擇分支
- Connection name (任意命名)
- Repo URL 輸入 Gitlab Repo URL
- User Name (任意命名)
- Password / Token Key (Gitlab PAT,需注意效期)
- 使用「Azure Functions for Python」Template
- Build extensions
- Use Python 3.10(可以更換合適的版本)
- Install Application Dependencies
- Archive files
- Publish Artifact: drop
- 追加 Agent job Task
- 搜尋「Azure Functions Deploy」
- 填寫
- Azure Resource Manager connection
- Manage > Service Connection > New Service Connection > Azure Resource Manager > Service principal(automatic)
- Service connection name
- Description (optional)
- 也可以選擇 > Service principal (manual),需要先加上 App registrations 具體流程如下:
- 在 Azure Portal 上建立一個新的 Azure Registration。
- 選擇 Certificates & secrets,建立一組 Certificates & secrets。
- 回到 Service principal (manual)
- Subscription Id
- Subscription Name
- Service Principal Id (App registrations Client secrets 的 Secret ID)
- Service principal key (App registrations Client secrets 的 Value)
- Tenant ID
- Manage > Service Connection > New Service Connection > Azure Resource Manager > Service principal(automatic)
- App type (我的情況是選 Function App on Linux)
- Azure Functions App name
- Azure Resource Manager connection
配置 GitLab CI/CD:
- 在 GitLab 中,建立
.gitlab-ci.yml
如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31image: debian:stable-slim
variables:
AZURE_PIPELINE_NAME: "dispatch-worker-deploy-pipeline"
before_script:
- apt-get update && apt-get install -y curl jq
stages:
- deploy
trigger_pipeline:
stage: deploy
script:
- |
json=$(curl -u $AZURE_DEVOPS_USER:$AZURE_DEVOPS_PAT \
-H "Content-Type: application/json" \
"https://dev.azure.com/Aiplux/Inpas/_apis/build/definitions?api-version=6.0")
id=$(echo $json | jq -r --arg pipeline_name "$AZURE_PIPELINE_NAME" '.value[] | select(.name==$pipeline_name) | .id')
echo -e "\033[1;33mPipeline: $AZURE_PIPELINE_NAME ID is $id\033[0m"
RESPONSE_CODE=$(curl -X POST "https://dev.azure.com/My_Organization/My_Project/_apis/build/builds?api-version=6.0" \
--data '{"definition": {"id": '$id'}}' \
-u ${AZURE_DEVOPS_USER}:${AZURE_DEVOPS_PAT} \
-H 'Content-Type: application/json' \
-w "%{http_code}" -o /dev/null -s)
if [ "$RESPONSE_CODE" -ne 200 ]; then
echo -e "\033[1;31mRequest failed with status code $RESPONSE_CODE\033[0m"
exit 1
fi
rules:
- if: '$CI_COMMIT_BRANCH == "main"'可以看到 AZURE_DEVOPS_USER 與 AZURE_DEVOPS_PAT 兩個參數,
可以在登入 Azure DevOps 後,在 User Settings >> Personal Access Tokens 取得,
實務上由管理者提供,但是有時效性,仍然需要定期更新(1年),應該有更簡便的方法才對。- 在 GitLab 中,建立
完成以上的設定後,只要推送到 Gitlab Repo 的 main 分支,就會觸發 Azure DevOps Pipeline 部署。
踩雷
在整合過程中遇到了一個問題。
儘管使用了 Azure Pipeline 提供的官方模板,部署過程依然出現了錯誤。
具體而言並沒有明顯的錯誤,但是 Log 會記錄
1 function found
0 function loaded
導致 Azure Functions Apps 無法正常工作。
解法
在 Azure Functions for Python 其中一步驟 Install Application Dependencies
Template 如下:
1 | python3.6 -m venv worker_venv |
需要修改成才能作用,不確定 Azure 會不會提出修正或新的 template
1 | python3.10 -m venv .python_packages |
查閱了 Azure 和 GitLab 的官方文檔以及技術社群中的討論,找到了有效的解決方案。
通過修改 template,成功解決了部署問題,
GitLab 和 Azure DevOps Pipeline 的整合成功。
參考
(fin)