Cloud Run에서 고정 IP로 외부 API 호출하기

yeahcold·2025년 5월 29일
0

Data Engineering

목록 보기
19/20

✨ Overview

DV360 API를 호출해야 하는 FastAPI 기반 크롤러를 Cloud Run Job으로 실행하면서, 다음과 같은 문제가 발생했다.

  • 외부 API(Google Ads, DV360 등)는 IP 화이트리스트 기반 접근만 허용함.
  • Cloud Run은 기본적으로 고정 IP가 없다 → 호출할 때마다 IP가 달라짐.

결국, Cloud Run 환경에서 고정 IP로 외부 API에 접근해야 했고, 그 과정에서 다양한 시행착오와 구조적 설정이 필요했다.


🌐 목표

Cloud Run Job에서 외부 API에 접근할 때 고정 IP를 사용하고, 이 IP를 화이트리스트에 등록해 접근을 허용하는 구조 만들기.


📌 전체 아키텍처 구조

[Cloud Run Job] ➔ [VPC Connector] ➔ [Serverless VPC Access] ➔ [Cloud NAT] ➔ [고정 External IP] ➔ [External API Endpoint]
  • Cloud Run Job: FastAPI + Selenium 기반 크롤러
  • VPC Connector: Serverless 환경을 VPC와 연결
  • Cloud NAT: VPC 내부에서 나온 요청에 고정 IP 부여

🧠 문제 발생 상황

1. 외부 API 접속 실패

Cloud Run Job으로 DV360 API에 요청을 보냈는데, 403 에러 발생. 로그를 통해 보니 API 쪽 서버에서 접속 시도 자체를 차단.

2. IP 확인 결과

Google Cloud NAT가 없을 경우, Cloud Run은 매번 다른 IP로 외부 호출을 시도.

  • API 서버는 이 IP를 알 수 없기 때문에 "화이트리스트 밖"이라고 판단함.
  • curl ifconfig.me를 통해 내부적으로 확인했을 때 IP가 매번 달랐음.

⚡️ 시도한 해결 방법들

(1) Cloud Run ➔ Cloud NAT 직접 연결? (X)

  • Cloud NAT는 직접 Cloud Run에 연결할 수 없다.
  • 반드시 VPC Connector를 거쳐야만 가능하다.

(2) VPC Connector만 만들고 연결해보기? (X)

  • VPC Connector를 연결했지만 여전히 NAT가 없으면 외부 IP가 나오지 않음.
  • 에러: no external access from VPC subnet

🔄 최종 해결 구조: Cloud Run 고정 IP 아키텍처 구성

1. 고정 IP 예약

gcloud compute addresses create fixed-egress-ip \
  --project=my-project-id \
  --region=asia-northeast3

2. Cloud NAT 생성

gcloud compute routers create nat-router \
  --network=default \
  --region=asia-northeast3

gcloud compute routers nats create nat-config \
  --router=nat-router \
  --region=asia-northeast3 \
  --nat-external-ip-pool=fixed-egress-ip \
  --nat-custom-subnet-ip-ranges=default \
  --enable-logging

3. VPC Connector 생성

gcloud compute networks vpc-access connectors create run-vpc-connector \
  --network default \
  --region asia-northeast3 \
  --range 10.8.0.0/28

4. Cloud Run Job에 VPC Connector 연결

gcloud run jobs update my-crawler-job \
  --vpc-connector=run-vpc-connector \
  --vpc-egress=all-traffic

이제 Cloud Run Job의 모든 외부 트래픽은 fixed-egress-ip로 나간다.


🧰 FastAPI 환경 변수 설정

Cloud Run Job은 다음과 같은 환경변수로 호출되며 실행된다.

os.environ["PLAN_ID"] = "12345"
os.environ["PLATFORMS"] = '["dv360"]'
os.environ["OPTIONS_JSON"] = '{"dv360": {"budget": 10000000, "location": "KR", ... }}'

그리고 Python에서는 이를 다음과 같이 파싱:

plan_id = int(os.environ["PLAN_ID"])  # ❌ 이 부분에서 "UNKNOWN" 들어오면 에러 발생

✔ 해결: Spring Controller에서 PLAN_ID 항상 숫자로 설정

String planId = requestBody.containsKey("plan_id")
    ? requestBody.get("plan_id").toString()
    : String.valueOf(saveId); // saveId = Long

⚠️ 실전에서 겪은 문제들

문제 1. PLAN_ID가 문자열 'UNKNOWN'으로 들어감

  • 원인: Spring에서 plan_id 미설정 시 "UNKNOWN" 문자열 지정 → Python에서 int 파싱 실패
  • 해결: controller에서 saveId를 fallback으로 지정하여 항상 Long 사용

문제 2. VPC Connector 연결 누락

  • 증상: Job은 정상 실행되지만 외부 API 응답 없음
  • 해결: --vpc-connector--vpc-egress=all-traffic을 꼭 설정해야 NAT가 적용됨

문제 3. NAT에서 IP가 고정되지 않음

  • 원인: nat-external-ip-pool 지정 누락 → ephemeral IP 사용
  • 해결: --nat-external-ip-pool=fixed-egress-ip 명시

🚀 마무리하며

Cloud Run에서 고정 IP를 통해 외부 API 호출하는 구조는 생각보다 복잡하지만, 한번 구성해두면 확장성과 관리성이 뛰어나다. 특히 다음과 같은 상황에서 매우 유용하다.

  • 외부 서비스에서 IP 화이트리스트만 허용
  • 사내 보안망 또는 파트너사 API 연동

Cloud Run Job + VPC Connector + Cloud NAT의 조합은 이런 요구사항을 충족할 수 있는 강력한 아키텍처이다.


🔗 참고용 리소스

profile
Software Engineer

0개의 댓글