1. 소개
개요
많은 조직에서 서비스와 애플리케이션의 네트워크 트래픽을 보호하기 위해 경계 제어와 함께 Google Cloud의 가상 프라이빗 클라우드 (VPC) 네트워크를 사용하여 데이터 무단 반출을 방지합니다. VPC 네트워크는 Google의 프로덕션 네트워크 내에 구현되는 실제 네트워크의 가상 버전입니다. VPC 네트워크는 Compute Engine 가상 머신 (VM) 인스턴스의 연결을 제공하고, 내부 애플리케이션 부하 분산기를 위한 기본 내부 패스 스루 네트워크 부하 분산기 및 프록시 시스템을 제공하며, Cloud VPN 터널 및 Cloud Interconnect용 VLAN 연결을 사용하여 온프레미스 네트워크에 연결하고, Google Cloud 외부 부하 분산기의 트래픽을 백엔드로 분산합니다.
VM과 달리 Cloud Run 서비스는 기본적으로 특정 VPC 네트워크와 연결되지 않습니다. 이 Codelab에서는 VPC에서 발생하는 트래픽만 Cloud Run 서비스 (예: 백엔드 서비스)에 액세스할 수 있도록 인그레스 (인바운드 연결) 설정을 변경하는 방법을 보여줍니다. 또한 이 Codelab에서는 두 번째 서비스 (예: 프런트엔드 서비스)가 VPC를 통해 백엔드 Cloud Run 서비스에 액세스하고 공개 인터넷 액세스를 계속 유지하는 방법을 보여줍니다.
이 예시에서 백엔드 Cloud Run 서비스는 hello world를 반환합니다. 프런트엔드 Cloud Run 서비스는 URL을 수집하기 위해 UI에 입력란을 제공합니다. 그런 다음 프런트엔드 서비스는 해당 URL(예: 백엔드 서비스)에 GET 요청을 수행하므로 브라우저에서 서비스로의 요청이 아닌 서비스 간 요청이 됩니다. 프런트엔드 서비스가 백엔드에 성공적으로 연결되면 브라우저에 hello world 메시지가 표시됩니다. 그런 다음 https://curlmyip.org를 호출하여 프런트엔드 서비스의 IP 주소를 가져오는 방법을 알아봅니다.
학습할 내용
- VPC의 트래픽만 Cloud Run 서비스로 허용하는 방법
- 프런트엔드 서비스의 공개 인터넷 액세스를 유지하면서 Cloud Run 서비스 (예: 프런트엔드)에서 이그레스를 구성하여 내부 인그레스 전용 Cloud Run 서비스 (예: 백엔드)와 통신하는 방법
2. 설정 및 요구사항
기본 요건
- Cloud Console에 로그인되어 있습니다.
- 이전에 2세대 함수를 배포했습니다. 예를 들어 Cloud Functions 2세대 배포 빠른 시작에 따라 시작할 수 있습니다.
Cloud Shell 활성화
- Cloud Console에서 Cloud Shell 활성화
를 클릭합니다.

Cloud Shell을 처음 시작하는 경우 Cloud Shell에 대한 설명이 포함된 중간 화면이 표시됩니다. 중간 화면이 표시되면 계속 을 클릭합니다.

Cloud Shell을 프로비저닝하고 연결하는 작업은 몇 분이면 끝납니다.

이 가상 머신에는 필요한 모든 개발 도구가 로드되어 있습니다. 영구적인 5GB 홈 디렉터리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 Codelab의 작업은 대부분 브라우저에서 수행할 수 있습니다.
Cloud Shell에 연결되면 인증이 완료되었고 프로젝트가 프로젝트 ID로 설정된 것을 확인할 수 있습니다.
- Cloud Shell에서 다음 명령어를 실행하여 인증되었는지 확인합니다.
gcloud auth list
명령어 결과
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- Cloud Shell에서 다음 명령어를 실행하여 gcloud 명령어가 프로젝트를 알고 있는지 확인합니다.
gcloud config list project
명령어 결과
[core] project = <PROJECT_ID>
또는 다음 명령어로 설정할 수 있습니다.
gcloud config set project <PROJECT_ID>
명령어 결과
Updated property [core/project].
3. Cloud Run 서비스 만들기
환경 변수 설정
이 Codelab 전체에서 사용할 환경 변수를 설정할 수 있습니다.
PROJECT_ID=<YOUR_PROJECT_ID> REGION=<YOUR_REGION, e.g. us-central1> FRONTEND=frontend-with-internet BACKEND=backend SUBNET_NAME=default
백엔드 Cloud Run 서비스 만들기
먼저 소스 코드의 디렉터리를 만들고 해당 디렉터리로 cd합니다.
mkdir -p egress-private-codelab/frontend-w-internet egress-private-codelab/backend && cd egress-private-codelab/backend
그런 다음 다음 콘텐츠를 포함한 `package.json`` 파일을 만듭니다.
{
"name": "backend-service",
"version": "1.0.0",
"description": "",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "^4.18.1"
}
}
다음으로 아래 콘텐츠를 포함한 index.js 소스 파일을 만듭니다. 이 파일에는 서비스의 진입점이 포함되어 있으며 앱의 기본 로직이 포함되어 있습니다.
const express = require('express');
const app = express();
app.use(express.urlencoded({ extended: true }));
app.get('/', function (req, res) {
res.send("hello world");
});
const port = parseInt(process.env.PORT) || 8080;
app.listen(port, () => {
console.log(`helloworld: listening on port ${port}`);
});
마지막으로 다음 명령어를 실행하여 Cloud Run 서비스를 배포합니다.
gcloud run deploy $BACKEND --source . --allow-unauthenticated --region $REGION
프런트엔드 Cloud Run 서비스 만들기
프런트엔드 디렉터리로 이동합니다.
cd ../frontend-w-internet
그런 다음 다음 콘텐츠를 포함한 package.json 파일을 만듭니다.
{
"name": "frontend",
"version": "1.0.0",
"description": "",
"scripts": {
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.6.6",
"express": "^4.18.2",
"htmx.org": "^1.9.10"
}
}
다음으로 아래 콘텐츠를 포함한 index.js 소스 파일을 만듭니다. 이 파일에는 서비스의 진입점이 포함되어 있으며 앱의 기본 로직이 포함되어 있습니다.
const express = require("express");
const app = express();
const port = 8080;
const path = require('path');
const axios = require('axios');
// serve static content (index.html) using
// built-in middleware function in Express
app.use(express.static('public'));
app.use(express.urlencoded({ extended: true }));
// this endpoint receives a URL in the post body
// and then makes a get request to that URL
// results are sent back to the caller
app.post('/callService', async (req, res) => {
const url = req.body.url;
let message = "";
try {
console.log("url: ", url);
const response = await axios.get(url);
message = response.data;
} catch (error) {
message = error.message;
console.error(error.message);
}
res.send(`
${message}
<p>
</p>
`);
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
index.html 파일의 공개 디렉터리를 만듭니다.
mkdir public touch public/index.html
다음이 포함되도록 index.html을 업데이트합니다.
<html>
<script
src="https://unpkg.com/htmx.org@1.9.10"
integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC"
crossorigin="anonymous"
></script>
<body>
<div style="margin-top: 100px; margin-left: 100px">
<h1>I'm the Request Tester service on the Internet</h1>
<form hx-trigger="submit" hx-post="/callService" hx-target="#zen">
<label for="url"> URL:</label>
<input
style="width: 308px"
type="text"
id="url"
name="url"
placeholder="The backend service URL"
required
/>
<button hx-indicator="#loading" type="submit">Submit</button>
<p></p>
<span class="htmx-indicator" id="loading"> Loading... </span>
<div id="zen" style="white-space: pre-wrap"></div>
<p></p>
</form>
</div>
</body>
</html>
마지막으로 다음 명령어를 실행하여 Cloud Run 서비스를 배포합니다.
gcloud run deploy $FRONTEND --source . --allow-unauthenticated --region $REGION
백엔드 서비스 호출
이 섹션에서는 두 개의 Cloud Run 서비스를 성공적으로 배포했는지 확인합니다.
웹브라우저에서 프런트엔드 서비스의 URL(예: https://frontend-your-hash-uc.a.run.app/)을 엽니다.
텍스트 상자에 백엔드 서비스의 URL을 입력합니다. 이 요청은 브라우저가 아닌 프런트엔드 Cloud Run 인스턴스에서 백엔드 Cloud Run 서비스로 라우팅됩니다.
'hello world'가 표시됩니다.
4. 내부 인그레스 전용으로 백엔드 서비스 설정
다음 gcloud 명령어를 실행하여 Cloud Run 서비스를 비공개 네트워크에 통합할 수 있습니다.
gcloud run services update $BACKEND --ingress internal --region $REGION
프런트엔드 서비스에서 백엔드 서비스를 호출하려고 하면 404 오류가 발생합니다. 프런트엔드 Cloud Run 서비스 발신 연결 (또는 이그레스)이 먼저 인터넷으로 이동하므로 Google Cloud는 요청의 출처를 알 수 없습니다.
5. VPC에 액세스하도록 프런트엔드 서비스 구성
이 섹션에서는 VPC를 통해 백엔드 서비스와 통신하도록 프런트엔드 Cloud Run 서비스를 구성합니다.
이렇게 하려면 프런트엔드 Cloud Run 서비스에 직접 VPC 이그레스를 추가하여 VPC 네트워크의 내부 IP 주소에 연결할 수 있도록 해야 합니다. 그런 다음 비공개 IP에 대한 요청만 VPC로 라우팅되도록 이그레스를 구성합니다. 이 구성을 사용하면 프런트엔드가 공개 인터넷에 계속 연결할 수 있습니다. 다른 Cloud Run 서비스에서 요청 수신에 관한 문서에서 자세히 알아보세요.
직접 VPC 이그레스 구성
먼저 이 명령어를 실행하여 프런트엔드 서비스에서 직접 VPC 이그레스를 사용합니다.
gcloud beta run services update $FRONTEND \ --network=$SUBNET_NAME \ --subnet=$SUBNET_NAME \ --vpc-egress=private-ranges-only \ --region=$REGION
이제 프런트엔드 서비스가 VPC에 액세스할 수 있는지 확인할 수 있습니다.
gcloud beta run services describe $FRONTEND \ --region=$REGION
다음과 비슷한 출력이 표시됩니다.
VPC access:
Network: default
Subnet: default
Egress: private-ranges-only
비공개 Google 액세스 사용 설정
다음으로 다음 명령어를 실행하여 서브넷에서 비공개 Google 액세스를 사용 설정합니다.
gcloud compute networks subnets update $SUBNET_NAME \ --region=$REGION \ --enable-private-ip-google-access
다음 명령어를 실행하여 비공개 Google 액세스가 사용 설정되었는지 확인할 수 있습니다.
gcloud compute networks subnets describe $SUBNET_NAME \ --region=$REGION \ --format="get(privateIpGoogleAccess)"
run.app URL의 Cloud DNS 영역 만들기
마지막으로 Google Cloud에서 run.app URL을 내부 IP 주소로 처리할 수 있도록 run.app URL의 Cloud DNS 영역을 만듭니다.
이전 단계에서 비공개 범위 전용으로 직접 VPC 이그레스를 구성했습니다. 즉, 대상이 내부 IP인 경우 프런트엔드 서비스의 아웃바운드 연결은 VPC 네트워크로만 이동합니다. 하지만 백엔드 서비스는 공개 IP로 확인되는 run.app URL을 사용합니다.
이 단계에서는 내부 IP 주소로 인식되는 private.googleapis.com IP 주소 범위로 확인되도록 run.app URL의 Cloud DNS 영역을 만듭니다. 이제 이러한 범위에 대한 모든 요청은 VPC 네트워크를 통해 라우팅됩니다.
다음과 같이 할 수 있습니다. https://cloud.google.com/run/docs/securing/private-networking#from-other-services
# do not include the https:// in your DNS Name # for example: backend-<hash>-uc.a.run.app DNS_NAME=<your backend service URL without the https://> gcloud dns --project=$PROJECT_ID managed-zones create codelab-backend-service \ --description="" \ --dns-name="a.run.app." \ --visibility="private" \ --networks=$SUBNET_NAME gcloud dns --project=$PROJECT_ID record-sets create $DNS_NAME. \ --zone="codelab-backend-service" \ --type="A" \ --ttl="60" \ --rrdatas="199.36.153.8,199.36.153.9,199.36.153.10,199.36.153.11"
이제 웹사이트의 백엔드 서비스에 연결하려고 하면 'hello world'가 반환됩니다.
https://curlmyip.org/를 사용하여 인터넷에 연결하려고 하면 IP 주소가 표시됩니다.
6. 문제 해결
설정이 올바르게 구성되지 않은 경우 발생할 수 있는 오류 메시지는 다음과 같습니다.
getaddrinfo ENOTFOUND backend-your-hash-uc.a.run.app오류가 발생하면 DNS A 레코드에 'https://'를 추가하지 않았는지 확인합니다.- 영역을 구성한 후 백엔드에 액세스하려고 할 때 404 오류가 발생하면 전역 run.app 레코드의 캐시가 만료될 때까지 기다리거나 (예: 6시간) 다음 명령어를 실행하여 새 버전을 만들 수 있습니다 (따라서 캐시 지우기).
gcloud beta run services update $FRONTEND --network=$SUBNET_NAME --subnet=$SUBNET_NAME --vpc-egress=private-ranges-only --region=$REGION
7. 축하합니다.
Codelab을 완료하신 것을 축하드립니다.
Cloud Run의 비공개 네트워킹에 관한 문서를 검토하는 것이 좋습니다.
학습한 내용
- VPC의 트래픽만 Cloud Run 서비스로 허용하는 방법
- 프런트엔드 서비스의 공개 인터넷 액세스를 유지하면서 Cloud Run 서비스 (예: 프런트엔드)에서 이그레스를 구성하여 내부 인그레스 전용 Cloud Run 서비스 (예: 백엔드)와 통신하는 방법
8. 삭제
의도치 않은 요금이 청구되지 않도록 하려면(예: 이 Cloud Run 서비스가 무료 등급의 월별 Cloud Run 호출 할당량보다 더 많이 호출되는 경우) Cloud Run 서비스를 삭제하거나 2단계에서 만든 프로젝트를 삭제하면 됩니다.
Cloud Run 서비스를 삭제하려면 https://console.cloud.google.com/functions/의 Cloud Run Cloud Console로 이동하여 이 Codelab에서 만든 $FRONTEND 및 $BACKEND 서비스를 삭제합니다.
전체 프로젝트를 삭제하려면 https://console.cloud.google.com/cloud-resource-manager로 이동하여 2단계에서 만든 프로젝트를 선택하고 삭제를 선택합니다. 프로젝트를 삭제하면 Cloud SDK에서 프로젝트를 변경해야 합니다. gcloud projects list를 실행하여 사용 가능한 모든 프로젝트의 목록을 볼 수 있습니다.