У меня проблемы с доступом к экземпляру Cloud SQL, на котором запущен Postgres, из кластера GKE с использованием частного IP-адреса базы данных. Вся найденная мною документация предлагает использовать для этого кластер с поддержкой VPC, но у меня все еще возникают проблемы с доступом к базе данных.
В частности, я могу получить доступ к базе данных с узлов в моем кластере, но я не могу связаться с база данных из контейнера на узле, если я не запустил контейнер докеров, используя сеть хоста. Это наводит меня на мысль, что я неправильно понимаю, как сетевые компоненты GCP VPC и Kubernetes взаимодействуют друг с другом.
Мой 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
Существует определенное Облако сетевых требований, которого должны придерживаться экземпляры SQL при передаче через частное соединение. Один из которых - то, что Ваш CloudSQL и экземпляры GKE расположены в том же регионе и сети VPC. [1]
Относительно "Я не могу достигнуть базы данных из контейнера на узле", это означает Вас, Ваша база данных и контейнер расположились в различных сетях? Если так, Вы не можете получить доступ к Облаку экземпляр SQL на его частном IP-адресе из другой сети с помощью Облака туннель VPN, основанная на экземпляре VPN или Облачное межсоединение.
[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, так как считаю это ошибкой.
У меня это работает со следующей настройкой 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
}
}
}
Это полностью рабочая версия для меня, которая:
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"
}
}
}