Cloud Build로 Google Kubernetes Engine (GKE)에 지속적 배포

1. 개요

이 실습에서는 Cloud Build를 사용하여 GKE용 지속적 배포 파이프라인을 설정하는 방법을 알아봅니다. 이 실습에서는 다양한 Git 이벤트에 대해 Cloud Build 작업을 트리거하는 방법과 GKE에서 자동 카나리아 출시를 위한 간단한 패턴을 중점적으로 설명합니다.

다음 단계를 완료합니다.

  • GKE 애플리케이션 만들기
  • Git 브랜치의 배포 자동화
  • Git 기본 브랜치의 배포 자동화
  • git 태그의 배포 자동화

2. 시작하기 전에

이 참조 가이드에는 Google Cloud 프로젝트가 필요합니다. 새 프로젝트를 만들거나 기존에 만든 프로젝트를 선택할 수 있습니다.

  1. Google Cloud 프로젝트를 선택하거나 만듭니다.

프로젝트 선택기 페이지로 이동

  1. 프로젝트에 결제를 사용 설정합니다.

결제 사용 설정

3. 환경 준비

  1. 이 튜토리얼 전체에서 사용할 환경 변수를 만듭니다.
    export PROJECT_ID=$(gcloud config get-value project)
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
    
    export ZONE=us-central1-b
    export CLUSTER=gke-progression-cluster
    export APP_NAME=myapp
    
  2. 다음 API를 사용 설정합니다.
    • Resource Manager
    • GKE
    • Cloud Source Repositories
    • Cloud Build
    • Container Registry
    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        container.googleapis.com \
        sourcerepo.googleapis.com \
        cloudbuild.googleapis.com \
        containerregistry.googleapis.com \
        --async
    
  3. 샘플 소스를 클론하고 실습 디렉터리로 전환합니다.
    git clone https://github.com/GoogleCloudPlatform/software-delivery-workshop.git gke-progression
    
    cd gke-progression/labs/gke-progression
    rm -rf ../../.git
    
  4. 샘플 저장소의 자리표시자 값을 PROJECT_ID로 바꿉니다. 이 단계에서는 현재 환경에 고유한 다양한 구성 파일의 인스턴스를 만듭니다. 업데이트되는 템플릿의 예를 검토하려면 다음 명령어를 실행하세요.
    cat k8s/deployments/dev/frontend-dev.yaml.tmpl
    
    다음 명령어를 실행하여 변수 치환을 실행합니다.
    for template in $(find . -name '*.tmpl'); do envsubst '${PROJECT_ID} ${ZONE} ${CLUSTER} ${APP_NAME}' < ${template} > ${template%.*}; done
    
    대체 후 파일의 예를 검토하려면 다음 명령어를 실행합니다.
    cat k8s/deployments/dev/frontend-dev.yaml
    
  5. 이전에 Cloud Shell에서 Git을 사용하지 않았으면 사용하려는 user.nameuser.email 값을 설정합니다.
    git config --global user.email "YOUR_EMAIL_ADDRESS"
    git config --global user.name "YOUR_USERNAME"
    
  6. 샘플 저장소의 코드를 Cloud Source Repositories에 저장합니다.
    gcloud source repos create gke-progression
    git init
    git config credential.helper gcloud.sh
    git remote add gcp https://source.developers.google.com/p/$PROJECT_ID/r/gke-progression
    git branch -m main
    git add . && git commit -m "initial commit"
    git push gcp main
    
  7. GKE 클러스터를 만듭니다.
    gcloud container clusters create ${CLUSTER} \
        --project=${PROJECT_ID} \
        --zone=${ZONE}
    
  8. 클러스터에 대한 권한을 Cloud Build에 부여합니다.Cloud Build는 GKE 클러스터에 애플리케이션을 배포하므로 이를 수행할 권한이 필요합니다.
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
        --role=roles/container.developer
    

환경이 준비되었습니다.

4. GKE 애플리케이션 만들기

이 섹션에서는 이 튜토리얼 전체에서 사용되는 초기 프로덕션 애플리케이션을 빌드하고 배포합니다.

  1. Cloud Build를 사용하여 애플리케이션을 빌드합니다.
    gcloud builds submit --tag gcr.io/$PROJECT_ID/$APP_NAME:1.0.0 src/
    
  2. 카나리아 및 프로덕션 환경에 수동으로 배포:kubectl apply 명령어를 사용하여 프로덕션 및 카나리아 배포와 서비스를 만듭니다.
    kubectl create ns production
    kubectl apply -f k8s/deployments/prod -n production
    kubectl apply -f k8s/deployments/canary -n production
    kubectl apply -f k8s/services -n production
    
    여기에 배포된 서비스는 카나리아 및 프로덕션 배포 모두로 트래픽을 라우팅합니다.
  3. 실행 중인 포드 수 검토프로덕션 트래픽용 3개와 카나리아 릴리스용 1개를 포함하여 프런트엔드에 실행 중인 포드가 4개인지 확인합니다. 즉, 카나리아 릴리스에 대한 변경사항은 사용자 4명 중 1명 (25%)에게만 적용됩니다.
    kubectl get pods -n production -l app=$APP_NAME -l role=frontend
    
  4. 프로덕션 서비스의 외부 IP 주소를 검색합니다.
    kubectl get service $APP_NAME -n production
    
    부하 분산기에서 IP 주소를 반환하면 다음 단계로 진행합니다.
  5. 나중에 사용할 수 있도록 외부 IP를 저장합니다.
    export PRODUCTION_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}"  --namespace=production services $APP_NAME)
    
  6. 애플리케이션 검토 서비스의 버전 출력 내용을 확인합니다. Hello World v1.0이라고 표시되어야 합니다.
    curl http://$PRODUCTION_IP
    

축하합니다. 샘플 앱을 배포했습니다. 이제 변경사항을 지속적으로 배포하기 위한 트리거를 설정합니다.

5. Git 브랜치의 배포 자동화

이 섹션에서는 main 이외의 브랜치를 커밋할 때 Cloud Build 작업을 실행하는 트리거를 설정합니다. 여기에서 사용되는 Cloud Build 파일은 기존 또는 새 브랜치에 대한 네임스페이스와 배포를 자동으로 생성하므로 개발자는 기본 브랜치와 통합하기 전에 코드를 미리 볼 수 있습니다.

  1. 트리거 설정:이 트리거의 핵심 구성요소는 branchName 매개변수를 사용하여 maininvertRegex 매개변수와 일치시키는 것입니다. invertRegex 매개변수는 true로 설정되어 main이 아닌 모든 항목과 일치하도록 branchName 패턴을 변경합니다. 참고로 build/branch-trigger.json에서 다음 줄을 확인할 수 있습니다.
      "branchName": "main",
      "invertRegex": true
    
    또한 이 트리거와 함께 사용되는 Cloud Build 파일의 마지막 몇 줄은 작업을 트리거한 브랜치의 이름을 따서 네임스페이스를 만든 다음 새 네임스페이스 내에 애플리케이션과 서비스를 배포합니다. 참고로 build/branch-cloudbuild.yaml에서 다음 줄을 확인할 수 있습니다.
      kubectl get ns ${BRANCH_NAME} || kubectl create ns ${BRANCH_NAME}
      kubectl apply --namespace ${BRANCH_NAME} --recursive -f k8s/deployments/dev
      kubectl apply --namespace ${BRANCH_NAME} --recursive -f k8s/services
    
    사용 중인 메커니즘을 이해했으므로 아래 gcloud 명령어로 트리거를 만듭니다.
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/branch-trigger.json
    
  2. 트리거를 검토하려면 콘솔에서 Cloud Build 트리거 페이지로 이동합니다.트리거로 이동
  3. 새 브랜치를 만듭니다.
    git checkout -b new-feature-1
    
  4. v1.1을 나타내도록 코드 수정src/app.py를 수정하고 응답을 1.0에서 1.1로 변경합니다.
    @app.route('/')
    def hello_world():
        return 'Hello World v1.1'
    
  5. 변경사항을 커밋하고 원격 저장소로 푸시합니다.
    git add . && git commit -m "updated" && git push gcp new-feature-1
    
  6. 진행 중인 빌드를 검토하려면 콘솔에서 Cloud Build 기록 페이지로 이동합니다.빌드로 이동빌드가 완료되면 다음 단계로 계속 진행합니다.
  7. 새로 배포된 브랜치 서비스의 외부 IP 주소를 가져옵니다.
    kubectl get service $APP_NAME -n new-feature-1
    
    부하 분산기에서 IP 주소를 반환하면 다음 단계로 진행합니다.
  8. 나중에 사용할 수 있도록 외부 IP를 저장합니다.
    export BRANCH_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}"  --namespace=new-feature-1 services $APP_NAME)
    
  9. 애플리케이션 검토서비스의 버전 출력 내용을 확인합니다. Hello World v1.0이라고 표시되어야 합니다.
    curl http://$BRANCH_IP
    

6. Git 기본 브랜치의 배포 자동화

코드가 프로덕션에 출시되면 모든 트래픽을 새로운 코드베이스로 마이그레이션하기 전에 라이브 트래픽 중 일부에 코드를 출시하는 것이 일반적입니다.

이 섹션에서는 코드가 기본 브랜치에 커밋되었을 때 활성화되는 트리거를 구현합니다. 이 트리거는 모든 라이브 트래픽 중 25% 를 수신하는 카나리아 배포를 새 버전에 배포합니다.

  1. 기본 브랜치의 트리거를 설정합니다.
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/main-trigger.json
    
  2. 새 트리거를 검토하려면 콘솔에서 Cloud Build 트리거 페이지로 이동합니다.트리거로 이동
  3. 브랜치를 기본 줄에 병합하고 원격 저장소에 푸시합니다.
    git checkout main
    git merge new-feature-1
    git push gcp main
    
  4. 진행 중인 빌드를 검토하려면 콘솔에서 Cloud Build 기록 페이지로 이동합니다.빌드로 이동빌드가 완료되면 다음 단계로 계속 진행합니다.
  5. 서버의 여러 응답 검토다음 명령어를 실행하고 응답의 약 25% 가 Hello World v1.1의 새 응답을 표시하는지 확인합니다.
    while true; do curl -w "\n" http://$PRODUCTION_IP; sleep 1;  done
    
    계속할 준비가 되면 Ctrl+c를 눌러 루프를 종료합니다.

7. Git 태그의 배포 자동화

트래픽 일부를 사용해서 카나리아 배포가 검증된 다음에는 나머지 라이프 트래픽에 배포를 출시합니다.

이 섹션에서는 저장소에서 태그를 만들 때 활성화되는 트리거를 설정합니다. 트리거는 이미지에 적절한 태그를 지정한 다음 업데이트를 프로덕션에 배포하여 트래픽의 100% 가 태그가 지정된 이미지에 액세스하도록 합니다.

  1. 태그 트리거를 설정합니다.
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/tag-trigger.json
    
  2. 새 트리거를 검토하려면 콘솔에서 Cloud Build 트리거 페이지로 이동합니다.트리거로 이동
  3. 새 태그를 만들고 원격 저장소에 푸시합니다.
    git tag 1.1
    git push gcp 1.1
    
  4. 진행 중인 빌드를 검토하려면 콘솔에서 Cloud Build 기록 페이지로 이동합니다.빌드로 이동
  5. 서버의 여러 응답 검토다음 명령어를 실행하고 응답의 100% 가 Hello World v1.1의 새 응답을 표시하는지 확인합니다.GKE 내에서 새 포드가 배포되고 상태 점검이 실행되므로 시간이 걸릴 수 있습니다.
    while true; do curl -w "\n" http://$PRODUCTION_IP; sleep 1;  done
    
    계속할 준비가 되면 Ctrl+c을 눌러 루프를 종료합니다.축하합니다! GKE에 앱을 배포하기 위해 브랜치 및 태그용 Cloud Build에서 CI/CD 트리거를 만들었습니다.

8. 삭제

프로젝트 삭제

  1. Cloud 콘솔에서 리소스 관리 페이지로 이동합니다.
  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력하고 종료를 클릭하여 프로젝트를 삭제합니다.