마짱짱의 지식창고

[GCP] Cloud Build 를 이용한 GKE 파이프라인 구축 본문

Cloud/GCP

[GCP] Cloud Build 를 이용한 GKE 파이프라인 구축

마짱짱 2023. 2. 14. 15:36
반응형

0. 개요

Commit 된 코드를 컨테이너 이미지에 자동으로 Build하고 Artifact Registry에 이미지를 저장, Git 저장소에서 k8s Manifest를 업데이트 하고, 해당 Manifest를 사용하여 Application을 GKE에 배포하는 CI/CD를 만듭니다.

 

해당 포스팅에선 2개의 Git Repository를 생성합니다.

1. App Repository: Application 자체의 소스 코드를 포함합니다.

2. env Repository: k8s 배포에 대한 Manifest를 포함합니다.

 

App Repository에 변경사항을 Push 하면 Cloud Build Pipeline이 테스트를 실행 하고 컨테이너 이미지를 빌드 한 다음 Artifact Registry에 Push 합니다. 이미지를 Push 한 후 Cloud Build는 배포 Manifeest 를 업데이트 하고 이를
env Repository에 Push 합니다. 이렇게 하면 Manifest를 GKE Cluster에 적용하는 또다른 Cloud Build Pipeline 트리거가 되고 성공되면 env 저장소의 다른 분기에 Menifest를 저장합니다.

 

app 및 env Repository는 수명주기와 용도가 다르기 때문에 별도로 유지됩니다.

App Repository의 주요 사용자는 실제 사람이며, 특정 Application 전용 입니다.

env Repository의 주요 사용자는 자동화된 시스템 이며 여러 Application 에서 공유 될 수 있습니다.

env Repository에는 각각 특정환경(dev, stg, prod, etc...)에 매핑되고 특정 컨테이너 이미지를 참조하는 여러 분기가 될 수 있지만 App Repository는 그렇지 않습니다.

 

해당 포스팅을 하시게 되면 다음과 같은 시스템을 갖추게 됩니다.

1. Cloud Build 기록을 보고 실패한 배포와 성공한 배포 구분

2. env Repository의 Prod 분기를 보고 현재 사용중인 Manifest에 Access 

3. 해당 Cloud Build의 빌드를 다시 실행하여 이전 버전으로 롤백

 

 

 

1. 필요한 GCP Project 환경세팅

모든 작업은 Cloud Shell 에서 실행합니다.

 

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
export REGION=us-central1
gcloud config set compute/region $REGION

프로젝트 ID, number, Region 선언

 

gcloud services enable container.googleapis.com \
    cloudbuild.googleapis.com \
    sourcerepo.googleapis.com \
    containeranalysis.googleapis.com

GCP API 활성화

 

gcloud artifacts repositories create my-repository \
  --repository-format=docker \
  --location=$REGION

Artifacts Repository(Docker) 생성

 

  gcloud container clusters create hello-cloudbuild --num-nodes 1 --region $REGION

GKE 생성

 

git config --global user.email "majjangjjang@example.com"  
git config --global user.name "majjangjjang"

Git 설정, 실제로 계정 없어도 됩니다.

 

gcloud source repos create hello-cloudbuild-app
gcloud source repos create hello-cloudbuild-env

Google Source Repository의 app용, env 용 2개 Repository 생성

 

 

git clone https://github.com/GoogleCloudPlatform/gke-gitops-tutorial-cloudbuild hello-cloudbuild-app

Sample 용 Git clone 하기

 

cd ~/hello-cloudbuild-app
PROJECT_ID=$(gcloud config get-value project)
git remote add google "https://source.developers.google.com/p/${PROJECT_ID}/r/hello-cloudbuild-app"

복사한 Sample App 을 App Repository로 저장소 추가

 

2. Cloud Build 를 이용하여 Container Image 생성

cd ~/hello-cloudbuild-app

Sample App Dir 이동

 

COMMIT_ID="$(git rev-parse --short=7 HEAD)"
gcloud builds submit --tag="${REGION}-docker.pkg.dev/${PROJECT_ID}/my-repository/hello-cloudbuild:${COMMIT_ID}" .

Cloud Build를 이용하여 Artifact Repository에 Container Image 생성

 

Cloud Build 에서 History 확인할 수 있음

 

또한 Artifact Registry에서도 확인 가능

 

3. CI 환경 구성하기

 작은 단위 테스트를 자동으로 실행하고 컨테이너 이미지를 빌드한 다음 Artifact Registry에 푸시하도록 Cloud Build를 구성합니다.Cloud Source Repositories에 새 커밋을 푸시하면 이 파이프라인이 자동으로 트리거됩니다. 코드에 이미 포함된 cloudbuild.yaml 파일 은 파이프라인의 구성입니다.

 

 

먼저 Coud Build이동하여 Triggers -> Create Trigger 클릭

 

이름설정, Event는 Branch Push시에

Repository는 App Repository선택, Branch는 .*

Cloud Build시 cloudbuild.yaml을 참조하여 구성

 

# Copyright 2018 Google LLC
#
# Licensed 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
#
#     https://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.
### Cloudbuild.yaml
# See the License for the specific language governing permissions and
# limitations under the License.

# [START cloudbuild]
steps:
# This step runs the unit tests on the app
- name: 'python:3.7-slim'
  id: Test
  entrypoint: /bin/sh
  args:
  - -c
  - 'pip install flask && python test_app.py -v'

# This step builds the container image.
- name: 'gcr.io/cloud-builders/docker'
  id: Build
  args:
  - 'build'
  - '-t'
  - 'us-central1-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild:$SHORT_SHA'
  - '.'

# This step pushes the image to Artifact Registry
# The PROJECT_ID and SHORT_SHA variables are automatically
# replaced by Cloud Build.
- name: 'gcr.io/cloud-builders/docker'
  id: Push
  args:
  - 'push'
  - 'us-central1-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild:$SHORT_SHA'
# [END cloudbuild]

 

 

생성하기 클릭

 

생성 완료

 

cd ~/hello-cloudbuild-app
git push google master

Application Code를 Cloud Source Repository에 Push하여 Cloud Build Trigger가 올바르게 동작하는 지 확인

 

 

Cloud Build Dashboard에서 Monitoring 가능합니다.

 

4. CD 환경 구성하기

Cloud Build는 지속적 배포 파이프라인에도 사용됩니다. 파이프라인은 커밋이 hello-cloudbuild-env 저장소 의 후보 분기로 푸시될 때마다 실행됩니다 . 파이프라인은 새 버전의 매니페스트를 Kubernetes 클러스터에 적용하고 성공하면 매니페스트를 프로덕션 브랜치로 복사합니다. 이 프로세스에는 다음과 같은 속성이 있습니다.

  • 후보 분기는 배포 시도의 기록입니다.
  • 프로덕션 분기는 성공적인 배포의 기록입니다.
  • Cloud Build에서 성공한 배포와 실패한 배포를 볼 수 있습니다.
  • Cloud Build에서 해당 빌드를 다시 실행하여 이전 배포로 롤백할 수 있습니다. 또한 롤백은 프로덕션 분기를 업데이트하여 배포 기록을 정직하게 반영합니다.

다음으로 지속적 통합 파이프라인을 수정하여 hello-cloudbuild-env 리포지토리 의 후보 분기를 업데이트하여 지속적 배포 파이프라인을 트리거합니다.

 

GKE Cluster에 애플리케이션을 배포하려면 Cloud Build에 Kubernetes Engine 개발자 ID 및 액세스 관리 역할이 필요합니다.

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

Cloud Build에 GKE 개발자 권한 부여

 

배포 프로세스를 설명하는 Cloud Build 구성 파일과 두 개의 분기(프로덕션 및 후보)로 hello-cloudbuild-env 저장소를 초기화해야 합니다 .첫 번째 단계는 hello-cloudbuild-env 리포지토리를 복제 하고 프로덕션 브랜치를 생성하는 것입니다. 아직 비어 있습니다.

 

cd ~
gcloud source repos clone hello-cloudbuild-env
cd ~/hello-cloudbuild-env
git checkout -b production

Source Repository의 hello-cloudbuild-env Repository를 복사하고 'production' branch 생성

 

---

 

Cloudbuild-delivery.yaml의 내용은 배포에 관한 설정이 정의되어 있습니다.

  • Cloud Build는 GKE 클러스터에 매니페스트를 적용합니다.
  • 성공하면 Cloud Build가 프로덕션 브랜치에 매니페스트를 복사합니다
cd ~/hello-cloudbuild-env
cp ~/hello-cloudbuild-app/cloudbuild-delivery.yaml ~/hello-cloudbuild-env/cloudbuild.yaml
git add .
git commit -m "Create cloudbuild.yaml for deployment"
### hello-cloudbuild-app의 cloudbuild-delivery.yaml을 복사해서 만든 cloudbuild.yaml

# Copyright 2018 Google LLC
#
# Licensed 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
#
#     https://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.

# [START cloudbuild-delivery]
steps:
# This step deploys the new version of our container image
# in the hello-cloudbuild Kubernetes Engine cluster.
- name: 'gcr.io/cloud-builders/kubectl'
  id: Deploy
  args:
  - 'apply'
  - '-f'
  - 'kubernetes.yaml'
  env:
  - 'CLOUDSDK_COMPUTE_REGION=us-central1'
  - 'CLOUDSDK_CONTAINER_CLUSTER=hello-cloudbuild'

# This step copies the applied manifest to the production branch
# The COMMIT_SHA variable is automatically
# replaced by Cloud Build.
- name: 'gcr.io/cloud-builders/git'
  id: Copy to production branch
  entrypoint: /bin/sh
  args:
  - '-c'
  - |
    set -x && \
    # Configure Git to create commits with Cloud Build's service account
    git config user.email $(gcloud auth list --filter=status:ACTIVE --format='value(account)') && \
    # Switch to the production branch and copy the kubernetes.yaml file from the candidate branch
    git fetch origin production && git checkout production && \
    git checkout $COMMIT_SHA kubernetes.yaml && \
    # Commit the kubernetes.yaml file with a descriptive commit message
    git commit -m "Manifest from commit $COMMIT_SHA
    $(git log --format=%B -n 1 $COMMIT_SHA)" && \
    # Push the changes back to Cloud Source Repository
    git push origin production
# [END cloudbuild-delivery]

 

 

후보 분기를 만들고 Cloud Source Repositories에서 사용할 수 있도록 두 분기를 모두 푸시합니다.

git checkout -b candidate
git push origin production
git push origin candidate

 

hello-cloudbuild-env Repository의 Cloud Build Service Account에 Source Repository Writer 역할부여

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

 

CD 관련 Pipeline 만들기

 

Cloud Build의 Trigger에서 "Create Trigger" 클릭

 

이름 및 Event "Push to Branch" 설정

 

hello-cloudbuild-env Repository 선택 및 Branch "candidate" 설정

 

Cloudbuild.yaml 설정적용 후 생성하기

 

 

생성 완료

 

 

생성된 CD 파이프라인 테스트

 

다음으로 Kubernetes 매니페스트의 새 버전을 생성하고 이를 hello-cloudbuild-env 리포지토리로 푸시하여 지속적 배포 파이프라인을 트리거하는 지속적 통합 파이프라인에 몇 가지 단계를 추가합니다.

 

app repositorty에 대한 cloudbuild.yaml의 확정버전 복사

 

cd ~/hello-cloudbuild-app
cp cloudbuild-trigger-cd.yaml cloudbuild.yaml
### cloudbuild-trigger-cd.yaml

# Copyright 2018 Google LLC
#
# Licensed 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
#
#     https://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.

# [START cloudbuild]
steps:
# This step runs the unit tests on the app
- name: 'python:3.7-slim'
  id: Test
  entrypoint: /bin/sh
  args:
  - -c
  - 'pip install flask && python test_app.py -v'

# This step builds the container image.
- name: 'gcr.io/cloud-builders/docker'
  id: Build
  args:
  - 'build'
  - '-t'
  - 'us-central1-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild:$SHORT_SHA'
  - '.'

# This step pushes the image to Artifact Registry
# The PROJECT_ID and SHORT_SHA variables are automatically
# replaced by Cloud Build.
- name: 'gcr.io/cloud-builders/docker'
  id: Push
  args:
  - 'push'
  - 'us-central1-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild:$SHORT_SHA'
# [END cloudbuild]

# [START cloudbuild-trigger-cd]
# This step clones the hello-cloudbuild-env repository
- name: 'gcr.io/cloud-builders/gcloud'
  id: Clone env repository
  entrypoint: /bin/sh
  args:
  - '-c'
  - |
    gcloud source repos clone hello-cloudbuild-env && \
    cd hello-cloudbuild-env && \
    git checkout candidate && \
    git config user.email $(gcloud auth list --filter=status:ACTIVE --format='value(account)')

# This step generates the new manifest
- name: 'gcr.io/cloud-builders/gcloud'
  id: Generate manifest
  entrypoint: /bin/sh
  args:
  - '-c'
  - |
     sed "s/GOOGLE_CLOUD_PROJECT/${PROJECT_ID}/g" kubernetes.yaml.tpl | \
     sed "s/COMMIT_SHA/${SHORT_SHA}/g" > hello-cloudbuild-env/kubernetes.yaml

# This step pushes the manifest back to hello-cloudbuild-env
- name: 'gcr.io/cloud-builders/gcloud'
  id: Push manifest
  entrypoint: /bin/sh
  args:
  - '-c'
  - |
    set -x && \
    cd hello-cloudbuild-env && \
    git add kubernetes.yaml && \
    git commit -m "Deploying image us-central1-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild:${SHORT_SHA}
    Built from commit ${COMMIT_SHA} of repository hello-cloudbuild-app
    Author: $(git log --format='%an <%ae>' -n 1 HEAD)" && \
    git push origin candidate

# [END cloudbuild-trigger-cd]

 

수정사항을 Commit 하고 Cloud Source Repository에 Push

cd ~/hello-cloudbuild-app
git add cloudbuild.yaml
git commit -m "Trigger CD pipeline"
git push google master

 

Cloud Build Console창에서 Dashboard 및 history를 볼 수 있습니다.

 

 

전체적인 CI/CD Pipeline Test

 

GKE의 service & ingress 이동하여 생성한 hello-cloudbuild application 확인

 

이제 app에서 hello world를 hello cloud build 로 변경하여 CI/CD 테스트

cd ~/hello-cloudbuild-app
sed -i 's/Hello World/Hello Cloud Build/g' app.py
sed -i 's/Hello World/Hello Cloud Build/g' test_app.py

git add app.py test_app.py
git commit -m "Hello Cloud Build"
git push google master

 

Cloud Build 에서 과거 History를 보고 Rebuild를 하여 복구도 가능하다.

 

 

출처

https://www.cloudskillsboost.google/focuses/52829?catalog_rank=%7B%22rank%22%3A2%2C%22num_filters%22%3A0%2C%22has_search%22%3Atrue%7D&parent=catalog&search_id=22331794 

https://cloud.google.com/build/docs/configuring-builds/create-basic-configuration?hl=ko 

 

반응형