使用 Azure Pipelines 和 Google Kubernetes Engine 建立持續整合/持續推送軟體更新管道

Last reviewed 2022-11-29 UTC

本教學課程說明如何使用 Azure PipelinesGoogle Kubernetes Engine (GKE) 和 Google Container Registry,為 ASP.NET MVC 網頁應用程式建立持續整合/持續部署 (CI/CD) 管道。為符合本教學課程的目的,您可以選取下列兩個範例應用程式:

  • 使用.NET 6 .0 且在 Linux 上執行的 ASP.NET Core 網頁應用程式
  • 使用.NET Framework 4 的 ASP .NET MVC 網頁應用程式,並在 Windows 上執行

CI/CD 管道使用兩個不同的 GKE 叢集,一個用於開發環境,另一個用於實際工作環境,如下圖所示。

顯示開發人員及使用者如何與應用程式互動的 CI/CD 管道概念圖

在管道的一開始,開發人員會將變更推送至範例程式碼基底。這個動作會觸發管道建立版本,並將版本部署至開發叢集。接著,版本管理員可以升級版本,再將版本部署至實際工作環境叢集中。

本教學課程適用於開發人員和 DevOps 工程師。本教學課程假設您具備 Microsoft .NET、Azure Pipelines 和 GKE 的基本知識。另外,也會要求您擁有 Azure DevOps 帳戶的管理權限。

目標

  • 將 Google Container Registry 連結至 Azure Pipelines,以發布 Docker 映像檔。
  • 準備一個 .NET 範例應用程式,以部署至 GKE。
  • 安全地驗證 GKE,無須使用舊版驗證。
  • 使用 Azure Pipelines 版本管理來自動化調度管理 GKE 部署。

範圍外

本教學課程不會說明如何將 Azure Pipelines 連線至私人 GKE 叢集,或連線至私人授權網路。

費用

在本文件中,您會使用下列 Google Cloud的計費元件:

您可以使用 Pricing Calculator,根據預測用量估算費用。

初次使用 Google Cloud 的使用者可能符合免費試用期資格。

完成本文所述工作後,您可以刪除建立的資源,避免繼續計費,詳情請參閱「清除所用資源」一節。

如要瞭解使用 Azure DevOps 可能需要支付的任何費用,請參閱 Azure DevOps 定價頁面

事前準備

我們通常建議使用不同的專案來處理開發環境工作負載與實際工作環境工作負載,這樣就能分別授予 Identity and Access Management (IAM) 角色與權限。為了簡化操作,本教學課程在一個專案上同時使用兩個 GKE 叢集,其中一個用於開發環境,另一個用於實際工作環境。

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  2. Verify that billing is enabled for your Google Cloud project.

  3. 確認您有 Azure DevOps 帳戶並具備其管理權限。 如果您還沒有 Azure DevOps 帳戶,可以在 Azure DevOps 首頁進行註冊。

建立 Azure DevOps 專案

您可使用 Azure DevOps 來管理原始碼、執行建構與測試,以及自動化調度管理 GKE 部署作業。首先,請在您的 Azure DevOps 帳戶中建立專案。

  1. 前往 Azure DevOps 首頁 (https://dev.azure.com/YOUR_AZURE_DEVOPS_ACCOUNT_NAME)。
  2. 按一下「New Project」
  3. 輸入專案名稱,例如 CloudDemo
  4. 將「Visibility」設為 [Private],然後按一下 [Create]
  5. 建立專案之後,請在左側的選單中按一下「Repos」
  6. 按一下「Import」,從 GitHub 建立 dotnet-docs-samples 存放區的分支,然後設定下列值:
    • 「存放區類型」Git
    • 「Clone URL」https://github.com/GoogleCloudPlatform/dotnet-docs-samples.git
  7. 按一下「匯入」

    匯入程序完成後,您會看到 dotnet-docs-samples 存放區的原始碼。

將 Azure Pipelines 連結至 Google Container Registry

如要為 CloudDemo 應用程式設定持續整合,必須先將 Azure Pipelines 連接至 Container Registry。這個連線可讓 Azure Pipelines 將容器映像檔發布至 Container Registry。

設定服務帳戶以發布映像檔

在專案中建立Google Cloud 服務帳戶

  1. 開啟 Google Cloud 控制台。

  2. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  3. 為了節省輸入專案 ID 和 Compute Engine 區域選項的時間,請執行下列指令,以設定預設的設定值:

    gcloud config set project PROJECT_ID
    gcloud config set compute/zone us-central1-a
    

    PROJECT_ID 替換為專案的專案 ID。

  4. 在專案中啟用 Container Registry API:

    gcloud services enable containerregistry.googleapis.com
    
  5. 建立 Azure Pipelines 用於發布 Docker 映像檔的服務帳戶:

    gcloud iam service-accounts create azure-pipelines-publisher \
        --display-name="Azure Pipelines Publisher"
    
  6. Storage 管理員身分與存取權管理角色 (roles/storage.admin) 授予服務帳戶,允許 Azure Pipelines 推送至 Container Registry:

    AZURE_PIPELINES_PUBLISHER=azure-pipelines-publisher@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
    
    gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
        --member serviceAccount:$AZURE_PIPELINES_PUBLISHER \
        --role roles/storage.admin
    
  7. 產生服務帳戶金鑰:

    gcloud iam service-accounts keys create azure-pipelines-publisher.json \
        --iam-account $AZURE_PIPELINES_PUBLISHER
    
    tr -d '\n' < azure-pipelines-publisher.json > azure-pipelines-publisher-oneline.json
    
  8. 查看服務帳戶金鑰檔案的內容:

    echo $(<azure-pipelines-publisher-oneline.json)
    

    您會在下列其中一個步驟中用到服務帳戶金鑰。

  9. 為 Google Container Registry 建立服務連線

    在 Azure Pipelines 中,為 Container Registry 建立新的服務連線:

    1. 在 Azure DevOps 選單中,選取「專案設定」,然後選取「管線」 >「服務連線」
    2. 按一下「建立服務連線」
    3. 從清單中選取「Docker Registry」,然後按一下「下一步」
    4. 在對話方塊中,在下列欄位輸入這些值:
      • 登記類型其他
      • Docker Registryhttps://gcr.io/PROJECT_ID,將 PROJECT_ID 替換為專案名稱 (例如 https://gcr.io/azure-pipelines-test-project-12345)。
      • 「Docker ID」_json_key
      • 密碼:貼上 azure-pipelines-publisher-oneline.json 的內容。
      • 服務連線名稱gcr-tutorial
    5. 按一下「儲存」建立連結。

    持續建構

    您現在可以使用 Azure Pipelines 設定持續整合。Azure Pipelines 會為每個推送至 Git 存放區的修訂版本建構程式碼,並將成果封裝至 Docker 容器中,接著將容器發布至 Container Registry。

    存放區已包含下列 Dockerfile:

    .NET/Linux

    #
    # Copyright 2020 Google LLC
    #
    # Licensed to the Apache Software Foundation (ASF) under one
    # or more contributor license agreements.  See the NOTICE file
    # distributed with this work for additional information
    # regarding copyright ownership.  The ASF licenses this file
    # to you under the Apache License, Version 2.0 (the
    # "License"); you may not use this file except in compliance
    # with the License.  You may obtain a copy of the License at
    # 
    #   http://www.apache.org/licenses/LICENSE-2.0
    # 
    # Unless required by applicable law or agreed to in writing,
    # software distributed under the License is distributed on an
    # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    # KIND, either express or implied.  See the License for the
    # specific language governing permissions and limitations
    # under the License.
    #
    
    FROM mcr.microsoft.com/dotnet/aspnet:6.0
    EXPOSE 8080
    
    #------------------------------------------------------------------------------
    # Copy publishing artifacts.
    #------------------------------------------------------------------------------
    
    WORKDIR /app
    COPY CloudDemo.MvcCore/bin/Release/net6.0/publish/ /app/
    
    ENV ASPNETCORE_URLS=http://0.0.0.0:8080
    
    #------------------------------------------------------------------------------
    # Run application in Kestrel.
    #------------------------------------------------------------------------------
    
    ENTRYPOINT ["dotnet", "CloudDemo.MvcCore.dll"]

    .NET Framework/Windows

    #
    # Copyright 2020 Google LLC
    #
    # Licensed to the Apache Software Foundation (ASF) under one
    # or more contributor license agreements.  See the NOTICE file
    # distributed with this work for additional information
    # regarding copyright ownership.  The ASF licenses this file
    # to you under the Apache License, Version 2.0 (the
    # "License"); you may not use this file except in compliance
    # with the License.  You may obtain a copy of the License at
    # 
    #   http://www.apache.org/licenses/LICENSE-2.0
    # 
    # Unless required by applicable law or agreed to in writing,
    # software distributed under the License is distributed on an
    # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    # KIND, either express or implied.  See the License for the
    # specific language governing permissions and limitations
    # under the License.
    #
    
    FROM mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
    EXPOSE 80
    SHELL ["powershell", "-command"]
    
    #------------------------------------------------------------------------------
    # Add LogMonitor so that IIS and Windows logs are emitted to STDOUT and can be 
    # picked up by Docker/Kubernetes.
    #
    # See https://github.com/microsoft/windows-container-tools/wiki/Authoring-a-Config-File
    # for details.
    #------------------------------------------------------------------------------
    
    ADD https://github.com/microsoft/windows-container-tools/releases/download/v1.1/LogMonitor.exe LogMonitor/
    ADD LogMonitorConfig.json LogMonitor/
    
    #------------------------------------------------------------------------------
    # Copy publishing artifacts to webroot.
    #------------------------------------------------------------------------------
    
    ADD CloudDemo.Mvc/bin/Release/PublishOutput/ c:/inetpub/wwwroot/
    
    #------------------------------------------------------------------------------
    # Configure IIS using the helper functions from deployment.ps1.
    #------------------------------------------------------------------------------
    
    ADD deployment.ps1 /
    RUN . /deployment.ps1; \
    	Install-Iis; \
    	Register-WebApplication -AppName "CloudDemo"; \
    	Remove-Item /deployment.ps1
    
    #------------------------------------------------------------------------------
    # Run IIS, wrapped by LogMonitor.
    #------------------------------------------------------------------------------
    
    ENTRYPOINT ["C:\\LogMonitor\\LogMonitor.exe", "C:\\ServiceMonitor.exe", "w3svc"]

    現在請建立使用 YAML 語法的新管道:

    1. 使用 Visual Studio 或指令列 git 用戶端,複製新的 Git 存放區,並查看 main 分支。
    2. 在存放區的根目錄中,建立名為 azure-pipelines.yml 的檔案。
    3. 將下列程式碼複製到檔案中:

      .NET/Linux

      resources:
      - repo: self
        fetchDepth: 1
      pool:
        vmImage: ubuntu-20.04
      trigger:
      - main
      variables:
        TargetFramework: 'net6.0'
        BuildConfiguration: 'Release'
        DockerImageName: 'PROJECT_ID/clouddemo'
      steps:
      - task: DotNetCoreCLI@2
        displayName: Publish
        inputs:
          projects: 'applications/clouddemo/netcore/CloudDemo.MvcCore.sln'
          publishWebProjects: false
          command: publish
          arguments: '--configuration $(BuildConfiguration) --framework=$(TargetFramework)'
          zipAfterPublish: false
          modifyOutputPath: false
      - task: CmdLine@1
        displayName: 'Lock image version in deployment.yaml'
        inputs:
          filename: /bin/bash
          arguments: '-c "awk ''{gsub(\"CLOUDDEMO_IMAGE\", \"gcr.io/$(DockerImageName):$(Build.BuildId)\", $0); print}'' applications/clouddemo/netcore/deployment.yaml > $(build.artifactstagingdirectory)/deployment.yaml"'
      - task: PublishBuildArtifacts@1
        displayName: 'Publish Artifact'
        inputs:
          PathtoPublish: '$(build.artifactstagingdirectory)'
      - task: Docker@2
        displayName: 'Login to Container Registry'
        inputs:
          command: login
          containerRegistry: 'gcr-tutorial'
      - task: Docker@2
        displayName: 'Build and push image'
        inputs:
          Dockerfile: 'applications/clouddemo/netcore/Dockerfile'
          command: buildAndPush
          repository: '$(DockerImageName)'

      .NET Framework/Windows

      resources:
      - repo: self
        fetchDepth: 1
      pool:
        vmImage: windows-2019     # Matches WINDOWS_LTSC in GKE
        demands:
        - msbuild
        - visualstudio
      trigger:
      - master
      variables:
        Solution: 'applications/clouddemo/net4/CloudDemo.Mvc.sln'
        BuildPlatform: 'Any CPU'
        BuildConfiguration: 'Release'
        DockerImageName: 'PROJECT_ID/clouddemo'
      steps:
      - task: NuGetCommand@2
        displayName: 'NuGet restore'
        inputs:
          restoreSolution: '$(Solution)'
      - task: VSBuild@1
        displayName: 'Build solution'
        inputs:
          solution: '$(Solution)'
          msbuildArgs: '/p:DeployOnBuild=true /p:PublishProfile=FolderProfile'
          platform: '$(BuildPlatform)'
          configuration: '$(BuildConfiguration)'
      - task: PowerShell@2
        displayName: 'Lock image version in deployment.yaml'
        inputs:
          targetType: 'inline'
          script: '(Get-Content applications\clouddemo\net4\deployment.yaml) -replace "CLOUDDEMO_IMAGE","gcr.io/$(DockerImageName):$(Build.BuildId)" | Out-File -Encoding ASCII $(build.artifactstagingdirectory)\deployment.yaml'
      - task: PublishBuildArtifacts@1
        displayName: 'Publish Artifact'
        inputs:
          PathtoPublish: '$(build.artifactstagingdirectory)'
      - task: Docker@2
        displayName: 'Login to Container Registry'
        inputs:
          command: login
          containerRegistry: 'gcr-tutorial'
      - task: Docker@2
        displayName: 'Build and push image'
        inputs:
          Dockerfile: 'applications/clouddemo/net4/Dockerfile'
          command: buildAndPush
          repository: '$(DockerImageName)'

      PROJECT_ID 替換成專案名稱,然後儲存檔案。

    4. 修訂變更並推送到 Azure Pipelines。

      Visual Studio

      1. 開啟 Team Explorer,然後按一下「首頁」圖示。
      2. 按一下 [Changes] (變更)
      3. 輸入修訂訊息,例如 Add pipeline definition
      4. 按一下 [Commit All and Push] (全部認可並推送)

      指令列

      1. 暫存所有已修改的檔案:

        git add -A
        
      2. 修訂本機存放區的變更:

        git commit -m "Add pipeline definition"
        
      3. 將變更推送至 Azure DevOps:

        git push
        
    5. 在 Azure DevOps 選單中選取「Pipelines」,然後按一下「Create Pipeline」

    6. 選取「Azure Repos Git」

    7. 選取存放區。

    8. 在「Review your pipeline YAML」(檢查管道 YAML) 頁面中,按一下「Run」(執行)

      系統會觸發新的建構作業。建構作業約需 6 分鐘才能完成。

    9. 如要確認映像檔是否已發布至 Container Registry,請在 Google Cloud 控制台中切換至您的專案,選取「Container Registry」 >「映像檔」,然後按一下「clouddemo」

      畫面上會顯示單一圖片和該圖片的標記。這個標記與在 Azure Pipelines 中執行的建構的數字 ID 相同。

    持續部署

    Azure Pipelines 已可自動建構程式碼並為每個修訂版本發佈 Docker 映像檔。因此,您現在可以專注在部署上。

    Azure Pipelines 與其他持續整合系統不同,會區分建構與部署,並提供一套名為「Release Management」的特殊工具,供所有部署相關工作使用。

    Azure Pipelines Release Management 是根據下列概念建構而成:

    • 「版本」是指一組構件,這些構件組成了應用程式的特定版本,且通常是建構過程的結果。
    • 「部署」是指建立版本,並將它部署至特定環境中的過程。
    • 部署會執行一組「任務」,您可將這組任務組成工作。
    • 「階段」可讓您為管道分段,以用來自動化調度管理部署作業到多個環境,例如部署與測試環境。

    CloudDemo 建構程序產生的主要成果為 Docker 映像檔。但由於 Docker 映像檔是發布至 Container Registry,因此映像檔會位於 Azure Pipelines 的範圍外。而無法有效地做為版本的定義。

    如要部署至 Kubernetes,您也需要一份「資訊清單」,這與物料清單類似。資訊清單不僅定義 Kubernetes 應建立及管理的資源,也指定了要使用的 Docker 映像檔確切版本。Kubernetes 資訊清單非常適合做為定義 Azure Pipelines Release Management 中的版本的成果。

    設定 Kubernetes 部署

    如要在 Kubernetes 中執行 CloudDemo,您需要下列資源:

    • 一個「部署」,定義一個執行 Docker 映像檔的 Pod。這個 Docker 映像檔是由建構所產生。
    • 一個「NodePort」服務,讓負載平衡器能夠存取 Pod。
    • 一個「輸入」,使用 Cloud HTTP(S) 負載平衡器將應用程式公開發布至網際網路。

    存放區已包含下列 Kubernetes 資訊清單,用於定義這些資源:

    .NET/Linux

    #
    # Copyright 2020 Google LLC
    #
    # Licensed to the Apache Software Foundation (ASF) under one
    # or more contributor license agreements.  See the NOTICE file
    # distributed with this work for additional information
    # regarding copyright ownership.  The ASF licenses this file
    # to you under the Apache License, Version 2.0 (the
    # "License"); you may not use this file except in compliance
    # with the License.  You may obtain a copy of the License at
    # 
    #   http://www.apache.org/licenses/LICENSE-2.0
    # 
    # Unless required by applicable law or agreed to in writing,
    # software distributed under the License is distributed on an
    # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    # KIND, either express or implied.  See the License for the
    # specific language governing permissions and limitations
    # under the License.
    #
    
    apiVersion: v1
    kind: Service
    metadata:
      name: clouddemo-netcore
    spec:
      ports:
      - port: 80
        targetPort: 8080
        protocol: TCP
        name: http
      selector:
        app: clouddemo-netcore
      type: NodePort
    
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: clouddemo-netcore
    spec:
      defaultBackend:
        service:
          name: clouddemo-netcore
          port:
            number: 80
    
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: clouddemo-netcore
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: clouddemo-netcore
      template:
        metadata:
          labels:
            app: clouddemo-netcore
        spec:
          containers:
          - name: clouddemo-netcore
            image: CLOUDDEMO_IMAGE
            ports:
              - containerPort: 8080
            livenessProbe:      # Used by deployment controller
              httpGet:
                path: /health
                port: 8080
              initialDelaySeconds: 5
              periodSeconds: 5
            readinessProbe:     # Used by Ingress/GCLB
              httpGet:
                path: /health
                port: 8080
              initialDelaySeconds: 3
              periodSeconds: 5
            resources:
              limits:
                memory: 1024Mi
              requests:
                memory: 256Mi

    .NET Framework/Windows

    #
    # Copyright 2020 Google LLC
    #
    # Licensed to the Apache Software Foundation (ASF) under one
    # or more contributor license agreements.  See the NOTICE file
    # distributed with this work for additional information
    # regarding copyright ownership.  The ASF licenses this file
    # to you under the Apache License, Version 2.0 (the
    # "License"); you may not use this file except in compliance
    # with the License.  You may obtain a copy of the License at
    # 
    #   http://www.apache.org/licenses/LICENSE-2.0
    # 
    # Unless required by applicable law or agreed to in writing,
    # software distributed under the License is distributed on an
    # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    # KIND, either express or implied.  See the License for the
    # specific language governing permissions and limitations
    # under the License.
    #
    
    apiVersion: v1
    kind: Service
    metadata:
      name: clouddemo-net4
      annotations:
        cloud.google.com/neg: '{"ingress": false}' # Disable NEG
    
    spec:
      ports:
      - port: 80
        targetPort: 80
        protocol: TCP
        name: http
      selector:
        app: clouddemo-net4
      type: NodePort
    
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: clouddemo-net4
    spec:
      defaultBackend:
        service:
          name: clouddemo-net4
          port:
            number: 80
    
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: clouddemo-net4
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: clouddemo-net4
      template:
        metadata:
          labels:
            app: clouddemo-net4
        spec:
          nodeSelector:
            kubernetes.io/os: windows
          containers:
          - name: clouddemo-net4
            image: CLOUDDEMO_IMAGE
            ports:
              - containerPort: 80
            livenessProbe:      # Used by deployment controller
              httpGet:
                path: /health
                port: 80
              initialDelaySeconds: 120
              periodSeconds: 5
            readinessProbe:     # Used by Ingress/GCLB
              httpGet:
                path: /health
                port: 80
              initialDelaySeconds: 10
              periodSeconds: 5
            resources:
              limits:
                memory: 1024Mi
              requests:
                memory: 256Mi

    設定開發環境和實際工作環境

    返回 Azure Pipelines Release Management 之前,您必須建立 GKE 叢集。

    建立 GKE 叢集

    1. 返回 Cloud Shell 執行個體。

    2. 為您的專案啟用 GKE API:

      gcloud services enable container.googleapis.com
    3. 使用下列指令建立開發叢集。請注意,這項作業可能需要幾分鐘的時間才能完成:

      .NET/Linux

      gcloud container clusters create azure-pipelines-cicd-dev --enable-ip-alias
      

      .NET Framework/Windows

      gcloud container clusters create azure-pipelines-cicd-dev --enable-ip-alias
      
      gcloud container node-pools create azure-pipelines-cicd-dev-win \
          --cluster=azure-pipelines-cicd-dev \
          --image-type=WINDOWS_LTSC \
          --no-enable-autoupgrade \
          --machine-type=n1-standard-2
      
    4. 使用下列指令建立實際工作環境叢集。請注意,這項作業可能需要幾分鐘的時間才能完成:

      .NET/Linux

      gcloud container clusters create azure-pipelines-cicd-prod --enable-ip-alias
      

      .NET Framework/Windows

      gcloud container clusters create azure-pipelines-cicd-prod --enable-ip-alias
      
      gcloud container node-pools create azure-pipelines-cicd-prod-win \
          --cluster=azure-pipelines-cicd-prod \
          --image-type=WINDOWS_LTSC \
          --no-enable-autoupgrade \
          --machine-type=n1-standard-2
      

    將 Azure Pipelines 連結至開發叢集

    正如同您可以使用 Azure Pipelines 連結至外部 Docker 註冊資料庫 (如 Container Registry) 一樣,Azure Pipelines 也支援整合外部 Kubernetes 叢集。

    您可以使用Google Cloud 服務帳戶向 Container Registry 取得驗證,但 Azure Pipelines 不支援使用 Google Cloud 服務帳戶以 GKE 進行驗證。您必須改用 Kubernetes 服務帳戶

    因此,如要將 Azure Pipelines 連結至開發叢集,您必須先建立 Kubernetes 服務帳戶。

    1. 在 Cloud Shell 中,連結至開發叢集:

      gcloud container clusters get-credentials azure-pipelines-cicd-dev
    2. 為 Azure Pipelines 建立 Kubernetes 服務帳戶:

      kubectl create serviceaccount azure-pipelines-deploy
    3. 建立 Kubernetes 密鑰,內含 Azure Pipelines 的權杖憑證:

      kubectl create secret generic azure-pipelines-deploy-token --type=kubernetes.io/service-account-token --dry-run -o yaml \
        | kubectl annotate --local -o yaml -f - kubernetes.io/service-account.name=azure-pipelines-deploy \
        | kubectl apply -f -
      
    4. 建立叢集角色繫結,將 cluster-admin 角色指派給服務帳戶:

      kubectl create clusterrolebinding azure-pipelines-deploy --clusterrole=cluster-admin --serviceaccount=default:azure-pipelines-deploy
    5. 判定叢集的 IP 位址:

      gcloud container clusters describe azure-pipelines-cicd-dev --format=value\(endpoint\)
      

      您稍後將會用到這個位址。

    6. 在 Azure DevOps 選單中,選取 [Project settings],然後選取 [Pipelines] > [Service connections]

    7. 按一下 [New service connection]

    8. 選取「Kubernetes」,然後按一下「下一步」

    9. 進行下列設定:

      • 「Authentication method」(驗證方式):選取「Service account」(服務帳戶)
      • 伺服器網址https://PRIMARY_IP。 將 PRIMARY_IP 換成您之前判定的 IP 位址。
      • 密鑰:您先前建立的 Kubernetes 密鑰。如要取得密鑰,請執行下列指令、複製密鑰,然後將密鑰複製到 Azure 頁面。
        kubectl get secret azure-pipelines-deploy-token -o yaml
      • 服務連線名稱azure-pipelines-cicd-dev
    10. 按一下 [儲存]

    將 Azure Pipelines 連結至實際工作環境叢集

    如要將 Azure Pipelines 連結至實際工作環境叢集,您可以按照相同的方法操作。

    1. 在 Cloud Shell 中,連結至實際工作環境叢集。

      gcloud container clusters get-credentials azure-pipelines-cicd-prod
    2. 為 Azure Pipelines 建立 Kubernetes 服務帳戶:

      kubectl create serviceaccount azure-pipelines-deploy
    3. 建立叢集角色繫結,將 cluster-admin 角色指派給服務帳戶:

      kubectl create clusterrolebinding azure-pipelines-deploy --clusterrole=cluster-admin --serviceaccount=default:azure-pipelines-deploy
    4. 判定叢集的 IP 位址:

      gcloud container clusters describe azure-pipelines-cicd-prod --format=value\(endpoint\)
      

      您稍後將會用到這個位址。

    5. 在 Azure DevOps 選單中,選取 [Project settings],然後選取 [Pipelines] > [Service connections]

    6. 按一下 [New service connection]

    7. 選取「Kubernetes」,然後按一下「下一步」

    8. 進行下列設定:

      • 「Authentication method」(驗證方式):選取「Service account」(服務帳戶)
      • 伺服器網址https://PRIMARY_IP。 將 PRIMARY_IP 換成您之前判定的 IP 位址。
      • 「Secret」:在 Cloud Shell 中執行下列指令,並複製輸出結果:
        kubectl get secret $(kubectl get serviceaccounts azure-pipelines-deploy -o custom-columns=":secrets[0].name") -o yaml
      • 服務連線名稱azure-pipelines-cicd-prod
    9. 按一下 [儲存]

    設定發布管道

    設定 GKE 基礎架構之後,您將返回 Azure Pipelines 以自動化部署作業,這包含了:

    • 部署至開發環境。
    • 要求通過手動核准後,才啟動部署到實際工作環境。
    • 部署至實際工作環境。

    建立發布定義

    第一步是建立新的發行定義。

    1. 在 Azure DevOps 選單中,選取 [Pipelines] > [Releases]
    2. 按一下 [New pipeline]
    3. 從範本清單中選取 [Empty job]
    4. 當系統提示您輸入階段名稱時,請輸入 Development
    5. 在畫面頂端,將發布命名為 CloudDemo-KubernetesEngine
    6. 在管道圖的 [Artifacts] 旁,按一下 [Add]
    7. 選取 [Build],並新增下列設定:

      • 來源類型建構
      • 「Source (build pipeline)」:選取建構定義 (應該只有一個選項)
      • 預設版本Latest
      • 「Source Alias」manifest
    8. 按一下「新增」。

    9. 按一下「Artifact」方塊中的「Continuous deployment trigger」(持續部署觸發程序) (閃電圖示),新增部署觸發條件。

    10. 在「Continuous deployment trigger」(持續部署觸發程序) 底下,將切換按鈕設定為 [Enabled] (已啟用)

    11. 按一下 [儲存]

    12. 視需要輸入註解,然後按一下 [OK] 確認。

      管道會顯示類似下列內容。

      Azure Pipelines 中更新管道的螢幕擷取畫面

    部署至開發叢集

    建立發行定義之後,您現在可以將部署設定至 GKE 開發叢集。

    1. 在選單中,切換至「Tasks」分頁標籤。
    2. 按一下「Agent job」(代理程式工作),然後設定下列項目:

      • 代理程式集區Azure Pipelines
      • 代理程式規格ubuntu-18.04
    3. 在「Agent job」旁,按一下「Add a task to agent job」 ,即可在階段中新增步驟。

    4. 選取 [Deploy to Kuberetes] 工作,然後按一下 [Add]

    5. 按一下新增的工作,然後進行下列設定:

      • 顯示名稱Deploy
      • 動作deploy
      • 「Kubernetes service connection」:[azure-pipelines-cicd-dev]
      • 命名空間default
      • 策略
      • 資訊清單manifest/drop/deployment.yaml
    6. 按一下 [儲存]

    7. 視需要輸入註解,然後按一下 [OK] 確認。

    部署至正式環境叢集

    最後,將部署設定至 GKE 實際工作環境叢集。

    1. 在選單中,切換至「Pipeline」分頁標籤。
    2. 在「Stages」方塊中,選取「Add」 >「New stage」
    3. 從範本清單中選取 [Empty job]
    4. 當系統提示您輸入階段名稱時,請輸入 Production
    5. 按一下新建立階段的閃電圖示。
    6. 進行下列設定:

      • 選取觸發條件After stage
      • 階段Dev
      • 「Pre-deployment approvals」(部署前核准):(啟用)
      • 「Approvers」(核准者):選取您自己的使用者名稱。

      管道現在看起來會像這樣:

      Azure Pipelines 中更新管道的螢幕擷取畫面

    7. 切換至「Tasks」分頁標籤。

    8. 將滑鼠停在「Tasks」分頁上方,然後選取「Tasks」 >「Production」

    9. 按一下「Agent job」(代理程式工作),然後設定下列項目:

      • 代理程式集區Azure Pipelines
      • 代理程式規格ubuntu-18.04
    10. 按一下「Add a task to agent job」(將工作新增至代理程式工作) ,即可在階段中新增步驟。

    11. 選取 [Deploy to Kuberetes] 工作,然後按一下 [Add]

    12. 按一下新增的工作,然後進行下列設定:

      • 顯示名稱Deploy
      • 動作deploy
      • 「Kubernetes service connection」:[azure-pipelines-cicd-prod]
      • 命名空間default
      • 策略
      • 資訊清單manifest/drop/deployment.yaml
    13. 按一下 [儲存]

    14. 視需要輸入註解,然後按一下 [OK] 確認。

    執行管道

    您已經設定了整個管道,現在可以開始執行原始碼變更來進行測試:

    1. 在您的本機電腦上,開啟先前複製的 Git 存放區中的 Index.cshtml 檔案:

      .NET/Linux

      這個檔案位於 applications\clouddemo\netcore\CloudDemo.MvcCore\Views\Home\

      .NET Framework/Windows

      這個檔案位於 applications\clouddemo\net4\CloudDemo.Mvc\Views\Home\

    2. 在第 26 行中,將 ViewBag.Title 的值從 Home Page 變更為 This app runs on GKE

    3. 確認變更,然後將其推送到 Azure Pipelines。

      Visual Studio

      1. 開啟 Team Explorer,然後按一下「首頁」圖示。
      2. 按一下 [Changes] (變更)
      3. 輸入修訂訊息,例如 Change site title
      4. 按一下 [Commit All and Push] (全部認可並推送)

      指令列

      1. 暫存所有已修改的檔案:

        git add -A
        
      2. 修訂本機存放區的變更:

        git commit -m "Change site title"
        
      3. 將變更推送至 Azure Pipelines:

        git push
        
    4. 在 Azure DevOps 選單中,選取「Pipelines」。系統會觸發建構作業。

    5. 建構完成後,請選取「Pipelines」 >「Releases」。啟動發布程序。

    6. 按一下「Release-1」開啟詳細資料頁面,並等候「Development」階段的狀態切換為「Succeeded」

    7. 在 Google Cloud 控制台中,依序選取「Kubernetes Engine」>「服務與 Ingress」>「Ingress」

    8. 找到 azure-pipelines-cicd-dev 叢集的輸入服務,然後等待其狀態變成「Ok」。這可能需要幾分鐘的時間。

    9. 開啟同一列「前端」欄中的連結。您一開始可能會看到錯誤,因為負載平衡器需要幾分鐘的時間才能變為可用。準備就緒後,您會發現 CloudDemo 已部署完成,並使用自訂名稱。

    10. 在 Azure Pipelines 的「Prod」階段中,按一下 [Approve] 將部署推送至實際工作環境。

      如果畫面上沒有按鈕,您可能需要先核准或拒絕先前的發行版本。

    11. 視需要輸入註解,然後按一下 [Approve] 確認。

    12. 等候「Prod」環境的狀態變成「Succeeded」。您可能需要在瀏覽器中手動重新整理頁面。

    13. 在 Google Cloud 控制台中,重新整理「Services & Ingress」(服務與輸入) 頁面。

    14. 找到 azure-pipelines-cicd-prod 叢集的輸入服務,然後等待其狀態變成「Ok」。這可能需要幾分鐘的時間。

    15. 開啟同一列「前端」欄中的連結。同樣地,您一開始可能會看到錯誤,因為負載平衡器需要過幾分鐘才能使用。準備就緒後,您會再次看到 CloudDemo 應用程式及自訂名稱,這次應用程式是在實際工作環境叢集中執行。

清除所用資源

如要避免在完成本教學課程後繼續產生費用,請刪除您建立的實體。

刪除 Azure Pipelines 專案

如要刪除 Azure Pipelines 專案,請參閱 Azure DevOps Services 文件。刪除 Azure Pipelines 專案會導致所有原始碼變更遺失。

刪除 Google Cloud 開發項目和專案

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

後續步驟