AWS RDS와 EC2만 사용해보다가 GCP 3개월 300달러 쿠폰을 사용해서 GCP를 사용해보았다. 원래도 AWS에서 사용하듯이 IaaS인 Compute Engine을 띄워서 구동해보려 했으나, 조금 더 도전해보고 싶어서 GCP에서 지원하는 PaaS를 사용해서 CI/CD를 구축했다. 이번 글에서는 GCP를 사용하면서 겪었던 트러블에 대해 작성해보려 한다.
치열한 나와 GCP의 투쟁
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
첫 시작은 Cloud SQL을 적용하고 나서의 이야기다. 로컬에서 실행할때는 jdbc의 url을 직접 적어 아이디와 패스워드로 인증을 했는데, Cloud Build에서는 Cloud SQL과 통신을 못해 빌드가 진행이 안됐다.
그래서 GCP에서 지원하는 라이브러리를 설치해서 진행을 했다. 연결시 서비스 계정의 인증정보가 필요해서 서비스 계정의 JSON 키 까지는 받았는데 공식문서에는 어떻게 사용하는지 작성이 안되있어서 결국 스택오버플로우를 통해 해결했다. application.yml에 다음과 같이 경로를 지정해주면 된다.
spring:
cloud:
gcp:
credentails:
loacation: classpath:/sound-yew-347405-a078b2cfef91.json
Unable to obtain credentials to communicate with the Cloud SQL API
다음은 인증을 지정해줬는데도 다음과 같은 오류때문에 인증이 진행 되지 않았다. 여기서 제일 많이 헤멘거 같다. 서비스 계정의 권한에 문제가 있는줄 알고 애꿏은 IAM이랑 서비스 계정 권한만 계속 만지작 걸렸는데 원인은 Cloud SQL의 경우 첫 번째 인스턴스는 root 계정의 비밀번호를 생성하지 않는데, 두 번째 인스턴스는 root 계정의 비밀번호를 생성한다고 한다.😱
그래서 root 계정의 비밀번호를 없애줬더니 잘 됐다. 시간이 제일 많이 걸렸는데 진짜 어이도 없고 맥 빠지는 트러블슈팅이였다.
Step 3/4 : COPY ${JAR_FILE} app.jar
COPY failed: no source files were specified
와일드 카드를 인식을 못해서 나는 오류였다. 그냥 파일명을 지정해줬더니 제대로 COPY가 진행됐다.
Step #0: * Exception is:
Step #0: org.gradle.execution.TaskSelectionException: Task 'clean build' not found in root project 'assignment'
Cloudbuild.yml에서 Gradle의 ARG 지정하는 부분을 그냥 문자열로 지정했더니 발생했다. 도커파일처럼 지정해줘야 한다
그 다음 문제로는 기존에 EC2에서 사용할때는 빌드하는 폴더 위치에다가 application.yml이랑 credential 파일을 올려 놨는데, Cloud BUild시 에는 어떻게 알려줘야하지? 알아보다가 시크릿 매니저를 통해서 파일을 관리 할 수 있다는 것을 알게 되어서 시크릿 매니저를 통해 application.yml과 json 키를 관리했다.
ERROR: (gcloud.app.deploy) There is a Dockerfile in the current directory, and the runtime field in /workspace/app.yaml is currently set to [runtime: java]. To use your Dockerfile to build a custom runtime, set the runtime field to [runtime: custom]. To continue using the [java] runtime, please remove the Dockerfile from this directory.
A custom runtime must have exactly one of [Dockerfile] and [cloudbuild.yaml] in the source directory
(gcloud.app.deploy) A custom runtime must have exactly one of [Dockerfile] and [cloudbuild.yaml] in the source directory; [/workspace] contains both
위에 오류를 정리하면 Dockerfile로 하면 Appengine의 runtime 환경을 custom으로 해야 하고, Dockerfile과 cloudbuild.yaml은 같은 폴더에 있다가 app engine에 배포될때는 app.yaml과 있어야 하고 app.yaml은 cloudbuild.yaml과 같이 있으면 안된다.
그리고 도커 환경에서는 App engine보다 Cloud Run이 더 낫다고 생각했고, Cloud Run같은 경우에는 요청이 없을시에는 인스턴스를 죽여놔서 돈이 안들기 때문에 Cloud Run으로 변경을 했다.
Cloud Run 구동은 그다지 어렵지 않았다. Containter Registery에 들어있는 이미지를 불러와 빌드를 시켜주기만 하면 된다. 게다가 블루 그린 전략 무중단 배포로 Cloud Run에서 알아서 배포해주기 때문에 개발에만 집중 할 수 있다.
따라서 최종 배포 인프라 환경은 다음과 같다.