Не удается подключиться к Cloud SQL Postgres из GKE через частный IP-адрес

У меня проблемы с доступом к экземпляру Cloud SQL, на котором запущен Postgres, из кластера GKE с использованием частного IP-адреса базы данных. Вся найденная мною документация предлагает использовать для этого кластер с поддержкой VPC, но у меня все еще возникают проблемы с доступом к базе данных.

В частности, я могу получить доступ к базе данных с узлов в моем кластере, но я не могу связаться с база данных из контейнера на узле, если я не запустил контейнер докеров, используя сеть хоста. Это наводит меня на мысль, что я неправильно понимаю, как сетевые компоненты GCP VPC и Kubernetes взаимодействуют друг с другом.

VPC

Мой VPC имеет одну подсеть с двумя дополнительными диапазонами:

IP Range ]: 10.0.0.0/16
Вторичный диапазон - pods: 10.1.0.0/16
Вторичный диапазон - сервисы: 10.2.0.0/16

Это создается с использованием следующей конфигурации Terraform :

resource "google_compute_subnetwork" "cluster" {
  ip_cidr_range            = "10.0.0.0/16"
  name                     = "cluster"
  network                  = google_compute_network.vpc.self_link

  secondary_ip_range {
    ip_cidr_range = "10.1.0.0/16"
    range_name    = "pods"
  }

  secondary_ip_range {
    ip_cidr_range = "10.2.0.0/16"
    range_name    = "services"
  }
}

База данных

Моя облачная база данных SQL работает под управлением Postgres 11 и настроена так, чтобы разрешать соединения только через частный IP. Я установил пиринговое соединение с набором глобальных вычислительных адресов, чтобы разрешить доступ к экземпляру Cloud SQL из моего VPC. В этом случае я получил следующие значения:

Диапазон IP-адресов подключения к частной службе: 172.26.0.0/16
Частный IP-адрес базы данных: 172.26.0.3

Эти ресурсы предоставляются с следующая конфигурация Terraform:

resource "google_compute_global_address" "db_private_ip" {
  provider = "google-beta"

  name          = "db-private-ip"
  purpose       = "VPC_PEERING"
  address_type  = "INTERNAL"
  prefix_length = 16
  network       = google_compute_network.vpc.self_link
}

resource "google_service_networking_connection" "db_vpc_connection" {
  network                 = google_compute_network.vpc.self_link
  service                 = "servicenetworking.googleapis.com"
  reserved_peering_ranges = [google_compute_global_address.db_private_ip.name]
}


resource "google_sql_database_instance" "db" {
  depends_on = [google_service_networking_connection.db_vpc_connection]

  database_version = "POSTGRES_11"

  settings {
    availability_type = "ZONAL"
    tier              = "db-f1-micro"

    ip_configuration {
      ipv4_enabled    = false
      private_network = google_compute_network.vpc.self_link
    }
  }
}

Кластер

Мой кластер GKE настроен для работы с VPC и для использования дополнительных диапазонов из подсети кластера VPC. Некоторая важная информация о кластере:

Основная версия: 1.14.8-gke.17
Сеть: my-vpc
Подсеть: кластер
Собственный VPC: Включено
Диапазон адресов пода: 10.1.0.0/16
Диапазон адресов службы: 10.2.0.0/16

Кластер создается с использованием следующей конфигурации Terraform:

resource "google_container_cluster" "primary" {
  location           = var.gcp_region
  min_master_version = data.google_container_engine_versions.latest_patch.latest_master_version
  name               = "my-cluster"
  network            = google_compute_network.vpc.self_link
  subnetwork         = google_compute_subnetwork.cluster.self_link

  # We can't create a cluster with no node pool defined, but we want to only use
  # separately managed node pools. So we create the smallest possible default
  # node pool and immediately delete it.
  remove_default_node_pool = true
  initial_node_count       = 1

  ip_allocation_policy {
    use_ip_aliases                = true
    cluster_secondary_range_name  = "pods"
    services_secondary_range_name = "services"
  }

  master_auth {
    username = ""
    password = ""

    client_certificate_config {
      issue_client_certificate = false
    }
  }
}

Попытки подключения

Я пытался подключиться к базе данных из разных контекстов, чтобы попытаться выяснить проблему.

Автономный экземпляр

Я создал новую вычислительную виртуальную машину Ubuntu в моем VPC и смог подключиться к базе данных с помощью nping и psql .

Из контейнера на узле

С помощью kubectl attach на модуле в моем кластера или SSH-подключения к узлу и запуска моей собственной команды docker, я вижу, что все пакеты в базу данных не поступают.

# SSH-ing and running a docker container.
docker run -it ubuntu /bin/bash -c 'apt update && apt install -y nmap && nping --tcp -p 5432 172.26.0.3'

Из контейнера на узле с сетевым узлом

Если я повторяю команду из bove, но используя сеть хоста, я могу подключиться к базе данных.

docker run -it --net host ubuntu /bin/bash -c 'apt update && apt install -y nmap && nping --tcp -p 5432 172.26.0.3'

Предложения?

Поскольку большинство вопросов о подключении к экземпляру Cloud SQL из GKE через частный IP-адрес решаются, когда они настраивают свой кластер для работы с VPC , Я полагаю, моя проблема кроется в моей сетевой конфигурации. Буду признателен за любые предложения и рад предоставить любую дополнительную информацию. Спасибо.

Связанные вопросы

Проблема с подключением к Cloud SQL Postgres с использованием частного IP-адреса от GKE

1
задан 17 November 2019 в 18:39
4 ответа

Существует определенное Облако сетевых требований, которого должны придерживаться экземпляры SQL при передаче через частное соединение. Один из которых - то, что Ваш CloudSQL и экземпляры GKE расположены в том же регионе и сети VPC. [1]

Относительно "Я не могу достигнуть базы данных из контейнера на узле", это означает Вас, Ваша база данных и контейнер расположились в различных сетях? Если так, Вы не можете получить доступ к Облаку экземпляр SQL на его частном IP-адресе из другой сети с помощью Облака туннель VPN, основанная на экземпляре VPN или Облачное межсоединение.

[1] https://cloud.google.com/sql/docs/mysql/private-ip#network_requirements.

0
ответ дан 4 December 2019 в 02:33

Контейнеры работают в сети так же, как виртуальные машины (хост и гость). Пример виртуального бокса показывает разные типы сетей https://www.nakivo.com/blog/virtualbox-network-setting-guide/ , и они очень полезны в других сетевых сценариях, таких как, например, контейнеризация. Что у вас есть с GKE, я считаю, что это внутренняя сеть , поэтому вы должны использовать iptables на узле. В GCP, например, этот материал используется для шлюзов NAT при создании экземпляра NAT, который обеспечивает доступ в Интернет для всех других виртуальных машин.

Кроме того, узел должен находиться в том же регионе, что и CloudSQL, потому что в противном случае использование частного IP-адреса не сработает. P.S. Если вы думаете о принудительном использовании SSL в будущем в своем экземпляре CloudSQL, не делайте этого, если вы не хотите навсегда потерять частное подключение. Я только что подал заявку в службу поддержки GCP, так как считаю это ошибкой.

0
ответ дан 4 December 2019 в 22:00

У меня это работает со следующей настройкой Terraform VPC, основная разница, которую я вижу в настройке OP, заключается в том, что я определяю сеть верхнего уровня, см. Ниже {"google_compute_network" "gke-sql -vpc-impl "} в отличие от OPs, использующего 'google_compute_network.vpc.self_link'

variable "public-subnet-cidr" {
default = "10.1.0.0/24"
}
resource "google_compute_network" "gke-sql-vpc-impl" {
name                    = "${var.network}"
auto_create_subnetworks = "false"
}

resource "google_compute_global_address" "mysql-private-ip-address-impl" {
name          = "mysql-private-ip-address"
purpose       = "VPC_PEERING"
address_type  = "INTERNAL"
prefix_length = 16
network       = "${google_compute_network.gke-sql-vpc-impl.name}"
}

resource "google_service_networking_connection" "private-mysql-vpc-connection-impl" {
network                 = "${google_compute_network.gke-sql-vpc-impl.self_link}"
service                 = "servicenetworking.googleapis.com"
reserved_peering_ranges = ["${google_compute_global_address.mysql-private-ip-address-impl.name}"]
}

resource "google_compute_subnetwork" "public-subnet-impl" {
name          = "${var.network}-public-subnet"
ip_cidr_range = "${var.public-subnet-cidr}"
network       = "${var.network}"
depends_on    = ["google_compute_network.gke-sql-vpc-impl"]
region        = "${var.region}"

secondary_ip_range {
ip_cidr_range = "10.2.0.0/16"
range_name    = "pods"
}

secondary_ip_range {
ip_cidr_range = "10.3.0.0/16"
range_name    = "services"
 }
}

с этим VPC, я могу подключиться из модуля к экземпляру Cloud SQL, используя частный IP-адрес, указанный выше mysql-private-ip-address -impl ". Также у меня есть правила брандмауэра, настроенные для tcp, и порт базы данных экземпляра Cloud SQL, привязанный к узлам кластера.

resource "google_container_cluster" "primary" {
name                     = "${var.cluster_name}"
location                 = "${var.zone}"
remove_default_node_pool = false
initial_node_count       = "${var.node_count_simple}"
network            = "${google_compute_network.gke-sql-vpc-impl.name}"
subnetwork         = "${google_compute_subnetwork.public-subnet-impl.name}"  

ip_allocation_policy {
cluster_secondary_range_name  = "pods"
services_secondary_range_name = "services"
}

node_config {
machine_type = "${var.pool_machine_type}"
preemptible  = true
oauth_scopes = [
  "https://www.googleapis.com/auth/compute",
  "https://www.googleapis.com/auth/devstorage.read_only",
  "https://www.googleapis.com/auth/logging.write",
  "https://www.googleapis.com/auth/monitoring"
 ]

 tags = ["default-nodeport-http", "default-nodeport-https", "default-firewall-mysql"]
  }

 master_auth {
 username = ""
 password = ""
 client_certificate_config {
  issue_client_certificate = false
  }
 }
}
0
ответ дан 13 January 2020 в 23:22

Это полностью рабочая версия для меня, которая:

  • использует GCP GKE VPC-native кластер
  • работает с экземпляром Private GCP PGSQL

resource "google_compute_subnetwork" "gke-subnet" {
  name          = "gke-subnet"
  region        = var.region
  network       = google_compute_network.vpc.name
  ip_cidr_range = "10.10.0.0/16"
}

resource "google_container_cluster" "the_cluster" {
  provider            = google-beta
  name                = "gke"
  project             = var.project_id
  # single-zone cluster
  location            = var.zone
  # we need 1.17.6+ to use NEGs
  # https://cloud.google.com/kubernetes-engine/docs/concepts/ingress
  # min_master_version  = data.google_container_engine_versions.default.latest_master_version
  min_master_version = "1.17.12-gke.2502"

  remove_default_node_pool = true
  initial_node_count       = 1

  # Create a VPC-native GKE cluster instead of route-based cluster
  network    = google_compute_network.vpc.name
  subnetwork = google_compute_subnetwork.gke-subnet.name
  networking_mode = "VPC_NATIVE"

  ip_allocation_policy {
    cluster_ipv4_cidr_block = "/20"
    services_ipv4_cidr_block = "/20"
  }

  master_auth {
    username = var.gke_username
    password = var.gke_password

    client_certificate_config {
      issue_client_certificate = false
    }
  }
}

# Separately Managed Node Pool
resource "google_container_node_pool" "the_cluster_nodes" {
  name       = "node-pool"
  project    = var.project_id
  # single-zone cluster
  location   = var.zone
  cluster    = google_container_cluster.the_cluster.name
  node_count = var.gke_num_nodes

  node_config {
    oauth_scopes = [
      "https://www.googleapis.com/auth/logging.write",
      "https://www.googleapis.com/auth/monitoring",
      # needed for Container Image pulling
      "https://www.googleapis.com/auth/devstorage.read_only"
    ]

    machine_type = "g1-small"

    tags         = [ "${data.google_project.project.name}-gke" ]
    metadata = {
      disable-legacy-endpoints = "true"
    }
  }
}

0
ответ дан 22 October 2020 в 10:15

Теги

Похожие вопросы