Azure DevOps 服務 |Azure DevOps Server |Azure DevOps Server 2022 |Azure DevOps Server 2020
本文說明如何在 Azure Pipelines 的 環境 中使用 Kubernetes 資源,您可以將其作為部署目標。 您可以連線到 Azure Kubernetes Service (AKS) 或其他雲端提供者中的公用或私人 Kubernetes 叢集。
環境資源檢視顯示 Kubernetes 資源的狀態,並提供管線的追蹤能力,使其追溯到觸發的提交紀錄。 您也可以建立動態 Kubernetes 環境資源,以在合併之前檢閱提取要求。 如需環境資源的詳細資訊,請參閱 YAML 管線中的資源 和 資源安全性。
注意
私人 AKS 叢集不會透過公用 IP 位址公開其 API 伺服器端點,因此您必須連線到叢集的虛擬網路。 您可以在虛擬網路內設定自我裝載代理程式,以存取叢集的虛擬網路或使用 受控 DevOps 集區。 如需詳細資訊,請參閱 連線至私有叢集的選項。
Kubernetes環境資源優勢
環境中的 Kubernetes 環境資源和資源檢視有以下幾個優點:
管道可追溯性。 Kubernetes manifest 部署任務會新增支援流水線追溯性的註解。 您可以看到負責更新命名空間內物件的 Azure DevOps 組織、專案和管線。
資源健康情況診斷。 工作負載狀態檢視是偵錯新部署所引進的錯誤或迴歸的快速方法。 例如,Pod 狀態資訊可協助您識別問題原因,如未設定
imagePullSecrets所導致的ImagePullBackOff錯誤。
審查應用程序。 檢閱應用程式會將 Git 存放庫中的每個提取要求部署至環境中的動態 Kubernetes 資源,並張貼連結至檢閱應用程式的 GitHub 註解。 檢閱者可以在將變更合併至目標分支並部署至生產環境之前,查看 PR 變更的外觀,以及與其他相依服務搭配使用的方式。
AKS 資源
AKS 會在您選擇的叢集和命名空間中建立 ServiceAccount ,並將環境中的 Kubernetes 資源對應至指定的命名空間。 如需在環境外部設定 Kubernetes 服務連線的相關資訊,請參閱 Kubernetes 服務連線。
對於已啟用 Kubernetes 角色型存取控制 (RBAC) 的叢集,也會建立 RoleBinding ,以將服務帳戶的範圍限制為所選的命名空間。 對於已停用 RBAC 的 Kubernetes 叢集,建立的服務帳戶具有跨命名空間的叢集範圍權限。
若要將 AKS 資源新增至 Azure Pipelines 環境:
在 [管線>環境] 底下的環境頁面上,選取 [ 新增資源 ],然後選取 [Kubernetes]。
在下一個畫面上,選取 Azure Kubernetes Service 作為 提供者,然後選取您的 Azure 訂用帳戶、AKS 叢集以及新的或現有的 命名空間。 對於新的命名空間,請輸入命名空間名稱。
選取 驗證並建立。 新資源會出現在環境的 [資源] 索引標籤上,並顯示文字 [從未部署]。
非 AKS 的 Kubernetes 資源
若要將 Kubernetes 資源從非 AKS 叢集對應至命名空間,您必須擁有非 AKS 提供者的現有服務帳戶。
若要將非 AKS Kubernetes 資源新增至 Azure Pipelines 環境:
在 [管線>環境] 底下的環境頁面上,選取 [ 新增資源 ],然後選取 [Kubernetes]。
在下一個畫面上,為提供者選取一般提供者(現有服務帳戶)。
在 叢集認證下,輸入 叢集名稱、 命名空間、 伺服器 URL 和 密碼。
若要取得伺服器 URL,請在本機 shell 中執行
kubectl config view --minify -o jsonpath={.clusters[0].cluster.server}。要獲得秘密:
- 執行
kubectl get serviceAccounts <service-account-name> -n <namespace> -o=jsonpath={.secrets[*].name}以取得服務帳戶密鑰名稱。 - 使用上述命令的輸出來執行
kubectl get secret <service-account-secret-name> -n <namespace> -o json。
注意
如果您執行
get ServiceAccounts命令時沒有任何結果,請參閱 手動建立 ServiceAccount 的持久性 API 權杖。- 執行
選取 驗證並建立。
管線中的 Kubernetes 資源
建立要部署至 AKS 的 YAML 管線最簡單的方式是從 部署至 Azure Kubernetes 服務 範本開始。 您不需要撰寫 YAML 程式碼,或手動建立明確的角色繫結。 產生的管線會根據您的組態設定設定並使用變數和其他值。
使用評論應用程式
作業 DeployPullRequest 會將 Git 存放庫中的每個提取要求部署至環境中的動態 Kubernetes 資源。 若要將此作業新增至管線,請選取 [部署至 Azure Kubernetes 服務] 組態表單中的 [啟用提取要求的檢閱應用程式流程] 複選框。
注意
若要將此作業新增至現有管線,請確定支援一般 Kubernetes 環境資源的服務連線已設定為 [使用叢集管理員認證]。 否則,必須為基礎服務帳戶在檢閱應用程式命名空間建立角色綁定。
檢閱應用程式資源在環境的資源清單中標示為檢閱。
範例管線
下列範例管線是以 部署至 Azure Kubernetes Services 範本為基礎。 管線會先建置映像,並將其推送至 Azure Container Registry。
然後,第一個部署作業會針對 main 分支的任何提交執行,並在環境中部署至常規的 Kubernetes 資源。
第二個作業會在建立 PR 或更新 main 至分支時執行,並視需要針對它在叢集中建立的動態檢閱應用程式資源進行部署。
# Deploy to Azure Kubernetes Service
# Build and push image to Azure Container Registry; Deploy to Azure Kubernetes Service
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker
trigger:
- main
resources:
- repo: self
variables:
# Container registry service connection established during pipeline creation
dockerRegistryServiceConnection: '12345' # Docker service connection identifier
imageRepository: 'name-of-image-repository' # name of image repository
containerRegistry: 'mycontainer.azurecr.io' # path to container registry
dockerfilePath: '**/Dockerfile'
tag: '$(Build.BuildId)'
imagePullSecret: 'my-app-secret' # image pull secret
# Agent VM image name
vmImageName: 'ubuntu-latest'
# Name of the new namespace being created to deploy the PR changes.
k8sNamespaceForPR: 'review-app-$(System.PullRequest.PullRequestId)'
stages:
- stage: Build
displayName: Build stage
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- task: Docker@2
displayName: Build and push an image to container registry
inputs:
command: buildAndPush
repository: $(imageRepository)
dockerfile: $(dockerfilePath)
containerRegistry: $(dockerRegistryServiceConnection)
tags: |
$(tag)
- upload: manifests
artifact: manifests
- stage: Production
displayName: Deploy stage
dependsOn: Build
jobs:
- deployment: Production
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/pull/')))
displayName: Production
pool:
vmImage: $(vmImageName)
environment: 'myenvironmentname.myresourcename'
strategy:
runOnce:
deploy:
steps:
- task: KubernetesManifest@1
displayName: Create imagePullSecret
inputs:
action: createSecret
secretName: $(imagePullSecret)
dockerRegistryEndpoint: $(dockerRegistryServiceConnection)
- task: KubernetesManifest@1
displayName: Deploy to Kubernetes cluster
inputs:
action: deploy
manifests: |
$(Pipeline.Workspace)/manifests/deployment.yml
$(Pipeline.Workspace)/manifests/service.yml
imagePullSecrets: |
$(imagePullSecret)
containers: |
$(containerRegistry)/$(imageRepository):$(tag)
- deployment: DeployPullRequest
displayName: Deploy Pull request
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/pull/'))
pool:
vmImage: $(vmImageName)
environment: 'myenvironmentname.$(k8sNamespaceForPR)'
strategy:
runOnce:
deploy:
steps:
- reviewApp: default
- task: Kubernetes@1
displayName: 'Create a new namespace for the pull request'
inputs:
command: apply
useConfigurationFile: true
inline: '{ "kind": "Namespace", "apiVersion": "v1", "metadata": { "name": "$(k8sNamespaceForPR)" }}'
- task: KubernetesManifest@1
displayName: Create imagePullSecret
inputs:
action: createSecret
secretName: $(imagePullSecret)
namespace: $(k8sNamespaceForPR)
dockerRegistryEndpoint: $(dockerRegistryServiceConnection)
- task: KubernetesManifest@1
displayName: Deploy to the new namespace in the Kubernetes cluster
inputs:
action: deploy
namespace: $(k8sNamespaceForPR)
manifests: |
$(Pipeline.Workspace)/manifests/deployment.yml
$(Pipeline.Workspace)/manifests/service.yml
imagePullSecrets: |
$(imagePullSecret)
containers: |
$(containerRegistry)/$(imageRepository):$(tag)
- task: Kubernetes@1
name: get
displayName: 'Get services in the new namespace'
continueOnError: true
inputs:
command: get
namespace: $(k8sNamespaceForPR)
arguments: svc
outputFormat: jsonpath='http://{.items[0].status.loadBalancer.ingress[0].ip}:{.items[0].spec.ports[0].port}'
# Get the IP of the deployed service and writing it to a variable for posting comment
- script: |
url="$(get.KubectlOutput)"
message="Your review app has been deployed"
if [ ! -z "$url" -a "$url" != "http://:" ]
then
message="${message} and is available at $url."
fi
echo "##vso[task.setvariable variable=GITHUB_COMMENT]$message"