PostgreSQL용 AlloyDB 대상의 비공개 IP 연결 구성

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

Private Service Connect의 네트워크 아키텍처 설정은 PSC 지원 또는 PSC 미지원 대상 PostgreSQL용 AlloyDB 클러스터를 사용하는지에 따라 다릅니다.

대상 연결 방법에 대한 자세한 내용은 대상 데이터베이스 연결 방법 개요를 참고하세요.

PSC 지원 PostgreSQL용 AlloyDB 클러스터의 Private Service Connect

PSC 지원 PostgreSQL용 AlloyDB 대상과 함께 비공개 연결을 사용하려면 다음 단계를 따르세요.

  1. 대상 클러스터를 만들고 구성할 때 비공개 IP를 사용하는 PSC 지원 클러스터로 만들어야 합니다. Private Service Connect용으로 사용 설정되도록 기존 PostgreSQL용 AlloyDB 클러스터를 수정할 수 없습니다.
  2. 나중에 대상 연결 프로필을 만들 때 다음을 실행합니다.
    1. 호스트 이름 또는 IP 주소 필드를 사용하여 대상 클러스터의 Private Service Connect 엔드포인트 DNS 레코드를 선택합니다.
    2. 연결 방법 정의 섹션에서 비공개 IP를 선택합니다.

PSC 지원이 아닌 PostgreSQL용 AlloyDB 클러스터용 Private Service Connect

Private Service Connect가 사용 설정된 상태로 생성되지 않은 PostgreSQL용 AlloyDB 대상에 비공개 IP 연결을 사용하려면 Database Migration Service와 대상 간 트래픽 라우팅을 위한 추가 네트워크 구성요소를 만들어야 합니다. 자세한 내용은 PSC가 아닌 PostgreSQL용 AlloyDB 클러스터의 비공개 IP 대상 연결을 참고하세요.

네트워킹 요구사항에 하나의 배스천 가상 머신 (VM)이 충분하지 않은 경우 네트워크 프로듀서 설정에 인스턴스 그룹을 구성합니다. 자세한 내용은 관리 서비스의 네트워크 연결을 참고하세요.

필요한 Private Service Connect 프로듀서 설정을 만들려면 Google Cloud CLI 또는 Terraform 자동화 스크립트를 사용하는 것이 좋습니다. 아래의 명령어 데이터를 사용하기 전에 다음을 바꿉니다.

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

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.
# 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 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

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-alloydb-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
}

나중에 대상 연결 프로필을 만들 때 다음 단계를 따르세요.

  1. 연결 방법 정의 섹션에서 비공개 IP를 선택합니다.
  2. 서비스 연결 이름 드롭다운 메뉴에서 dms-psc-svc-att-REGION을 선택합니다.