개인 프로젝트에서 GCP의 Cloud Run을 활용하여 얻은 경험을 나누고자 합니다. 이 글에서는 기본적인 설정, 배포, 관리, 그리고 트러블 슈팅에 중점을 두어 설명하겠습니다.
먼저 Google Cloud Console에 로그인하고 결제 수단을 등록합니다.
결제 수단 등록은 Google Cloud 리소스 사용 시 중복 생성을 방지하고 첫 3개월은 무료 크레딧을 제공받아 운영할 수 있도록 도와줍니다. 무료 크레딧 기간 종료 후 자동으로 서비스가 종료되어 과금되지 않습니다. 이 과정을 마치면 프로젝트와 해당 프로젝트의 고유 ID가 생성됩니다.
로컬에서 shell script를 사용할 수 있도록 필요한 권한을 설정합니다. 소유자는 GCP의 기본 기능에 대한 권한이 이미 부여되어 있어, 추후 Artifact Registry와 같은 기능을 사용할 때 별도의 권한 부여 없이 이용할 수 있습니다.
// gcloud 설치: https://cloud.google.com/sdk/docs/install?hl=ko
> gcloud init
> Pick configuration to use:
[x] Create a new configuration
> Choose the account you would like to use to perform operations for this configuration:
[x] Log in with a new account
// GCP 계정 로그인
> You are logged in as: [계정].
Pick cloud project to use:
[1] [My First Project의 id]
GCP 관리 콘솔 > Cloud Run > "서비스 만들기"를 클릭합니다.
샘플 컨테이너로 테스트
버튼을 클릭해 샘플 이미지를 등록합니다.
Cloud Run은 컨테이너 기반으로 서비스를 제공합니다. 현재는 프로젝트 docker 이미지를 생성하지 않았기 때문에 샘플로 제공하는 이미지를 사용해 배포해봅니다.
가장 가까운 도쿄로 등급 1 리전을 선택합니다. 서울 리전도 가능하지만, 나중에 GCP에서 무료로 제공하는 기능을 활용하기 위해 도쿄를 선택합니다.
등급 2 리전부터는 SSL 인증서나 HTTPS 프로토콜을 직접 설정해야 합니다. 서울 리전을 선택했다면 추후 Let's Encrypt를 이용하여 인증서를 발급하고 Cloud Load Balancer를 사용해보세요.
다음으로 서비스가 운영될 수 있는 최소 스펙으로 설정합니다.
만들기 클릭 후 상태 체크와 제공하는 URL에 접속해 페이지가 제대로 뜬다면 성공입니다.
Artifact Registry를 활용하여 Docker 이미지를 효과적으로 관리하는 방법에 대해 알아보겠습니다. GCP의 통합된 서비스로서, 이미지 관리, 권한 관리, 그리고 가격 측면에서 큰 장점을 가지고 있습니다.
GCP 관리 콘솔 > Artifact Registry > 저장소 만들기를 선택합니다. 이동 후 이름을 gar-my-project
, 리전은 서울
로 선택하고 나머지는 기본값을 지정했습니다.
create next app을 이용해 예제 프로젝트를 생성합니다. Dockerfile을 업데이트하여 Cloud Run이 애플리케이션을 실행하기 위한 설정을 추가합니다. 기본 포트를 8080
으로 변경하고, standalone 옵션도 추가합니다.
...
// nextjs docker example
// https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
ENV HOSTNAME=0.0.0.0
ENV PORT=8080
EXPOSE 8080
CMD ["node", "server.js"]
GAR에 이미지를 푸시할 때 특정 형식을 따라야 합니다. [GAR_HOST]/[GCP_PROJECT_ID]/[GAR_REPOSITORY_NAME]/[DOCKER_IMAGE_NAME]
형식을 유지하세요.
간편하게 GAR 프로젝트에 진입하면 bread crumb 옆 복사 버튼을 이용할 수 있습니다.
> docker build ( m1 silicon의 경우 )
docker buildx build --platform linux/amd64 -t [GAR 폼]/[이미지 name] .
docker buildx build --platform linux/amd64 -t asia-northeast3-docker.pkg.dev/avian-hangout-407706/gar-my-project/next-app .
> docker push (to GAR)
docker push [GAR 폼]/[이미지 name][:latest]
docker push asia-northeast3-docker.pkg.dev/avian-hangout-407706/gar-my-project/next-app:latest
이제 샘플 이미지로 만든 Cloud Run 프로젝트가 아니라 실제 프로젝트를 build 한 이미지로 배포하는 과정입니다.
> GCP deploy
gcloud run deploy my-project --image [GAR 폼]/[이미지 name]:latest --region=[배포 리전]
gcloud run deploy my-project --image asia-northeast3-docker.pkg.dev/avian-hangout-407706/gar-my-project/next-app:latest --region=asia-northeast1
성공 메세지와 함께 제공되는 URL이 잘 열리는지 확인하면 성공입니다.
실제 애플리케이션 관리 방법과 활용법을 공유합니다.
만약 배포 후 버그가 발생해 hotfix를 하려 한다면, 일반적으로 git의 태그나 버전을 롤백, build 후 deploy 과정을 거쳐야 할 겁니다.
cloud run을 이용해 관리한다면 버그가 발생한 이미지 직전의 이미지로 트래픽을 돌리면 10초 내에 이전 버전으로 롤백이 가능합니다.
배포 이미지의 tag를 이용해 어떤 이미지인 지 판단할 수 있습니다.
저 같은 경우 revalidate 옵션을 이용해 부하 테스트를 진행하는데, 쉽게 이미지를 바꾸며 테스트가 가능했습니다.
또 50%씩 트래픽을 나누어 다양한 시도를 할 수 있을 것 같아요.
서비스에 대한 트래픽이 변할 때, 자동으로 스케일링되지만, 트래픽 패턴에 따라 스케일링을 최적화하는 작업을 수행할 수 있습니다. 이를 통해 자원을 효율적으로 활용할 수 있습니다.
예를 들어, 트래픽이 몰리는 특정 시간대를 알고 있다면, 미리 최소 인스턴스 수를 늘려 배포해 대비할 수 있습니다.
애플리케이션을 프론트엔드와 백엔드로 나눠 배포하는 경우, Cloud Run에서 이미지를 수신하고 트래픽을 받아야 하는 단계에서 문제가 발생할 수 있습니다. 이로 인해 제공된 URL로 진입 시 에러가 발생하고 배포가 실패하는 경우가 있습니다. 아래는 이러한 상황에 대한 트러블 슈팅 방법과 주의사항입니다.
백엔드 서버와 프론트엔드 서버를 동시에 배포해야 하는 경우, 다음 주의사항을 고려하세요.
프론트 서버를 배포하기 전에 백엔드 서버를 먼저 띄워놓으세요. 이를 통해 프론트 서버의 BASE_DOMAIN
에서 기대하는 트래픽을 백엔드 서버에서 정상적으로 받을 수 있습니다.
백엔드 서버는 DB 등의 연결이 필요한 경우, 배포 전에 해당 연결이 설정되어 있는지 확인하세요.
위에서 겪는 이슈는 제공되는 로그를 통해 에러 로그를 확인 후 해결할 수 있습니다. 하지만 가장 정확한 방법은 로컬에서 서비스를 연결해 보는 방법입니다. (컨테이너 기반 서비스의 장점)
특히 React Server Component를 사용한다면 로그를 봐도 어디서 에러가 나는지 감이 잘 안 올 수 있는데요, 이럴 때 local 환경에서 테스트해보세요.
// local에 이미지가 없다면, GAR에서 가져온다.
docker pull [GAR 폼]/[이미지 name]:latest
// local 테스트의 경우 PORT를 각 환경에 맞춰 실행합니다.
docker run -p 3000:3000 [GAR 폼]/[이미지 name]:latest
// http://localhost:3000
Cloud Run을 활용해 프로젝트 배포, 관리 방법, 트러블 슈팅에 대해 알아봤습니다. 지금은 이미지를 빌드하고 배포하는 기본적인 단계를 살펴보았지만, GCP에서 제공하는 다양한 기능을 더한다면 더 복잡한 프로젝트도 효율적으로 구성할 수 있을 것 같습니다.
기회가 된다면 다음 주제로도 글을 작성해 보려고 해요.