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

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

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

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

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

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

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

목표

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

비용

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

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

이 가이드를 마치면 만든 리소스를 삭제하여 비용이 계속 청구되지 않게 할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

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

시작하기 전에

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

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

    프로젝트 선택기로 이동

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

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

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

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

  1. Azure DevOps 메뉴에서 Project settings(프로젝트 설정)를 선택한 다음 Pipelines(파이프라인) > Service connections(서비스 연결)를 선택합니다.
  2. Create service connection(서비스 연결 만들기)을 클릭합니다.
  3. 목록에서 Docker Registry(Docker 레지스트리)를 선택하고 Next(다음)를 클릭합니다.
  4. 대화상자에서 다음 필드의 값을 입력합니다.
    • Registry type(레지스트리 유형): Others(기타)
    • Docker Registry(Docker 레지스트리): https://gcr.io/PROJECT_ID. PROJECT_ID를 프로젝트 이름으로 바꿉니다(예: https://gcr.io/azure-pipelines-test-project-12345).
    • Docker ID: _json_key
    • Password(비밀번호): azure-pipelines-publisher-oneline.json의 콘텐츠를 붙여 넣습니다.
    • Service connection name(서비스 연결 이름): gcr-tutorial
  5. Save(저장)를 클릭하여 연결을 만듭니다.

지속적으로 빌드

이제 Azure Pipelines를 사용하여 지속적 통합을 설정할 수 있습니다. Azure Pipelines는 Git 저장소로 커밋이 푸시될 때마다 코드를 빌드하고 빌드 아티팩트를 Docker 컨테이너로 패키징합니다. 그러면 컨테이너가 Container Registry에 게시됩니다.

저장소에 이미 다음 Dockerfile이 포함됩니다.

.NET Core/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/core/aspnet:3.1
EXPOSE 8080

#------------------------------------------------------------------------------
# Copy publishing artifacts.
#------------------------------------------------------------------------------

WORKDIR /app
COPY CloudDemo.MvcCore/bin/Release/netcoreapp3.1/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 저장소를 클론합니다.
  2. 저장소 루트에서 azure-pipelines.yml이라는 파일을 만듭니다.
  3. 다음 코드를 파일에 복사합니다.

    .NET Core/Linux

    resources:
    - repo: self
      fetchDepth: 1
    pool:
      vmImage: ubuntu-16.04
    trigger:
    - master
    variables:
      TargetFramework: 'netcoreapp3.1'
      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. 팀 탐색기를 열고 Home(홈) 아이콘을 클릭합니다.
    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(Azure 저장소 Git)를 선택합니다.

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

  8. Review your pipeline YAML(파이프라인 YAML 검토) 페이지에서 Run(실행)을 클릭합니다.

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

  9. 이미지가 Container Registry에 게시되었는지 확인하려면 Cloud Console에서 프로젝트로 전환하고, 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 이미지를 실행하는 단일 pod를 정의하는 배포
  • 부하 분산기가 pod에 액세스할 수 있게 해 주는 NodePort 서비스
  • Cloud HTTP(S) 부하 분산기를 사용하여 공개 인터넷에 애플리케이션을 노출하는 인그레스

저장소에 이미 이러한 리소스를 정의하는 다음 Kubernetes 매니페스트가 포함됩니다.

.NET Core/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: extensions/v1beta1
kind: Ingress
metadata:
  name: clouddemo-netcore
spec:
  backend:
    serviceName: clouddemo-netcore
    servicePort: 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/v1beta1
kind: Ingress
metadata:
  name: clouddemo-net4
spec:
  backend:
    serviceName: clouddemo-net4
    servicePort: 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
        cloud.google.com/gke-os-distribution: windows_ltsc
      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 Core/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 Core/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. 클러스터 역할 결합을 만들어 서비스 계정에 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-dev --format=value\(endpoint\)
    

    잠시 후에 이 주소가 필요합니다.

  5. Azure DevOps 메뉴에서 Project settings(프로젝트 설정)를 선택한 다음 Pipelines(파이프라인) > Service connections(서비스 연결)를 선택합니다.

  6. New service connection(새 서비스 연결)을 클릭합니다.

  7. Kubernetes를 선택하고 Next(다음)를 클릭합니다.

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

    • Authentication method(인증 방법): Service account(서비스 계정)
    • Server URL(서버 URL): 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
    • Service connection name(서비스 연결 이름): azure-pipelines-cicd-dev
  9. 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. 다음 설정을 구성합니다.

    • Authentication method(인증 방법): Service account(서비스 계정)
    • Server URL(서버 URL): 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
    • Service connection name(서비스 연결 이름): azure-pipelines-cicd-prod
  9. Save(저장)를 클릭합니다.

출시 파이프라인 구성

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

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

출시 정의 만들기

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

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

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

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

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

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

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

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

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

개발 클러스터에 배포

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

  1. 메뉴에서 Tasks(태스크) 탭으로 전환합니다.
  2. Agent job(에이전트 작업)을 클릭합니다.
  3. Agent specification(에이전트 사양)ubuntu-18.04로 설정합니다.
  4. Agent job(에이전트 작업) 옆의 Add a task to agent job(에이전트 작업에 태스크 추가) 을 클릭하여 단계(phase)에 단계를 추가합니다.
  5. Deploy to Kubernetes(Kubernetes에 배포) 태스크를 선택하고 Add(추가)를 클릭합니다.
  6. 새로 추가된 작업을 클릭하고 다음 설정을 구성합니다.

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

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

프로덕션 클러스터에 배포

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

  1. 메뉴에서 Pipeline(파이프라인) 탭으로 전환합니다.
  2. 스테이지 상자에서 Add(추가) > New stage(새 스테이지)를 선택합니다.
  3. 템플릿 목록에서 Empty job(빈 작업)을 선택합니다.
  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(에이전트 작업)을 클릭합니다.

  10. Agent specification(에이전트 사양)ubuntu-18.04로 설정합니다.

  11. Add a task to agent job(에이전트 작업에 태스크 추가) 을 클릭하여 단계(phase)에 단계를 추가합니다.

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

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

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

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

파이프라인 실행

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

  1. 로컬 컴퓨터에서 이전에 클론한 Git 저장소의 Index.cshtml 파일을 엽니다.

    .NET Core/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. 팀 탐색기를 열고 Home(홈) 아이콘을 클릭합니다.
    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 메뉴에서 파이프라인을 선택합니다. 빌드가 트리거됩니다.

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

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

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

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

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

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

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

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

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

  13. Cloud Console에서 서비스 페이지를 새로고침합니다.

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

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

삭제

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

Azure Pipelines 프로젝트 삭제

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

Google Cloud 개발 및 프로젝트 삭제

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

    리소스 관리로 이동

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

다음 단계