Azure Pipelines 및 Google Kubernetes Engine으로 CI/CD 파이프라인 만들기

Last reviewed 2022-11-29 UTC

이 튜토리얼에서는 Azure Pipelines, Google Kubernetes Engine(GKE), Google Container Registry를 사용하여 ASP.NET MVC 웹 애플리케이션을 위해 지속적 통합/지속적 배포(CI/CD) 파이프라인을 만드는 방법을 설명합니다. 이 튜토리얼에서는 두 가지 예시 애플리케이션 중에서 선택할 수 있습니다.

  • .NET 6 .0을 사용하고 Linux에서 실행되는 ASP.NET Core 웹 애플리케이션
  • .NET Framework 4를 사용하고 Windows에서 실행되는 ASP.NET MVC 웹 애플리케이션

CI/CD 파이프라인은 다음 다이어그램과 같이 두 개의 개별 GKE 클러스터(개발용 및 프로덕션용)를 사용합니다.

개발자 및 최종 사용자가 애플리케이션과 상호작용하는 방법을 보여주는 CI/CD 파이프라인의 개념 다이어그램

파이프라인 시작 부분에서 개발자는 예시 코드베이스에 대한 변경사항을 커밋합니다. 이 작업은 파이프라인을 트리거하여 릴리스를 만들고 개발 클러스터에 배포합니다. 그러면 출시 관리자는 프로덕션 클러스터에 배포되도록 출시를 승격할 수 있습니다.

이 튜토리얼은 개발자 및 DevOps 엔지니어를 대상으로 하며, 여기에서는 Microsoft .NET, Azure Pipelines, GKE에 대한 기본 지식이 있다고 가정합니다. 또한 이 튜토리얼을 진행하려면 Azure DevOps 계정에 대한 관리 액세스 권한이 있어야 합니다.

목표

  • Docker 이미지 게시를 위해 Google Container Registry를 Azure Pipelines에 연결합니다.
  • GKE에 배포할 .NET 샘플 앱을 준비합니다.
  • 이전 인증을 사용하지 않고도 GKE에 대해 안전하게 인증합니다.
  • Azure Pipelines 릴리스 관리를 사용하여 GKE 배포를 조정합니다.

비용

이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.

이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

Azure DevOps 사용 시 부과될 수 있는 요금은 Azure DevOps 가격 책정 페이지를 참조하세요.

시작하기 전에

일반적으로 Identity and Access Management(IAM) 역할 및 권한을 개별적으로 부여할 수 있도록 개발 및 프로덕션 워크로드에 별도의 프로젝트를 사용하는 것이 좋습니다. 이 튜토리얼에서는 편의상 2가지 GKE 클러스터(개발용 및 프로덕션용)에 대해 단일 프로젝트를 사용합니다.

  1. Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

  2. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  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. 새 프로젝트를 클릭합니다.
  3. 프로젝트 이름을 입력합니다(예: CloudDemo).
  4. 표시 유형비공개로 설정하고 만들기를 클릭합니다.
  5. 프로젝트를 만든 후 왼쪽 메뉴에서 저장소를 클릭합니다.
  6. 가져오기를 클릭하여 GitHub에서 dotnet-docs-samples 저장소를 포크한 후 다음 값을 설정합니다.
    • 저장소 유형: Git
    • 클론 URL: https://github.com/GoogleCloudPlatform/dotnet-docs-samples.git
  7. 가져오기를 클릭합니다.

    가져오기 프로세스가 완료되면 dotnet-docs-samples 저장소의 소스 코드가 표시됩니다.

Container Registry에 Azure Pipelines 연결

CloudDemo 앱에 대해 지속적 통합을 설정하려면 먼저 Azure Pipelines를 Container Registry에 연결해야 합니다. 이 연결을 통해 Azure Pipelines가 컨테이너 이미지를 Container Registry에 게시할 수 있습니다.

이미지 게시를 위한 서비스 계정 설정

프로젝트에서 Google Cloud 서비스 계정을 만듭니다.

  1. Google Cloud 콘솔을 엽니다.

  2. Google Cloud 콘솔에서 Cloud Shell을 활성화합니다.

    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. 서비스 계정에 스토리지 관리자 IAM 역할(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)
    

    다음 단계 중 하나에서 서비스 계정 키가 필요합니다.

Google Container Registry에 대해 서비스 연결 만들기

Azure Pipelines에서 Container Registry에 대해 새 서비스 연결을 만듭니다.

  1. Azure DevOps 메뉴에서 프로젝트 설정를 선택한 다음 파이프라인 > 서비스 연결을 선택합니다.
  2. 서비스 연결 만들기를 클릭합니다.
  3. 목록에서 Docker 레지스트리를 선택하고 다음을 클릭합니다.
  4. 대화상자에서 다음 필드의 값을 입력합니다.
    • 레지스트리 유형: 기타
    • Docker 레지스트리: https://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. 팀 탐색기를 열고 아이콘을 클릭합니다.
    2. Changes(변경사항)를 클릭합니다.
    3. Add pipeline definition과 같은 커밋 메시지를 입력합니다.
    4. 모두 커밋 후 푸시를 클릭합니다.

    명령줄

    1. 수정된 모든 파일을 스테이징합니다.

      git add -A
      
    2. 로컬 저장소에 대한 변경사항을 커밋합니다.

      git commit -m "Add pipeline definition"
      
    3. Azure DevOps에 변경사항을 푸시합니다.

      git push
      
  5. Azure DevOps 메뉴에서 파이프라인를 선택한 후 파이프라인 만들기를 클릭합니다.

  6. Azure 저장소 Git를 선택합니다.

  7. 저장소를 선택합니다.

  8. 파이프라인 YAML 검토 페이지에서 실행을 클릭합니다.

    새 빌드가 트리거됩니다. 빌드가 완료되려면 6분 정도 걸릴 수 있습니다.

  9. 이미지가 Container Registry에 게시되었는지 확인하려면 Google Cloud 콘솔에서 프로젝트로 전환하고 Container Registry > 이미지를 선택한 후 clouddemo를 클릭합니다.

    단일 이미지와 이 이미지의 태그가 표시됩니다. 이 태그는 Azure Pipelines에서 실행된 빌드의 숫자 ID에 해당합니다.

지속적으로 배포

이제 커밋할 때마다 Azure Pipelines가 자동으로 코드를 빌드하고 Docker 이미지를 게시하므로 개발자는 배포 작업에만 집중할 수 있습니다.

다른 지속적 통합 시스템과 달리 Azure Pipelines는 빌드와 배포를 구분하며, 배포와 관련된 모든 태스크에 출시 관리라는 특수 도구 세트를 제공합니다.

Azure Pipelines 출시 관리는 다음과 같은 개념을 바탕으로 합니다.

  • 출시는 앱의 특정 버전을 구성하고 일반적으로 빌드 프로세스의 결과인 아티팩트 집합을 의미합니다.
  • 배포는 출시를 가져와서 특정 환경에 배포하는 프로세스를 의미합니다.
  • 배포는 일련의 태스크을 수행하며 작업별로 그룹화할 수 있습니다.
  • 단계를 사용하여 파이프라인을 세분화하고 개발 및 테스트 환경과 같은 여러 환경으로의 배포를 조정할 수 있습니다.

CloudDemo 빌드 프로세스가 생성하는 기본 아티팩트는 Docker 이미지입니다. 그러나 Docker 이미지는 Container Registry에 게시되므로 Azure Pipelines의 범위를 벗어납니다. 따라서 이미지는 릴리스의 정의에 딱 부합하지는 않습니다.

Kubernetes에 배포하려면 일종의 명세서와 비슷한 역할을 하는 매니페스트도 필요합니다. 매니페스트는 Kubernetes가 만들고 관리해야 하는 리소스를 정의할 뿐 아니라 사용할 Docker 이미지의 정확한 버전도 지정합니다. Kubernetes 매니페스트는 Azure Pipelines 출시 관리에서 출시를 정의하는 아티팩트 역할을 하기에 적합합니다.

Kubernetes 배포 구성

Kubernetes에서 CloudDemo를 실행하려면 다음과 같은 리소스가 필요합니다.

  • 빌드에서 생성된 Docker 이미지를 실행하는 단일 포드를 정의하는 배포
  • 부하 분산기가 포드에 액세스할 수 있게 해 주는 NodePort 서비스
  • 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 출시 관리로 돌아가기 전에 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를 사용하여 Container Registry와 같은 외부 Docker 레지스트리에 연결할 수 있는 것처럼, 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. Azure Pipelines의 토큰 사용자 인증 정보가 포함된 Kubernetes 보안 비밀을 만듭니다.

    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를 선택하고 Next(다음)를 클릭합니다.

  9. 다음 설정을 구성합니다.

    • 인증 방법: 서비스 계정
    • 서버 URL: https://PRIMARY_IP. PRIMARY_IP를 이전에 결정한 IP 주소로 바꿉니다.
    • 보안 비밀: 이전에 만든 Kubernetes 보안 비밀입니다. 보안 비밀을 가져오려면 다음 명령어를 실행하고, 보안 비밀을 복사한 후 보안 비밀을 Azure 페이지에 복사합니다.
      kubectl get secret azure-pipelines-deploy-token -o yaml
    • 서비스 연결 이름: azure-pipelines-cicd-dev
  10. Save(저장)를 클릭합니다.

프로덕션 클러스터에 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를 선택하고 Next(다음)를 클릭합니다.

  8. 다음 설정을 구성합니다.

    • 인증 방법: 서비스 계정
    • 서버 URL: https://PRIMARY_IP. PRIMARY_IP를 이전에 결정한 IP 주소로 바꿉니다.
    • 보안 비밀: Cloud Shell에서 다음 명령어를 실행하고 출력을 복사합니다.
      kubectl get secret $(kubectl get serviceaccounts azure-pipelines-deploy -o custom-columns=":secrets[0].name") -o yaml
    • 서비스 연결 이름: azure-pipelines-cicd-prod
  9. Save(저장)를 클릭합니다.

출시 파이프라인 구성

GKE 인프라를 설정한 후에는 Azure Pipelines로 돌아가서 다음을 비롯한 개발을 자동화합니다.

  • 개발 환경에 배포
  • 프로덕션 환경에 배포를 시작하기 전에 수동 승인 요청
  • 프로덕션 환경에 배포

출시 정의 만들기

첫 번째 단계로 새 출시 정의를 만듭니다.

  1. Azure DevOps 메뉴에서 Pipelines(파이프라인) > Releases(릴리스)를 선택합니다.
  2. 새 파이프라인을 클릭합니다.
  3. 템플릿 목록에서 빈 작업을 선택합니다.
  4. 스테이지 이름을 입력하라는 메시지가 표시되면 Development를 입력합니다.
  5. 화면 상단에서 릴리스 이름을 CloudDemo-KubernetesEngine으로 지정합니다.
  6. 파이프라인 다이어그램의 아티팩트 옆에서 추가를 클릭합니다.
  7. Build(빌드)를 선택하고 다음 설정을 추가합니다.

    • Source type(소스 유형): Build(빌드)
    • Source(build pipeline)(소스(빌드 파이프라인)): 빌드 정의를 선택합니다. 옵션이 하나뿐이어야 합니다.
    • Default version(기본 버전): Latest
    • Source alias(소스 별칭): manifest
  8. 추가를 클릭합니다.

  9. Artifact(아티팩트) 상자에서 Continuous deployment trigger(지속적 배포 트리거)(번개 아이콘)를 클릭하여 배포 트리거를 추가합니다.

  10. Continuous deployment trigger(지속적 배포 트리거)에서 스위치를 Enabled(사용 설정됨)로 설정합니다.

  11. Save(저장)를 클릭합니다.

  12. 원하는 경우 설명을 입력한 다음 확인을 클릭하여 확인합니다.

    파이프라인은 다음과 비슷하게 표시됩니다.

    Azure Pipelines의 업데이트된 파이프라인 스크린샷

개발 클러스터에 배포

출시 정의가 생성되면 이제 GKE 개발 클러스터에 대한 배포를 구성할 수 있습니다.

  1. 메뉴에서 Tasks(태스크) 탭으로 전환합니다.
  2. Agent job(에이전트 작업)을 클릭하고 다음 설정을 구성합니다.

    • Agent pool(에이전트 풀): Azure Pipelines
    • Agent specification(에이전트 사양): ubuntu-18.04
  3. Agent job(에이전트 작업) 옆의 Add a task to agent job(에이전트 작업에 태스크 추가) 을 클릭하여 단계(phase)에 단계를 추가합니다.

  4. Deploy to Kubernetes(Kubernetes에 배포) 태스크를 선택하고 Add(추가)를 클릭합니다.

  5. 새로 추가된 작업을 클릭하고 다음 설정을 구성합니다.

    • Display name(표시 이름): Deploy
    • Action(작업): deploy
    • Kubernetes service connection(Kubernetes 서비스 연결): azure-pipelines-cicd-dev
    • Namespace(네임스페이스): default
    • Strategy(전략): None(없음)
    • Manifests(매니페스트): manifest/drop/deployment.yaml
  6. Save(저장)를 클릭합니다.

  7. 원하는 경우 설명을 입력한 다음 확인을 클릭하여 확인합니다.

프로덕션 클러스터에 배포

마지막으로 GKE 프로덕션 클러스터에 대한 배포를 구성합니다.

  1. 메뉴에서 Pipeline(파이프라인) 탭으로 전환합니다.
  2. 스테이지 상자에서 Add(추가) > New stage(새 스테이지)를 선택합니다.
  3. 템플릿 목록에서 빈 작업을 선택합니다.
  4. 스테이지 이름을 입력하라는 메시지가 표시되면 Production를 입력합니다.
  5. 새로 만든 스테이지의 번개 아이콘을 클릭합니다.
  6. 다음 설정을 구성합니다.

    • Select trigger(트리거 선택): After stage
    • Stages(스테이지): Dev
    • Pre-deployment approvals(사전 배포 승인): (사용 설정됨)
    • Approvers(승인자): 자신의 사용자 이름 선택

    이제 파이프라인이 다음과 같이 표시됩니다.

    Azure Pipelines의 업데이트된 파이프라인 스크린샷

  7. Tasks(태스크) 탭으로 전환합니다.

  8. Tasks(태스크) 탭 위로 마우스 커서를 가져간 다음 Tasks(태스크) > Production(프로덕션)을 선택합니다.

  9. Agent job(에이전트 작업)을 클릭하고 다음 설정을 구성합니다.

    • Agent pool(에이전트 풀): Azure Pipelines
    • Agent specification(에이전트 사양): ubuntu-18.04
  10. Add a task to agent job(에이전트 작업에 태스크 추가) 을 클릭하여 단계(phase)에 단계를 추가합니다.

  11. Deploy to Kubernetes(Kubernetes에 배포) 태스크를 선택하고 Add(추가)를 클릭합니다.

  12. 새로 추가된 작업을 클릭하고 다음 설정을 구성합니다.

    • Display name(표시 이름): Deploy
    • Action(작업): deploy
    • Kubernetes service connection(Kubernetes 서비스 연결): azure-pipelines-cicd-prod
    • Namespace(네임스페이스): default
    • Strategy(전략): None(없음)
    • Manifests(매니페스트): manifest/drop/deployment.yaml
  13. Save(저장)를 클릭합니다.

  14. 원하는 경우 설명을 입력한 다음 확인을 클릭하여 확인합니다.

파이프라인 실행

이제 전체 파이프라인을 구성했으므로 소스 코드 변경을 수행하여 파이프라인을 테스트할 수 있습니다.

  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. 팀 탐색기를 열고 아이콘을 클릭합니다.
    2. Changes(변경사항)를 클릭합니다.
    3. Change site title과 같은 커밋 메시지를 입력합니다.
    4. 모두 커밋 후 푸시를 클릭합니다.

    명령줄

    1. 수정된 모든 파일을 스테이징합니다.

      git add -A
      
    2. 로컬 저장소에 대한 변경사항을 커밋합니다.

      git commit -m "Change site title"
      
    3. 변경사항을 Azure Pipelines로 푸시합니다.

      git push
      
  4. Azure DevOps 메뉴에서 파이프라인을 선택합니다. 빌드가 트리거됩니다.

  5. 빌드가 완료되면 Pipelines(파이프라인) > Releases(출시)를 선택합니다. 출시 프로세스가 시작됩니다.

  6. Release-1을 클릭하여 세부정보 페이지를 열고 Development(개발) 스테이지의 상태가 Succeeded(성공)로 전환될 때까지 기다립니다.

  7. Google Cloud 콘솔에서 Kubernetes Engine > 서비스 및 인그레스 > 인그레스를 선택합니다.

  8. azure-pipelines-cicd-dev 클러스터의 인그레스 서비스를 찾고 상태가 확인으로 전환될 때까지 기다립니다. 이 작업은 몇 분 정도 걸릴 수 있습니다.

  9. 같은 행의 프런트엔드 열에서 링크를 엽니다. 부하 분산기를 사용할 수 있게 될 때까지 몇 분이 걸리므로 처음에는 오류가 표시될 수 있습니다. 준비되면 CloudDemo가 배포되었고 커스텀 제목을 사용하고 있는지 확인합니다.

  10. Azure Pipelines에서 Prod(프로덕션) 단계 아래의 Approve(승인) 버튼을 클릭하여 배포를 프로덕션 환경으로 승격합니다.

    버튼이 보이지 않는 경우 먼저 이전 출시를 승인 또는 거부해야 할 수 있습니다.

  11. 원하는 경우 설명을 입력한 다음 Approve(승인)를 클릭하여 확인합니다.

  12. Prod(프로덕션) 환경의 상태가 Succeeded(성공)로 전환될 때까지 기다립니다. 브라우저에서 페이지를 직접 새로고침해야 할 수 있습니다.

  13. Google Cloud 콘솔에서 서비스 및 인그레스 페이지를 새로고침합니다.

  14. azure-pipelines-cicd-prod 클러스터의 인그레스 서비스를 찾고 상태가 확인으로 전환될 때까지 기다립니다. 이 작업은 몇 분 정도 걸릴 수 있습니다.

  15. 같은 행의 프런트엔드 열에서 링크를 엽니다. 부하 분산기를 사용할 수 있게 될 때까지 몇 분이 걸리므로 처음에는 오류가 표시될 수 있습니다. 준비가 되면 커스텀 제목이 있는 CloudDemo 앱이 다시 표시됩니다. 이번에는 프로덕션 클러스터에서 실행됩니다.

삭제

이 튜토리얼을 완료한 후에 추가 비용이 발생하지 않도록 하려면 만든 항목을 삭제하세요.

Azure Pipelines 프로젝트 삭제

Azure Pipelines 프로젝트를 삭제하려면 Azure DevOps 서비스 문서를 참조하세요. Azure Pipelines 프로젝트를 삭제하면 모든 소스 코드 변경사항도 손실됩니다.

Google Cloud 개발 및 프로젝트 삭제

  1. Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다.

    리소스 관리로 이동

  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.

다음 단계