У меня проблемы с доступом к экземпляру Cloud SQL, на котором запущен Postgres, из кластера GKE с использованием частного IP-адреса базы данных. Вся найденная мною документация предлагает использовать для этого кластер с поддержкой VPC, но у меня все еще возникают проблемы с доступом к базе данных.
В частности, я могу получить доступ к базе данных с узлов в моем кластере, но я не могу получить доступ к базе данных из контейнера на узле, если я не запустил контейнер докеров, используя сеть хоста. Это заставляет меня думать, что я неправильно понимаю, как сетевые компоненты GCP VPC и Kubernetes взаимодействуют друг с другом.
В моем VPC есть одна подсеть с двумя дополнительными диапазонами:
Диапазон IP: 10.0.0.0/16
Вторичный диапазон - стручки: 10.1.0.0/16
Secondary Range - услуги: 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 и использует дополнительные диапазоны из cluster
подсеть VPC. Некоторая важная информация о кластере:
Основная версия: 1.14.8-гке.17
Сеть: мой-vpc
Подсеть: кластер
VPC-native: Включено
Диапазон адресов пакета: 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'
Если я повторю команду сверху, но использую сеть хоста, я могу подключиться к базе данных.
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-native, я предполагаю, что моя проблема кроется где-то в моей сетевой конфигурации. Буду признателен за любые предложения и рад предоставить любую дополнительную информацию. Спасибо.
Проблема с подключением к Cloud SQL Postgres с использованием частного IP-адреса от GKE
Преобразование команд из связанный вопрос связанный выше с Terraform (назовите это конфигурацией MVP), я могу подключиться к экземпляру Postgres, используя частный IP-адрес, поэтому теперь я считаю, что проблема лежит глубже в моей конфигурации. Я до сих пор не определил, какая именно часть моей инфраструктуры отличается от конфигурации MVP.
Моя следующая попытка, вероятно, будет состоять в том, чтобы улучшить конфигурацию MVP, чтобы использовать отдельно настроенный пул узлов, а не пул узлов по умолчанию, чтобы увидеть, учитывает ли это поведение, которое я наблюдаю.
У меня это работает со следующей настройкой VPC terraform, основная разница, которую я вижу в настройке 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
}
}
}
Существуют определенные сетевые требования, которым должны соответствовать экземпляры Cloud SQL при обмене данными через частное соединение. Во-первых, ваши экземпляры CloudSQL и GKE расположены в одном регионе и в одной сети VPC. [1]
Что касается «Я не могу получить доступ к базе данных из контейнера на узле», означает ли это, что ваша база данных и контейнер расположены в разных сетях? В таком случае вы не можете получить доступ к экземпляру Cloud SQL по его частному IP-адресу из другой сети, используя туннель Cloud VPN, VPN на основе экземпляра или межсоединение Cloud.
[1] https://cloud.google.com/sql/docs/mysql/private-ip#network_requirements.
Когда дело касается сети, контейнеры работают так же, как виртуальные машины (хост и гость). На примере виртуального бокса показаны разные типы сетей https://www.nakivo.com/blog/virtualbox-network-setting-guide/ и они очень полезны в других сетевых сценариях, например, в контейнеризации. Что у вас есть с GKE, я считаю Внутренняя сеть поэтому вы должны использовать iptables на узле. В GCP, например, этот материал используется для шлюзов NAT при создании экземпляра NAT, который обеспечивает доступ в Интернет для всех других виртуальных машин.
Кроме того, узел должен находиться в том же регионе, что и CloudSQL, потому что в противном случае использование частного IP-адреса не будет работать. P.S. Если вы думаете о принудительном использовании SSL в будущем в своем экземпляре CloudSQL, не делайте этого, если вы не хотите навсегда потерять частное подключение. Я только что обратился в службу поддержки GCP, так как считаю это ошибкой.