Cloud Run 사용해서 core 백엔드를 배포하려고 했는데 의외로 시간을 많이 잡아먹혔다.
우선 가장 큰 문제는 local 환경변수들이 Cloud run에 적용이 안되었던것이고
두번째로 큰 문제는 Cloud run 인스턴스가 Cloud SQL 접근 권한이 없어서 flyway가 실패하는 문제였다.
아래는 우리 지피티랑 리서치 하면서 해결하고 정리를 요청한 내용에 대한 산출물이다.
컨닝페이퍼로 써야겠다.
0) 상황 요약
Cloud Run에 Spring Boot 컨테이너를 배포했지만 다음 에러로 Revision 생성이 실패하고 서비스가 Ready 상태가 되지 않음.
- Cloud Run 배포 실패 메시지:
- The user-provided container failed to start and listen on the port defined provided by the PORT=8080 ...
- 상태:
- Ready=False, reason=HealthCheckContainerError
- Startup TCP probe 실패 후 컨테이너 exit(1)
핵심: 이 메시지는 원인이 아니라 결과다. (컨테이너가 8080을 열기 전에 프로세스가 죽었을 가능성이 매우 큼)
1) 1차 진단 원칙: “Revision 로그에서 첫 번째 예외”를 찾는다
Cloud Run의 “PORT 미리스닝”은 대부분 앱 부팅 중 크래시다. 따라서 해당 Revision 로그를 직접 조회해야 한다.
1.1 CLI로 Revision 로그 확인
PROJECT=<프로젝트 이름>
SERVICE=<서비스 이름>
REV=<실패한 revision 이름>
gcloud logging read \
'resource.type="cloud_run_revision"
AND resource.labels.service_name="'"$SERVICE"'"
AND resource.labels.revision_name="'"$REV"'"' \
--project "$PROJECT" \
--limit 200 \
--format 'value(textPayload)'
2) 케이스 A: Cloud SQL Admin API 403 (권한 문제)
2.1 증상 로그
403 Forbidden
Not authorized ... Possibly missing permission cloudsql.instances.get ...
status: PERMISSION_DENIED
의미:
- Cloud SQL JDBC SocketFactory가 인스턴스 메타데이터(connectSettings)를 조회해야 하는데
- 런타임 서비스 계정이 권한이 없어서 연결 정보 획득 단계에서 실패
- 결과적으로 Flyway/Hikari가 DB 연결 못 하고 앱이 죽음 → Cloud Run이 “PORT 미리스닝”으로 표시
2.2 해결 방향
- Cloud Run 런타임 서비스 계정 확인/지정
- DB가 속한 프로젝트에 서비스 계정에 roles/cloudsql.client 부여
- 필요 시 sqladmin.googleapis.com 활성화
주의: 크로스 프로젝트(서비스 프로젝트 ≠ DB 프로젝트)면, 권한 부여/서비스 활성화를 DB 프로젝트에서 해야 한다.
2.3 권장 구성(런타임 SA 명시)
RUN_PROJECT=<프로젝트 이름>
REGION=asia-northeast3
SERVICE=<서비스 이름>
SA_NAME=<SA 이름>
SA_EMAIL="${SA_NAME}@${RUN_PROJECT}.iam.gserviceaccount.com"
gcloud iam service-accounts create $SA_NAME --project $RUN_PROJECT \
--display-name "Cloud Run runtime SA"
gcloud run services update $SERVICE \
--project $RUN_PROJECT --region $REGION \
--service-account $SA_EMAIL
2.4 Cloud SQL 권한 부여(중요)
# DB가 속한 프로젝트에서 실행해야 함
SQL_PROJECT=<DB 프로젝트>
gcloud projects add-iam-policy-binding "$SQL_PROJECT" \
--member="serviceAccount:${SA_EMAIL}" \
--role="roles/cloudsql.client"
3) 케이스 B: password authentication failed for user "root" (DB 계정/비번 문제)
권한 문제를 해결하거나, 인스턴스 프로젝트가 맞춰진 뒤에 다음 단계로 터질 수 있는 대표 케이스.
3.1 증상 로그(확정)
FATAL: password authentication failed for user "root"
SQL State: 28P01
의미:
- 앱이 Postgres에 root 계정으로 접속 시도
- Cloud SQL Postgres 환경에서 보통 root는 기본 계정이 아니고(대부분 postgres),
- DB_USER가 잘못 설정됐거나
- DB_PASSWORD가 틀렸거나
- 사용자 자체가 존재하지 않음
결과:
- Flyway 연결 단계에서 실패 → 앱 종료 → Cloud Run “PORT 8080 미리스닝”
3.2 해결 방향
- Cloud SQL 인스턴스의 실제 사용자 확인
- 올바른 사용자(예: postgres 또는 앱 전용 유저)로 DB_USER 수정
- 비밀번호 재설정 또는 Secret/Env 수정
- DB 이름 존재 여부 확인 (다음 장애 예방)
3.3 Cloud SQL 사용자 확인
gcloud sql users list \
--project <프로젝트 이름> \
--instance <Cloud SQL DB 인스턴스 이름>
3.4 비밀번호 재설정(예: postgres)
gcloud sql users set-password postgres \
--project <프로젝트 이름> \
--instance <Cloud SQL DB 인스턴스 이름> \
--password '새_비밀번호'
3.5 Cloud Run 환경변수 업데이트
gcloud run services update <프로젝트 이름> \
--project <프로젝트 이름> --region asia-northeast3 \
--update-env-vars DB_USER=<DB 사용자 이름>,DB_PASSWORD='새_비밀번호'
운영에선 Secret Manager로 빼는 게 맞지만, 일단 “기동 성공”을 우선하려면 env로 빠르게 맞추는 게 효과적이다.
3.6 DB 존재 여부 확인(선택이지만 추천)
gcloud sql databases list \
--project <프로젝트 이름> \
--instance <Cloud SQL DB 인스턴스 이름>
DB가 없으면 생성:
gcloud sql databases create <DB 이름> \
--project <프로젝트 이름> \
--instance <Cloud SQL DB 인스턴스 이름>
4) “빌드가 아니라 컨테이너가 안 뜬다”의 의미
Cloud Run 배포 과정에서 “Revision 생성 실패”는 흔히 아래 패턴이다.
- 컨테이너 이미지 자체는 실행됨
- Tomcat도 8080 바인딩 직전/직후까지 감
- 하지만 Flyway/Hikari 등 부팅 과정에서 DB 연결 실패로 프로세스가 종료
- 결과적으로 Cloud Run은 “PORT=8080 리스닝 실패”로만 표현
따라서 “포트/타임아웃”을 먼저 의심하기보다는,
- Flyway/DB 연결 관련 첫 예외를 먼저 잡는 게 효율적이다.
5) 체크리스트(재발 방지용)
5.1 Cloud Run / Spring
- server.port=${PORT:8080} 확인
- server.address를 127.0.0.1로 고정하지 않기(바인딩 문제 유발)
5.2 Cloud SQL / IAM
- 런타임 서비스 계정 명시
- DB 프로젝트에 roles/cloudsql.client 부여
- (필요 시) sqladmin.googleapis.com 활성화
- 크로스 프로젝트 사용 시, 권한/서비스는 DB 프로젝트에서 처리
5.3 DB 인증
- Postgres에 root 계정 전제로 하지 않기
- DB_USER, DB_PASSWORD가 Cloud Run에 실제로 세팅됐는지 확인
- 가능하면 앱 전용 계정 사용
5.4 로깅/운영
- 실패한 Revision 로그를 CLI로 즉시 확인하는 루틴 고정
- “PORT 미리스닝”은 대부분 부팅 크래시로 간주하고 원인 로그부터 본다
6) 빠른 결론(한 줄 요약)
Cloud Run에서 “PORT=8080 미리스닝”은 대부분 **앱 부팅 중 예외로 exit(1)**이며, 이번 케이스는 단계적으로:
- (초기) Cloud SQL Admin API 접근 권한 부족(403) → 연결 메타데이터 조회 실패
- (권한/프로젝트 정리 후) DB 인증 정보가 잘못돼서 root 비번 인증 실패(28P01)