Cloud/GCP
GCP VPC간 Classic VPN 생성 스크립트
달빛궁전-
2026. 4. 22. 16:13
목표
VPN간 테스트를 위해 GCP VPC 간 VPN을 구축하는 스크립트
추가적으로 Private Service Connect (PSC)연결을 위해 PSC IP 라우팅을 추가한 설치 쉘스크립트를 설명합니다.
- 사용방법
소스코드를 Cloud Shell, ADC인증을 받은 local CLI(CMD)에서 실행합니다.
쉘스크립트는 gcloud 명령을 이용하여, 인증된 GCP 프로젝트의 VPC를 조회하고, 선택된 VPC의 subnet을 조회합니다.
사용자는 각 VPC, Subnet을 선택합니다.
PSC를 테스트 할 경우 해당 PSC IP대역을 입력하면 On-premise (VPC2번측)에서 PSC대역으로 찾아가도록 자동으로 GCP VPC 경로를 추가해줍니다.
아래는 실행시 예제 화면 입니다.
- 스크립트 실행

- 스크립트 실행 완료
- PSC 자동 경로 추가
- VPN 생성확인

2. Shell Script 소스코드
#!/bin/bash
# --- 색상 정의 ---
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}======================================================${NC}"
echo -e "${BLUE} GCP VPC간 VPN 테스트를 위한 스크립트 (정적 라우팅 기반) ${NC}"
echo -e "${BLUE}======================================================${NC}"
# 1. 인프라 정보 수집
PROJECT_ID=$(gcloud config get-value project)
REGION="asia-northeast3"
VPC_LIST=($(gcloud compute networks list --format="value(name)"))
echo -e "\n${YELLOW}--- 1. VPC 네트워크 선택 ---${NC}"
for i in "${!VPC_LIST[@]}"; do echo "[$i] ${VPC_LIST[$i]}"; done
read -p "VPC 1 (Agent측) 번호 선택 [0]: " IDX1
VPC1_NAME=${VPC_LIST[${IDX1:-0}]}
read -p "VPC 2 (Onprem측) 번호 선택 [1]: " IDX2
VPC2_NAME=${VPC_LIST[${IDX2:-1}]}
echo -e "\n${YELLOW}--- 2. VPC 1 서브넷 선택 ---${NC}"
S_CIDRS1=($(gcloud compute networks subnets list --network=$VPC1_NAME --regions=$REGION --format="value(ipCidrRange)"))
S_NAMES1=($(gcloud compute networks subnets list --network=$VPC1_NAME --regions=$REGION --format="value(name)"))
for i in "${!S_CIDRS1[@]}"; do echo "[$i] ${S_NAMES1[$i]} (${S_CIDRS1[$i]})"; done
read -p "VPC 1에서 전파할 서브넷 번호들 (예: 0,1) [0]: " S_IDXS_STR
S_IDXS_STR=${S_IDXS_STR:-0}
SELECTED_CIDRS=()
IFS=',' read -ra ADDR <<< "$S_IDXS_STR"
for idx in "${ADDR[@]}"; do SELECTED_CIDRS+=("${S_CIDRS1[$idx]}") ; done
VPC1_SUBNETS_STR=$(IFS=, ; echo "${SELECTED_CIDRS[*]}")
echo -e "\n${YELLOW}--- 3. VPC 2 서브넷 선택 ---${NC}"
S_CIDRS2=($(gcloud compute networks subnets list --network=$VPC2_NAME --regions=$REGION --format="value(ipCidrRange)"))
for i in "${!S_CIDRS2[@]}"; do echo "[$i] ${S_CIDRS2[$i]}"; done
read -p "VPC 2 서브넷 번호 선택 [0]: " S_IDX2
VPC2_CIDR=${S_CIDRS2[${S_IDX2:-0}]}
echo -e "\n${YELLOW}--- 4. PSC IP 라우팅 설정 ---${NC}"
read -p "Vertex AI PSC IP (예: 100.100.100.254 / 대역 가능): " PSC_IP
# CIDR 형식이 아니면 /32 자동 추가
if [[ -n "$PSC_IP" && "$PSC_IP" != *"/"* ]]; then
PSC_IP_TF="$PSC_IP/32"
else
PSC_IP_TF="$PSC_IP"
fi
# 테라폼용 리스트 변환 (["10.1", "10.2"])
VPC1_SUBNETS_TF=$(echo $VPC1_SUBNETS_STR | sed 's/,/","/g' | sed 's/^/["/' | sed 's/$/"]/')
# 2. Terraform 생성 (세미콜론 완전 제거)
echo -e "\n${YELLOW}[3/4] Terraform 소스 생성 중...${NC}"
cat <<EOF > main.tf
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.0"
}
}
}
provider "google" {
project = "$PROJECT_ID"
region = "$REGION"
}
resource "random_string" "shared_secret" {
length = 24
special = false
}
data "google_compute_network" "vpc1" {
name = "$VPC1_NAME"
}
data "google_compute_network" "vpc2" {
name = "$VPC2_NAME"
}
resource "google_compute_address" "ip1" {
name = "vpn-ip-1"
region = "$REGION"
}
resource "google_compute_address" "ip2" {
name = "vpn-ip-2"
region = "$REGION"
}
resource "google_compute_vpn_gateway" "gw1" {
name = "vpn-gw-1"
network = data.google_compute_network.vpc1.id
region = "$REGION"
}
resource "google_compute_vpn_gateway" "gw2" {
name = "vpn-gw-2"
network = data.google_compute_network.vpc2.id
region = "$REGION"
}
resource "google_compute_forwarding_rule" "fr1_esp" {
name = "fr1-esp"
region = "$REGION"
ip_protocol = "ESP"
ip_address = google_compute_address.ip1.address
target = google_compute_vpn_gateway.gw1.id
}
resource "google_compute_forwarding_rule" "fr1_u500" {
name = "fr1-u500"
region = "$REGION"
ip_protocol = "UDP"
port_range = "500"
ip_address = google_compute_address.ip1.address
target = google_compute_vpn_gateway.gw1.id
}
resource "google_compute_forwarding_rule" "fr1_u4500" {
name = "fr1-u4500"
region = "$REGION"
ip_protocol = "UDP"
port_range = "4500"
ip_address = google_compute_address.ip1.address
target = google_compute_vpn_gateway.gw1.id
}
resource "google_compute_forwarding_rule" "fr2_esp" {
name = "fr2-esp"
region = "$REGION"
ip_protocol = "ESP"
ip_address = google_compute_address.ip2.address
target = google_compute_vpn_gateway.gw2.id
}
resource "google_compute_forwarding_rule" "fr2_u500" {
name = "fr2-u500"
region = "$REGION"
ip_protocol = "UDP"
port_range = "500"
ip_address = google_compute_address.ip2.address
target = google_compute_vpn_gateway.gw2.id
}
resource "google_compute_forwarding_rule" "fr2_u4500" {
name = "fr2-u4500"
region = "$REGION"
ip_protocol = "UDP"
port_range = "4500"
ip_address = google_compute_address.ip2.address
target = google_compute_vpn_gateway.gw2.id
}
resource "google_compute_vpn_tunnel" "t1_to_2" {
name = "tunnel1-to-2"
region = "$REGION"
peer_ip = google_compute_address.ip2.address
shared_secret = random_string.shared_secret.result
target_vpn_gateway = google_compute_vpn_gateway.gw1.id
ike_version = 2
local_traffic_selector = ["0.0.0.0/0"]
remote_traffic_selector = ["0.0.0.0/0"]
depends_on = [
google_compute_forwarding_rule.fr1_esp,
google_compute_forwarding_rule.fr1_u500,
google_compute_forwarding_rule.fr1_u4500
]
}
resource "google_compute_vpn_tunnel" "t2_to_1" {
name = "tunnel2-to-1"
region = "$REGION"
peer_ip = google_compute_address.ip1.address
shared_secret = random_string.shared_secret.result
target_vpn_gateway = google_compute_vpn_gateway.gw2.id
ike_version = 2
local_traffic_selector = ["0.0.0.0/0"]
remote_traffic_selector = ["0.0.0.0/0"]
depends_on = [
google_compute_forwarding_rule.fr2_esp,
google_compute_forwarding_rule.fr2_u500,
google_compute_forwarding_rule.fr2_u4500
]
}
resource "google_compute_route" "r1_to_2" {
name = "route-1-to-2"
network = data.google_compute_network.vpc1.name
dest_range = "$VPC2_CIDR"
priority = 1000
next_hop_vpn_tunnel = google_compute_vpn_tunnel.t1_to_2.id
}
resource "google_compute_route" "r2_to_1_subnets" {
for_each = toset($VPC1_SUBNETS_TF)
name = "route-2-to-1-sub-\${replace(each.value, "/[/.]/", "-")}"
network = data.google_compute_network.vpc2.name
dest_range = each.value
priority = 1000
next_hop_vpn_tunnel = google_compute_vpn_tunnel.t2_to_1.id
}
resource "google_compute_route" "r2_to_1_psc" {
count = "$PSC_IP_TF" != "" ? 1 : 0
name = "route-2-to-1-psc"
network = data.google_compute_network.vpc2.name
dest_range = "$PSC_IP_TF"
priority = 500
next_hop_vpn_tunnel = google_compute_vpn_tunnel.t2_to_1.id
}
EOF
echo -e "\n${YELLOW}[4/4] Terraform 시작...${NC}"
terraform init && terraform apply -auto-approve
echo -e "\n${GREEN}=== 모든 작업이 완료되었습니다. ===${NC}"
echo -e "테스트 종료 후 삭제방안: ${YELLOW}terraform destroy -auto-approve${NC}"