대상 클러스터에 Private Service Connect 구성

이 페이지에서는 대상 PostgreSQL용 AlloyDB 클러스터의 비공개 IP 주소를 사용하여 Oracle을 PostgreSQL용 AlloyDB 워크로드로 마이그레이션하도록 Database Migration Service를 설정하는 방법을 설명합니다. 비공개 연결을 사용하면 Database Migration Service가 인터넷을 통하거나 외부 IP 주소를 사용하지 않고도 서비스에 액세스할 수 있습니다.

Database Migration Service는 Private Service Connect를 사용하여 비공개 IP 주소를 통해 PostgreSQL용 AlloyDB 클러스터에 연결합니다. Private Service Connect를 사용하면 대상 데이터베이스를 수신 보안 연결에 노출하고 데이터베이스에 액세스할 수 있는 사용자를 제어할 수 있습니다.

PSC 지원 PostgreSQL용 AlloyDB 클러스터의 비공개 서비스 연결

Private Service Connect가 사용 설정된 PostgreSQL용 AlloyDB 대상 인스턴스를 만드는 경우 추가 네트워크 설정 없이 비공개 IP 연결을 사용할 수 있습니다. 대상 데이터베이스 연결 프로필을 만들 때만 다음을 확인하면 됩니다.

  • 대상의 호스트 이름 대신 PostgreSQL용 AlloyDB 클러스터의 DNS 레코드를 사용합니다.

  • Google Cloud CLI 또는 API를 통한 프로그래매틱 액세스만 해당: 요청에서 대상의 서비스 연결을 명시적으로 지정합니다. Google Cloud 콘솔에서 연결 프로필을 만들 때 데이터베이스 이전 서비스에서 자동으로 처리합니다.

PSC를 사용 설정하지 않은 PostgreSQL용 AlloyDB 클러스터의 비공개 서비스 연결

PostgreSQL용 AlloyDB 클러스터에 Private Service Connect를 사용하여 서비스를 노출하려면 프로젝트에서 서비스 연결을 만듭니다. Private Service Connect 프로듀서 설정 만들기 섹션의 예시 gcloud 및 Terraform 스크립트를 사용하여 필요한 리소스를 만들 수 있습니다.

하나의 방어 가상 머신 (VM)이 네트워킹 요구사항을 충족하지 못하는 경우 네트워크 제작자 설정에 인스턴스 그룹을 구성합니다. 자세한 내용은 관리 서비스의 네트워크 연결을 참고하세요.

다음 다이어그램은 Database Migration Service에서 PostgreSQL용 AlloyDB 클러스터에 대한 비공개 연결을 설정하는 데 사용하는 다양한 컴퓨팅 및 네트워킹 리소스를 보여줍니다.

Private Service Connect 설정

Database Migration Service 작업자는 Database Migration Service 마이그레이션을 담당하는 내부 처리 단위입니다. 나가는 Private Service Connect 전달 규칙을 사용하여 작업자에서 방화벽 VM이 있는 VPC 네트워크로 트래픽을 전송합니다.

스크립트를 통해 만들 수 있는 주요 리소스는 다음과 같습니다.

  • 서비스 연결: 트래픽을 대상 서비스로 전달하여 서비스를 노출하는 리소스입니다. 다이어그램에서 대상 서비스는 수신 전달 규칙입니다.
  • 수신 전달 규칙: 서비스 첨부파일에서 수신 트래픽을 전용 대상 (예: VM 또는 인스턴스 그룹)으로 라우팅하는 트래픽 전달자입니다. 다이어그램에서 규칙은 트래픽을 배스천 VM으로 전달합니다.
  • 배스천 VM: 두 개의 네트워크 인터페이스 컨트롤러 (NIC)가 있는 VM으로, 그중 하나는 전용 Private Service Connect 네트워크에 연결되고 다른 하나는 PostgreSQL용 AlloyDB 클러스터가 피어링된 네트워크에 연결됩니다. 배스천은 연결을 안전하게 전달하는 데 사용되는 Dante SOCKS 서버를 실행합니다. 예시 스크립트는 Private Service Connect 네트워크에 전용 네트워크와 서브넷을 자동으로 만듭니다.

서비스 연결을 사용하여 서비스를 게시하는 데 사용하는 Google Cloud 프로젝트가 서비스 프로듀서입니다. 서비스 소비자는 Database Migration Service입니다. Private Service Connect, 설정, 아키텍처에 관한 자세한 내용은 Private Service Connect 문서를 참고하세요.

Private Service Connect 프로듀서 설정 만들기

다음 스크립트를 사용하여 Private Service Connect 설정을 만들고 대상 PostgreSQL용 AlloyDB 클러스터에 연결할 수 있습니다. 연결 설정 중에 문제가 발생하면 연결 문제 해결 페이지를 참고하세요.

gcloud

다음 bash 스크립트는 Google Cloud CLI를 사용하여 대상 데이터베이스의 Private Service Connect 프로듀서 설정을 만듭니다. 일부 기본값(예: Private Service Connect 서브넷 CIDR 범위)은 조정해야 할 수 있습니다.

#!/bin/bash

# Create the VPC network for the Database Migration Service Private Service Connect.
gcloud compute networks create dms-psc-vpc \
--project=PROJECT_ID \
--subnet-mode=custom

# Create a subnet for the Database Migration Service Private Service Connect.
gcloud compute networks subnets create dms-psc-REGION \
--project=PROJECT_ID \
--range=10.0.0.0/16 --network=dms-psc-vpc \
--region=REGION

# Create a router required for the bastion to be able to install external
# packages (for example, Dante SOCKS server):
gcloud compute routers create ex-router-REGION \
--network dms-psc-vpc \
--project=PROJECT_ID \
--region=REGION

gcloud compute routers nats create ex-nat-REGION \
--router=ex-router-REGION \
--auto-allocate-nat-external-ips \
--nat-all-subnet-ip-ranges \
--enable-logging \
--project=PROJECT_ID \
--region=REGION

# Create the bastion VM.
gcloud compute instances create BASTION \
    --project=PROJECT_ID \
    --zone=ZONE \
    --image-family=debian-11 \
    --image-project=debian-cloud \
    --network-interface subnet=dms-psc-REGION,no-address \
    --network-interface subnet=DB_SUBNETWORK,no-address \
    --metadata=startup-script='#! /bin/bash

# Route the private IP address using the gateway of the database subnetwork.
# Find the gateway for the relevant subnetwork go to the VPC network page
# in the Google Cloud console. Click VPC networks and select the database VPC
# to see the details.
ip route add ALLOYDB_INSTANCE_PRIVATE_IP via DB_SUBNETWORK_GATEWAY

# Install Dante SOCKS server.
apt-get install -y dante-server

# Create the Dante configuration file.
touch /etc/danted.conf

# Create a proxy.log file.
touch proxy.log

# Add the following configuration for Dante:
cat > /etc/danted.conf << EOF
logoutput: /proxy.log
user.privileged: proxy
user.unprivileged: nobody

internal: 0.0.0.0 port = PORT
external: ens5

clientmethod: none
socksmethod: none

client pass {
        from: 0.0.0.0/0
        to: 0.0.0.0/0
        log: connect error disconnect
}
client block {
        from: 0.0.0.0/0
        to: 0.0.0.0/0
        log: connect error
}
socks pass {
        from: 0.0.0.0/0
        to: ALLOYDB_INSTANCE_PRIVATE_IP/32
        protocol: tcp
        log: connect error disconnect
}
socks block {
        from: 0.0.0.0/0
        to: 0.0.0.0/0
        log: connect error
}
EOF

# Start the Dante server.
systemctl restart danted

tail -f proxy.log'

# Create the target instance from the created bastion VM.
gcloud compute target-instances create bastion-ti-REGION \
--instance=BASTION \
--project=PROJECT_ID \
--instance-zone=ZONE \
--network=dms-psc-vpc

# Create a forwarding rule for the backend service.
gcloud compute forwarding-rules create dms-psc-forwarder-REGION \
--project=PROJECT_ID \
--region=REGION \
--load-balancing-scheme=internal \
--network=dms-psc-vpc \
--subnet=dms-psc-REGION \
--ip-protocol=TCP \
--ports=all \
--target-instance=bastion-ti-REGION \
--target-instance-zone=ZONE

# Create a TCP NAT subnet.
gcloud compute networks subnets create dms-psc-nat-REGION-tcp \
--network=dms-psc-vpc \
--project=PROJECT_ID \
--region=REGION \
--range=10.1.0.0/16 \
--purpose=private-service-connect

# Create a service attachment.
gcloud compute service-attachments create dms-psc-svc-att-REGION \
--project=PROJECT_ID \
--region=REGION \
--producer-forwarding-rule=dms-psc-forwarder-REGION \
--connection-preference=ACCEPT_MANUAL \
--nat-subnets=dms-psc-nat-REGION-tcp

# Create a firewall rule allowing the Private Service Connect NAT subnet.
# access the Private Service Connect subnet
gcloud compute \
--project=PROJECT_ID firewall-rules create dms-allow-psc-tcp \
--direction=INGRESS \
--priority=1000 \
--network=dms-psc-vpc \
--action=ALLOW \
--rules=all \
--source-ranges=10.1.0.0/16 \
--enable-logging

# Print out the created service attachment.
gcloud compute service-attachments describe dms-psc-svc-att-REGION \
--project=PROJECT_ID \
--region=REGION

다음을 바꿉니다.

  • PROJECT_ID: Private Service Connect 프로듀서 설정을 만드는 프로젝트입니다.
  • REGION: Private Service Connect 프로듀서 설정을 만드는 리전입니다.
  • ZONE: REGION 내의 영역으로, 모든 영역 리소스 (예: 배스천 VM)를 만드는 영역입니다.
  • BASTION: 만들 바스천 VM입니다.
  • DB_SUBNETWORK: 트래픽이 전달될 서브네트워크입니다. 하위 네트워크는 PostgreSQL용 AlloyDB 클러스터에 액세스할 수 있어야 합니다.
  • DB_SUBNETWORK_GATEWAY: 하위 네트워크의 IPv4 게이트웨이입니다.
  • PORT: 배스천이 기본 데이터베이스를 노출하는 데 사용할 포트입니다.
  • ALLOYDB_INSTANCE_PRIVATE_IP: PostgreSQL용 AlloyDB 클러스터의 비공개 IP 주소입니다.

Terraform

다음 파일을 Terraform 모듈에서 사용하여 대상 데이터베이스의 Private Service Connect 프로듀서 설정을 만들 수 있습니다. Private Service Connect 서브넷 CIDR 범위와 같은 일부 기본값은 조정해야 할 수 있습니다.

variables.tf:

variable "project_id" {
  type        = string
  description = <<DESC
The Google Cloud project in which the setup is created. This should be the same project as
the one that the AlloyDB for PostgreSQL cluster belongs to.
DESC
}

variable "region" {
  type        = string
  description = "The Google Cloud region in which you create the Private Service Connect
regional resources."
}

variable "zone" {
  type        = string
  description = <<DESC
The Google Cloud zone in which you create the Private Service Connect zonal resources
(should be in the same region as the one specified in the "region" variable).
DESC
}

variable "primary_instance_private_ip" {
  type = string
  description = "The cluster's primary instance private IP"
}

variable "port" {
  type        = string
  description = "The port that the bastion will use to expose the underlying database."
  default     = "5432"
}

variable "alloydb_cluster_network" {
  type        = string
  description = <<DESC
The VPC to which the AlloyDB for PostgreSQL cluster is peered. This is where the bastion will
forward connections to (the destination database needs to be accessible in this VPC).
DESC
}

main.tf:

/* To execute the call:
terraform apply
-var="project_id=PROJECT_ID"
-var="region=REGION"
-var="zone=ZONE"
-var="primary_instance_private_ip=PRIMARY_INSTANCE_PRIVATE_IP"
-var="port=PORT"
-var="alloydb_cluster_network=ALLOYDB_CLUSTER_NETWORK" */

# Needed for getting the IPv4 gateway of the subnetwork for the database.

data "google_compute_subnetwork" "db_network_subnet" {
  name    = var.alloydb_cluster_network
  project = var.project_id
  region  = var.region
}

resource "google_compute_network" "psc_sp_network" {
  name                    = "dms-psc-network"
  project                 = var.project_id
  auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "psc_sp_subnetwork" {
  name    = "dms-psc-subnet"
  region  = var.region
  project = var.project_id

  network = google_compute_network.psc_sp_network.id
  # CIDR range can be lower.

  ip_cidr_range = "10.0.0.0/16"
}

resource "google_compute_subnetwork" "psc_sp_nat" {
  provider = google-beta
  name     = "dms-psc-nat"
  region   = var.region
  project  = var.project_id

  network = google_compute_network.psc_sp_network.id
  purpose = "PRIVATE_SERVICE_CONNECT"
  # CIDR range can be lower.

  ip_cidr_range = "10.1.0.0/16"
}

resource "google_compute_service_attachment" "psc_sp_service_attachment" {
  provider = google-beta
  name     = "dms-psc-svc-att"
  region   = var.region
  project  = var.project_id

  enable_proxy_protocol = false
  connection_preference = "ACCEPT_MANUAL"
  nat_subnets           = [google_compute_subnetwork.psc_sp_nat.id]
  target_service        = google_compute_forwarding_rule.psc_sp_target_direct_rule.id
}

resource "google_compute_forwarding_rule" "psc_sp_target_direct_rule" {
  name       = "dms-psc-fr"
  region     = var.region
  project    = var.project_id
  network    = google_compute_network.psc_sp_network.id
  subnetwork = google_compute_subnetwork.psc_sp_subnetwork.id

  load_balancing_scheme = "INTERNAL"
  ip_protocol           = "TCP"
  all_ports             = true

  target = google_compute_target_instance.psc_sp_target.id

}

resource "google_compute_target_instance" "psc_sp_target" {
  provider = google-beta
  name     = "dms-psc-fr-target"
  zone     = var.zone
  instance = google_compute_instance.psc_sp_bastion.id
  network  = google_compute_network.psc_sp_network.id
}

resource "google_compute_instance" "psc_sp_bastion" {
  name           = "dms-psc-cloud-sql-bastion"
  project        = var.project_id
  machine_type   = "e2-medium"
  zone           = var.zone
  can_ip_forward = true

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-11"
    }
  }

  # The incoming NIC defines the default gateway which must be the Private Service Connect subnet.

  network_interface {
    network    = google_compute_network.psc_sp_network.id
    subnetwork = google_compute_subnetwork.psc_sp_subnetwork.id
  }

  # The outgoing NIC which is on the same network as the AlloyDB for PostgreSQL cluster.

  network_interface {
    network = data.google_compute_subnetwork.db_network_subnet.network
  }

  metadata_startup_script = <<SCRIPT

#!/bin/bash

# Route the private IP address of the database using the gateway of the database subnetwork.

# To find the gateway for the relevant subnetwork, go to the VPC network page

# in the Google Cloud console. Click VPC networks, and select the database VPC

# to see the details.

ip route add ${var.primary_instance_private_ip} \
via ${data.google_compute_subnetwork.db_network_subnet.gateway_address}

# Install Dante SOCKS server.

apt-get install -y dante-server

# Create the Dante configuration file.

touch /etc/danted.conf

# Create a proxy.log file.

touch proxy.log

# Add the following configuration for Dante:

cat > /etc/danted.conf << EOF
logoutput: /proxy.log
user.privileged: proxy
user.unprivileged: nobody

internal: 0.0.0.0 port = ${var.port}
external: ens5

clientmethod: none
socksmethod: none

client pass {
        from: 0.0.0.0/0
        to: 0.0.0.0/0
        log: connect error disconnect
}
client block {
        from: 0.0.0.0/0
        to: 0.0.0.0/0
        log: connect error
}
socks pass {
        from: 0.0.0.0/0
        to: ${var.primary_instance_private_ip}/32
        protocol: tcp
        log: connect error disconnect
}
socks block {
        from: 0.0.0.0/0
        to: 0.0.0.0/0
        log: connect error
}
EOF

# Start the Dante server.

systemctl restart danted

tail -f proxy.log

SCRIPT
}

# Required firewall rules:

/* Firewall rule allowing the Private Service Connect NAT subnet to access
the Private Service Connect subnet. */
resource "google_compute_firewall" "psc_sp_in_fw" {
  name    = "dms-psc-ingress-nat-fw"
  project = var.project_id
  network = google_compute_network.psc_sp_network.id

  log_config {
    metadata = "INCLUDE_ALL_METADATA"
  }

  allow {
    protocol = "all"
  }

  priority  = 1000
  direction = "INGRESS"
  source_ranges = [google_compute_subnetwork.psc_sp_nat.ip_cidr_range]
}

/* The router that the bastion VM uses to install external packages
(for example, Dante SOCKS server). */

resource "google_compute_router" "psc_sp_ex_router" {
  name    = "dms-psc-external-router"
  project = var.project_id
  region  = var.region
  network = google_compute_network.psc_sp_network.id
}

resource "google_compute_router_nat" "psc_sp_ex_router_nat" {
  name    = "dms-psc-external-router-nat"
  project = var.project_id
  region  = var.region
  router  = google_compute_router.psc_sp_ex_router.name

  nat_ip_allocate_option             = "AUTO_ONLY"
  source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"

  log_config {
    enable = true
    filter = "ERRORS_ONLY"
  }
}

outputs.tf:

# The Private Service Connect service attachment.

output "service_attachment" {
  value = google_compute_service_attachment.psc_sp_service_attachment.id
}