이 페이지에서는 호스팅 제품과 널리 사용되는 GititOps 방법론만을 사용하여 Google Cloud에서 지속적 통합 및 배포(CI/CD) 파이프라인을 만드는 방법을 설명합니다.
오랫동안 Google의 엔지니어들은 구성 및 배포 파일을 Google의 기본 소스 코드 저장소에 보관해 왔습니다. 이 방법론은 사이트 안정성 엔지니어링 8장(Beyer et al., 2016)에서 다루었으며, Google Cloud Next '17 키노트에서 켈시 하이타워가 시연한 바 있습니다.
GitOps의 핵심은 '코드로 표현한 환경', 즉 Git 저장소에 저장된 Kubernetes 매니페스트와 같은 파일을 사용하여 배포를 선언적으로 기술한다는 개념입니다.
이 가이드에서는 커밋된 코드로부터 컨테이너 이미지를 자동으로 빌드하는 CI/CD 파이프라인을 만들고, Artifact Registry에 이미지를 저장하고, Git 저장소의 Kubernetes 매니페스트를 업데이트하고, 이 매니페스트를 사용하여 애플리케이션을 Google Kubernetes Engine에 배포합니다.
이 튜토리얼에서는 두 개의 Git 저장소를 사용합니다.
- app 저장소: 애플리케이션 자체의 소스 코드를 포함합니다.
- env 저장소: Kubernetes 배포용 매니페스트를 포함합니다.
변경사항을 app 저장소에 푸시하면 Cloud Build 파이프라인이 테스트를 실행하고 컨테이너 이미지를 빌드하여 Artifact Registry에 푸시합니다. Cloud Build는 이미지를 푸시한 후 배포 매니페스트를 업데이트하여 env 저장소에 푸시합니다. 이때 다른 Cloud Build 파이프라인이 트리거되며, 이 파이프라인은 GKE 클러스터에 매니페스트를 적용하고 성공하면 env 저장소의 다른 분기에 매니페스트를 저장합니다.
app과 env 저장소를 분리하는 이유는 수명 주기와 용도가 서로 다르기 때문입니다. app 저장소는 주 사용자가 실제 사람이며 특정 애플리케이션 전용입니다. env 저장소는 주 사용자가 Cloud Build 등의 자동화된 시스템이며 여러 애플리케이션에 공유될 수 있습니다. env 저장소는 각각 특정 환경에 매핑되는 여러 분기(이 튜토리얼에서는 production만 사용)를 가질 수 있으며 특정 컨테이너 이미지를 참조하지만, env 저장소는 그렇지 않습니다.
이 튜토리얼을 마치면 다음 작업을 손쉽게 처리할 수 있는 시스템이 구축됩니다.
- Cloud Build 기록을 조회하여 배포 실패와 성공 구분
- env 저장소의 production 분기를 조회하여 현재 사용 중인 매니페스트에 액세스
- Cloud Build의 해당 빌드를 다시 실행하여 이전 버전으로 롤백
이 튜토리얼 정보
이 튜토리얼에서는 Cloud Source Repositories를 사용하여 Git 저장소를 호스팅하지만 GitHub, Bitbucket, GitLab 등의 다른 타사 제품을 사용해도 같은 결과를 얻을 수 있습니다.
이 파이프라인은 배포 전 검증 메커니즘을 구현하지 않습니다. GitHub, Bitbucket 또는 GitLab을 사용하는 경우 파이프라인을 수정하여 pull 요청을 이 용도로 사용할 수 있습니다.
팀에서 블루-그린, 카나리아 분석, 멀티 클라우드 등의 고급 배포 패턴을 구현하려는 경우 Spinnaker가 권장되지만, 소규모 조직 및 프로젝트에서는 이러한 기능 모음 없이도 성공적으로 CI/CD 전략을 구현할 수 있습니다. 이 튜토리얼에서는 도구를 사용하여 GKE에 호스팅된 애플리케이션에 적합한 CI/CD 파이프라인을 만드는 방법을 알아봅니다.
이 튜토리얼에서는 편의상 env 저장소에서 단일 환경(production)만 사용하지만 필요한 경우 여러 환경으로 배포하도록 확장할 수 있습니다.
목표
- Cloud Source Repositories에 Git 저장소 만들기
- Cloud Build로 컨테이너 이미지를 만들고 Artifact Registry에 저장
- CI 파이프라인 만들기
- CD 파이프라인 만들기
- CI/CD 파이프라인 테스트
비용
이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.
프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요.
이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.
시작하기 전에
Google Cloud 프로젝트를 선택하거나 만듭니다.
프로젝트에 결제를 사용 설정합니다.
Cloud Shell을 열고 이 튜토리얼에 나열된 명령어를 실행합니다. Cloud Shell은 웹브라우저에서 프로젝트와 리소스를 관리할 수 있는 Google Cloud용 대화형 셸 환경입니다.
gcloud config get-value project
명령어가 방금 선택한 프로젝트의 ID를 반환하지 않으면 Cloud Shell이 프로젝트를 사용하도록 구성합니다.gcloud config set project [PROJECT_ID]
Cloud Shell에서 필요한 API를 사용 설정합니다.
gcloud services enable container.googleapis.com \ cloudbuild.googleapis.com \ sourcerepo.googleapis.com \ artifactregistry.googleapis.com
us-central1
리전에my-repository
라는 Artifact Registry Docker 저장소를 만들어 컨테이너 이미지를 저장합니다.gcloud artifacts repositories create my-repository \ --repository-format=docker \ --location=us-central1
Cloud Shell에서 이 가이드의 샘플 애플리케이션을 배포하는 데 사용할 GKE 클러스터를 만듭니다.
Autopilot
hello-cloudbuild
라는 Autopilot 클러스터를 만듭니다.gcloud container clusters create-auto hello-cloudbuild \ --region us-central1
표준
hello-cloudbuild
라는 단일 노드 표준 클러스터를 만듭니다.gcloud container clusters create hello-cloudbuild \ --num-nodes 1 --region us-central1
Cloud Shell에서 Git을 사용한 적이 없는 경우 내 이름과 이메일 주소를 사용하여 구성합니다. Git은 이러한 정보를 사용하여 Cloud Shell에서 만드는 커밋의 작성자를 식별합니다.
git config --global user.email "YOUR_EMAIL_ADDRESS" git config --global user.name "YOUR_NAME"
이 튜토리얼을 마치면 만든 리소스를 삭제하여 비용이 계속 청구되지 않도록 할 수 있습니다. 자세한 내용은 삭제를 참조하세요.
Cloud Source Repositories에 Git 저장소 만들기
이 섹션에서는 이 튜토리얼에 사용되는 두 개의 Git 저장소(app과 env)를 만들고 app 저장소를 샘플 코드로 초기화합니다.
Cloud Shell에서 두 개의 Git 저장소를 만듭니다.
gcloud source repos create hello-cloudbuild-app gcloud source repos create hello-cloudbuild-env
GitHub에서 샘플 코드를 복제합니다.
cd ~ git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples cd ~/kubernetes-engine-samples/management/gitops-style-delivery/
Cloud Source Repositories를 원격으로 구성합니다.
PROJECT_ID=$(gcloud config get-value project) git remote add google \ "https://source.developers.google.com/p/${PROJECT_ID}/r/hello-cloudbuild-app"
클론한 코드에는 'Hello World' 애플리케이션이 포함되어 있습니다.
Cloud Build로 컨테이너 이미지 만들기
복제한 코드에는 다음 Dockerfile이 포함되어 있습니다.
이 Dockerfile을 사용하면 Cloud Build로 컨테이너 이미지를 만들어 Artifact Registry에 저장할 수 있습니다.
Cloud Shell에서 다음 명령어를 사용하여 최신 커밋에 따라 Cloud Build 빌드를 만듭니다.
cd ~/kubernetes-engine-samples/management/gitops-style-delivery/ COMMIT_ID="$(git rev-parse --short=7 HEAD)" gcloud builds submit --tag="us-central1-docker.pkg.dev/${PROJECT_ID}/my-repository/hello-cloudbuild:${COMMIT_ID}" .
이 명령어를 실행하면 Cloud Build는 컨테이너 이미지가 만들어질 때 생성되는 로그를 터미널에 스트리밍합니다.
빌드가 끝난 후 새 컨테이너 이미지를 Artifact Registry에서 사용할 수 있는지 확인합니다.
지속적 통합 파이프라인 만들기
이 섹션에서는 소규모 단위 테스트를 자동으로 실행하고 컨테이너 이미지를 빌드하여 Artifact Registry에 푸시하도록 Cloud Build를 구성합니다. Cloud Source Repositories에 새 커밋을 푸시하면 이 파이프라인이 자동으로 트리거됩니다. 코드에 포함된 cloudbuild.yaml
파일은 파이프라인의 구성입니다.
Cloud Build 트리거 페이지를 엽니다.
트리거 만들기를 클릭합니다.
다음 옵션을 입력합니다.
- 이름 필드에
hello-cloudbuild
를 입력합니다. - 이벤트에서 분기로 푸시를 선택합니다.
- 소스에서
hello-cloudbuild-app
을 저장소로 선택하고^master$
를 분기로 선택합니다. - 빌드 구성에서 Cloud Build 구성 파일을 선택합니다.
- Cloud Build 구성 파일 위치 필드에
/
와cloudbuild.yaml
을 차례로 입력합니다.
- 이름 필드에
만들기를 클릭하여 빌드 트리거를 저장합니다.
팁: 많은 프로젝트의 빌드 트리거를 만들어야 하는 경우에는 Build Triggers API를 사용하면 됩니다.
Cloud Shell에서 애플리케이션 코드를 Cloud Source Repositories에 푸시하여 Cloud Build의 CI 파이프라인을 트리거합니다.
cd ~/kubernetes-engine-samples/management/gitops-style-delivery/ git push google master
Cloud Build 콘솔을 엽니다.
최근에 실행한 빌드와 완료된 빌드가 표시됩니다. 빌드를 클릭하면 실행 상태를 추적하고 로그를 조사할 수 있습니다.
지속적 배포 파이프라인 만들기
Cloud Build는 지속적 배포 파이프라인에도 사용됩니다. hello-cloudbuild-env 저장소의 candidate 분기에 커밋이 푸시될 때마다 파이프라인이 실행됩니다. 이 파이프라인은 Kubernetes 클러스터에 매니페스트의 새 버전을 적용하고, 여기에 성공하면 매니페스트를 production 분기에 복사합니다. 이 프로세스의 속성은 다음과 같습니다.
- candidate 분기는 배포 시도 기록입니다.
- production 분기는 배포 성공 기록입니다.
- Cloud Build에서 배포 성공과 실패를 확인할 수 있습니다.
- Cloud Build의 해당 빌드를 다시 실행하여 이전 배포로 롤백할 수 있습니다. 롤백하면 배포 기록을 정확히 반영하기 위해 production 분기도 업데이트됩니다.
이제 지속적 통합 파이프라인을 수정하여 hello-cloudbuild-env 저장소의 candidate 분기를 업데이트하고 지속적 배포 파이프라인을 트리거하겠습니다.
GKE에 Cloud Build 액세스 권한 부여
애플리케이션을 Kubernetes 클러스터에 배포하려면 Cloud Build에 Kubernetes Engine 개발자 ID 및 액세스 관리 역할이 필요합니다.
Shell
Cloud Shell에서 다음 명령어를 실행합니다.
PROJECT_NUMBER="$(gcloud projects describe ${PROJECT_ID} --format='get(projectNumber)')" gcloud projects add-iam-policy-binding ${PROJECT_NUMBER} \ --member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \ --role=roles/container.developer
콘솔
Google Cloud Console에서 Cloud Build 설정 페이지를 엽니다.
서비스 계정 권한 페이지가 표시됩니다.
Kubernetes Engine 개발자 역할의 상태를 사용 설정으로 설정합니다.
hello-cloudbuild-env 저장소 초기화
hello-cloudbuild-env 저장소를 두 개의 분기(hello-cloudbuild-env과 hello-cloudbuild-env) 및 배포 프로세스를 기술하는 Cloud Build 구성 파일로 초기화해야 합니다.
Cloud Shell에서 hello-cloudbuild-env 저장소를 클론하고 hello-cloudbuild-env 분기를 만듭니다.
cd ~ gcloud source repos clone hello-cloudbuild-env cd ~/kubernetes-engine-samples/management/gitops-style-delivery/ git checkout -b production
hello-cloudbuild-app 저장소에서 사용할 수 있는
cloudbuild-delivery.yaml
파일을 복사하고 변경사항을 커밋합니다.cd ~/kubernetes-engine-samples/management/gitops-style-delivery/ cp ~/hello-cloudbuild-app/cloudbuild-delivery.yaml ~/kubernetes-engine-samples/management/gitops-style-delivery/cloudbuild.yaml git add . git commit -m "Create cloudbuild.yaml for deployment"
cloudbuild-delivery.yaml
파일은 Cloud Build에서 실행될 배포 프로세스를 설명합니다. 프로세스는 두 단계로 구성됩니다.Cloud Build가 GKE 클러스터에 매니페스트를 적용합니다.
여기에 성공하면 Cloud Build가 매니페스트를 production 분기에 복사합니다.
candidate 분기를 만들고 두 분기를 푸시하여 Cloud Source Repositories에 제공합니다.
git checkout -b candidate git push origin production git push origin candidate
hello-cloudbuild-env 저장소의 Cloud Build 서비스 계정에 소스 저장소 작성자 IAM 역할을 부여합니다.
PROJECT_NUMBER="$(gcloud projects describe ${PROJECT_ID} \ --format='get(projectNumber)')" cat >/tmp/hello-cloudbuild-env-policy.yaml <<EOF bindings: - members: - serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com role: roles/source.writer EOF gcloud source repos set-iam-policy \ hello-cloudbuild-env /tmp/hello-cloudbuild-env-policy.yaml
지속적 배포 파이프라인의 트리거 만들기
이 섹션에서는 hello-cloudbuild-env 저장소의 candidate 분기에 푸시할 때 Cloud Build가 트리거되도록 구성합니다.
Cloud Build의 트리거 페이지를 엽니다.
트리거 만들기를 클릭합니다.
다음 옵션을 입력합니다.
- 이름 필드에
hello-cloudbuild-deploy
를 입력합니다. - 이벤트에서 분기로 푸시를 선택합니다.
- 소스에서
hello-cloudbuild-env
을 저장소로 선택하고^candidate$
를 분기로 선택합니다. - 구성에서 Cloud Build 구성 파일(yaml 또는 json)을 선택합니다.
- Cloud Build 구성 파일 위치 필드에
/
와cloudbuild.yaml
을 차례로 입력합니다.
- 이름 필드에
만들기를 클릭합니다.
지속적 배포 파이프라인을 트리거하도록 지속적 통합 파이프라인 수정
이 섹션에서는 지속적 통합 파이프라인에 몇 단계를 추가하여 Kubernetes 매니페스트의 새 버전을 생성하고 hello-cloudbuild-env 저장소에 푸시하여 지속적 배포 파이프라인을 트리거합니다.
cloudbuild.yaml
파일을cloudbuild-trigger-cd.yaml
파일의 확장 예시로 바꿉니다.cd ~/kubernetes-engine-samples/management/gitops-style-delivery/ cp cloudbuild-trigger-cd.yaml cloudbuild.yaml
cloudbuild-trigger-cd.yaml
은cloudbuild.yaml
의 확장된 버전입니다. 새 Kubernetes 매니페스트를 생성하고 지속적 배포 파이프라인을 트리거하는 단계를 추가합니다.수정사항을 커밋한 후 Cloud Source Repositories에 푸시합니다.
cd ~/kubernetes-engine-samples/management/gitops-style-delivery/ git add cloudbuild.yaml git commit -m "Trigger CD pipeline" git push google master
이렇게 하면 Cloud Build의 지속적 통합 파이프라인이 트리거됩니다.
지속적 통합 빌드를 조사합니다.
hello-cloudbuild-app 저장소의 최근 실행 및 완료된 빌드가 나타납니다. 빌드를 클릭하면 실행 상태를 추적하고 로그를 조사할 수 있습니다. 이 파이프라인의 마지막 단계에서는 새 매니페스트를 hello-cloudbuild-env 저장소에 푸시하여 지속적 배포 파이프라인을 트리거합니다.
지속적 배포 빌드를 조사합니다.
hello-cloudbuild-env 저장소의 최근 실행 및 완료된 빌드가 표시됩니다. 빌드를 클릭하면 실행 상태를 추적하고 로그를 조사할 수 있습니다.
전체 파이프라인 테스트
이제 전체 CI/CD 파이프라인이 구성되었습니다. 이 섹션에서는 파이프라인을 처음부터 끝까지 테스트합니다.
GKE 서비스 페이지로 이동합니다.
Google Kubernetes Engine 서비스로 이동
목록에는 최근에 완료된 지속적 배포 빌드에서 만든 hello-cloudbuild라는 단일 서비스가 포함되어 있습니다.
hello-cloudbuild 서비스의 엔드포인트를 클릭합니다. 'Hello World!'가 표시됩니다. 엔드포인트가 없거나 부하 분산기 오류가 표시되는 경우 부하 분산기가 완전히 초기화될 때까지 몇 분 정도 기다려야 할 수 있습니다. 필요하다면 새로고침을 클릭하여 페이지를 업데이트합니다.
Cloud Shell에서 애플리케이션 및 단위 테스트의 'Hello World'를 'Hello Cloud Build'로 바꿉니다.
cd ~/kubernetes-engine-samples/management/gitops-style-delivery/ sed -i 's/Hello World/Hello Cloud Build/g' app.py sed -i 's/Hello World/Hello Cloud Build/g' test_app.py
변경사항을 커밋하고 Cloud Source Repositories에 푸시합니다.
git add app.py test_app.py git commit -m "Hello Cloud Build" git push google master
이렇게 하면 전체 CI/CD 파이프라인이 트리거됩니다.
몇 분 후에 브라우저에서 애플리케이션을 다시 로드합니다. 'Hello Cloud Build!'가 표시됩니다.
롤백 테스트
이 세션에서는 'Hello World!'를 표시하던 애플리케이션 버전으로 롤백합니다.
hello-cloudbuild-env 저장소의 Cloud Build 콘솔을 엽니다.
사용 가능한 빌드 중에서 두 번째로 최신인 빌드를 클릭합니다.
다시 빌드를 클릭합니다.
빌드가 끝나면 브라우저에서 애플리케이션을 다시 로드합니다. 'Hello World!'가 다시 표시됩니다.
삭제
이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
리소스 삭제
이 튜토리얼에서 사용된 Google Cloud 프로젝트를 유지하려면 개별 리소스를 삭제합니다.
로컬 Git 저장소를 삭제합니다.
cd ~ rm -rf ~/hello-cloudbuild-app rm -rf ~/hello-cloudbuild-env
Cloud Source Repositories의 Git 저장소를 삭제합니다.
gcloud source repos delete hello-cloudbuild-app --quiet gcloud source repos delete hello-cloudbuild-env --quiet
Cloud Build 트리거를 삭제합니다.
Cloud Build의 트리거 페이지를 엽니다.
각 트리거에 대해 추가 more_vert를 클릭한 다음 삭제를 클릭합니다.
Artifact Registry에서 Docker 저장소를 삭제합니다.
gcloud artifacts repositories delete my-repository \ --location=us-central1
GKE에 연결하도록 Cloud Build에 부여한 권한을 삭제합니다.
PROJECT_NUMBER="$(gcloud projects describe ${PROJECT_ID} \ --format='get(projectNumber)')" gcloud projects remove-iam-policy-binding ${PROJECT_NUMBER} \ --member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \ --role=roles/container.developer
GKE 클러스터를 삭제합니다.
gcloud container clusters delete hello-cloudbuild \ --region us-central1