애플리케이션을 수정하고 다시 빌드하고 배포하는 작업, 이런 반복작업은 굉장히 시간 소비가 클 뿐만이 아니라 수작업으로 계속 수행하기 번거로운 작업이다. 작은 단위의 테스트면 몰라도 조금 더 큰 시스템을 일일이 수작업으로 빌드, 배포하는 것은 쉽지 않은 일이다. 이번 장에서는 자동으로 이러한 일을 해줄 수 있는 방법에 대해서 알아보도록 하겠다.
자신의 github나 gitlab의 샘플 애플리케이션을 직접 빌드하고 배포하기 위해서 해당 소스를 로컬 환경으로 clone 한다.
git clone https://github.com/lhbbbb/enterview.git
최종적으로 완성될 아키텍처는 다음과 같다.
Cloud Build 를 통한 CI/CD 구성을 해보도록 한다. GCP의 Marketplace 항목에서 Cloud Build를 검색하여 사용 설정을 클릭해야 한다.
우선 가장 먼저 GKE 작업을 위한 권한에 문제가 없도록 하기 위하여 Cloud IAM 을 통해서 cloudbuild 의 service account 에 conatiner.developer 권한을 매핑하는 작업을 하단과 같이 수행한다.
export PROJECT=$(gcloud info --format='value(config.project)')
export PROJECT_NUMBER="$(gcloud projects describe \
$(gcloud config get-value core/project -q) --format='get(projectNumber)')"
gcloud projects add-iam-policy-binding ${PROJECT} \
--member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role=roles/container.developer
service account가 존재하지 않는다는 에러가 뜨면 이곳에서 설정 권한을 변경하도록 한다.
이제 본격적으로 공식문서를 참고하여 Cloud Build 를 위한 설정 파일인 cloudbuild.yaml 파일을 작성한다. Front와 Back 업데이트시 따로따로 배포해주기 위해 FrontEnd와 BackEnd 디렉토리에 모두 cloudbuild.yaml 파일을 작성하였다.
#BackEnd
steps:
### Build
- id: 'build'
name: 'gcr.io/cloud-builders/docker'
args:
- 'build'
- '-t'
- 'gcr.io/$PROJECT_ID/back:$COMMIT_SHA'
# - 'gcr.io/$PROJECT_ID/back:$TAG_NAME'
- 'BackEnd/'
### Test
### Publish
- id: 'publish'
name: 'gcr.io/cloud-builders/docker'
args:
- 'push'
- 'gcr.io/$PROJECT_ID/back:$COMMIT_SHA'
### Deploy
- id: 'deploy'
name: 'gcr.io/cloud-builders/gcloud'
env:
- 'CLOUDSDK_COMPUTE_ZONE=${_CLOUDSDK_COMPUTE_ZONE}'
- 'CLOUDSDK_CONTAINER_CLUSTER=${_CLOUDSDK_CONTAINER_CLUSTER}'
- 'KUBECONFIG=/kube/config'
entrypoint: 'bash'
args:
- '-c'
- |
cd BackEnd
CLUSTER=${_CLOUDSDK_CONTAINER_CLUSTER}
PROJECT=$$(gcloud config get-value core/project)
ZONE=${_CLOUDSDK_COMPUTE_ZONE}
gcloud container clusters get-credentials "$${CLUSTER}" \
--project "$${PROJECT}" \
--zone "$${ZONE}"
sed -i 's|gcr.io/$PROJECT_ID/back:.*|gcr.io/$PROJECT_ID/back:$COMMIT_SHA|' ./k8s/back-deploy.yaml
kubectl get ns production || kubectl create ns production
kubectl apply --namespace production -f ./k8s/
본인의 폴더구조에 따라 args
항목에 들어가는 명령어는 달라질 수 있음을 유의해야한다.
이렇게 Cloud Build 를 위한 설정 파일에 대한 준비가 되었다면 먼저 정상적으로 잘 수행되는지 파악하기 위해서 로컬 테스트를 수행해 보도록 한다. 로컬 테스트의 경우에는 gcloud builds
명령을 사용하며 TAG_NAME 이나 cloudbuild.yaml 파일에서 내부적으로 사용된 변수를 직접 넣어주어야 한다는 점을 유념해야한다. $COMMIT_SHA
나 $TAG_NAME
을 사용하면 연동된 레포지토리에서 고유 커밋 번호나 태그이름을 사용하여 이미지를 만들 수 있다.
export PROJECT_ID=$(gcloud info --format='value(config.project)')
export CLUSTER=cluster-1
export ZONE=us-central1-c
gcloud builds submit --config builder/cloudbuild.yaml --substitutions=COMMIT_SHA=xxxxxx,_CLOUDSDK_COMPUTE_ZONE=${ZONE},_CLOUDSDK_CONTAINER_CLUSTER=${CLUSTER} .
로컬 테스트 후에 정상적으로 배포가 되었는지 확인한다. 기본적으로 큰 변화가 없다면 추가 테스트를 하지 않고도 해당 pod 의 AGE 가 변경되었는지 여부를 통해서 반영 여부를 확인할 수도 있다.
kubectl get pods -n production -o wide
pod을 확인했을 때 ImagePullBackOff 에러가 나온다면 .yaml 파일에서 이미지나 태그가 올바르게 작성되었는지 확인한다. 에러와 관련해 자세한 사항은 이곳을 참고한다.
향후 Cloud Build 의 trigger 를 사용할때 cloudbuild.yaml 을 활용하기 위해 만든 cloudbuild.yaml 파일의 경로는 숙지하고 있어야 한다.
로컬 테스트를 수행해서 정상적으로 결과가 나오는 것을 확인했으면 이제 본격적으로 좀 더 CI/CD 스럽게 github 연동 작업을 수행하도록 한다. GCP 의 Cloud Build 는 github 의 App 을 이용해서 저장소 변경시에 자동으로 Cloud Build 의 trigger 를 동작 시킬 수 있다. 이를 다시 정리하면 github 의 저장소가 변경되는 이벤트 만으로도 자동으로 Cloud Build 를 수행해서 애플리케이션을 빌드/배포 할 수 있다.
이를 위해서 Google Cloud Build 라는 github application 에 대한 설치가 필요하다.(설치해보면 알겠지만 로컬에 실제 설치되는 것은 아니며 개인 github 계정에 등록되는 것) 이곳에 접속하여 install 버튼을 클릭한다.
마지막으로 trigger 를 위한 세부 설정을 한다. 예를 들어 Trigger type 을 어떤 것으로 할 것인지(Branch 가 변경될 때 반응 or Tag 가 변경될 때 반응) 나 cloudbuild.yaml 파일의 위치(github 기준으로 폴더 위치를 지정 — builder/cloudbuild-prod2.yaml 이 되어야 한다.), 맨 앞에 ‘_’ 로 시작하는 변수(cloudbuild.yaml 파일 내에서 사용한 변수)의 값 등을 넣을 수 있다.
크게 이슈가 없다면 해당 설정은 하단과 같이 해주고 Create trigger 버튼을 클릭하면 trigger 가 생성된다.
언급한대로 ‘Run a trigger’ 명령을 클릭하여 메뉴얼로 테스트를 해보면 하단과 같이 History 에서 자동으로 Build 가 수행된 것을 확인할 수 있다.
모든 구성이 다 되었으므로 마지막으로 github 의 내 저장소에서 직접 소스를 변경하여 Cloud Build 를 거쳐 실제 GKE 환경까지 애플리케이션이 배포되는 작업을 테스트 해보도록 한다.
Github 의 샘플 애플리케이션이 있는 내 저장소에 가서 FrontEnd 디렉터리에서 페이지 하나를 간단하게 변경해본다. 그리고 해당 변경 사항을 commit 한다.
현재 Cloud Build 의 trigger 변경 기준을 Tag 로 했기 때문에 commit 한다고 해서 변경이 발생되지는 않으며 github 에서 버전이 변경되었다는 의미로 tag 를 업데이트 해준다.