9 votes

Impossible de se connecter à Cloud SQL Postgres depuis GKE via une adresse IP privée

Je rencontre des problèmes pour accéder à une instance Cloud SQL exécutant Postgres à partir d'un cluster GKE en utilisant l'IP privée de la base de données. Toute la documentation que j'ai trouvée suggère d'utiliser un cluster activé pour VPC pour accomplir cela, mais j'ai toujours du mal à accéder à la base de données.

Plus précisément, je peux accéder à la base de données à partir des nœuds de mon cluster, mais je ne peux pas y accéder à partir d'un conteneur sur le nœud à moins d'exécuter le conteneur Docker en utilisant le réseau de l'hôte. Cela me fait penser que j'ai une incompréhension de la façon dont les composants de réseau d'un VPC GCP et de Kubernetes interagissent les uns avec les autres.

VPC

Mon VPC a un sous-réseau avec deux plages secondaires :

Plage IP : 10.0.0.0/16
Plage secondaire - pods : 10.1.0.0/16
Plage secondaire - services : 10.2.0.0/16

Ceci est créé en utilisant la configuration Terraform suivante :

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

Base de Données

Ma base de données Cloud SQL exécute Postgres 11 et est configurée pour autoriser uniquement les connexions via l'IP privée. J'ai mis en place une connexion de couplage avec un ensemble d'adresses de calcul globales pour permettre l'accès à l'instance Cloud SQL depuis mon VPC. Dans ce cas, j'ai obtenu les valeurs suivantes :

Plage d'IP de connexion de service privé : 172.26.0.0/16
IP Privée de la Base de Données : 172.26.0.3

Ces ressources sont provisionnées avec la configuration Terraform suivante :

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

Cluster

Mon cluster GKE est configuré pour être natif VPC et pour utiliser les plages secondaires du sous-réseau cluster du VPC. Informations importantes sur le cluster :

Version du Master : 1.14.8-gke.17
Réseau : my-vpc
Sous-réseau : cluster
Natif VPC : Activé
Plage d'adresses des Pods : 10.1.0.0/16
Plage d'adresses des Services : 10.2.0.0/16

Le cluster est créé en utilisant la configuration Terraform suivante :

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

Tentatives de Connexion

J'ai essayé de me connecter à la base de données depuis de nombreux contextes différents pour essayer de comprendre le problème.

Instance Autonome

J'ai créé une nouvelle VM de calcul Ubuntu dans mon VPC et j'ai pu me connecter à la base de données en utilisant à la fois nping et psql.

Depuis un Conteneur sur un Nœud

En utilisant soit kubectl attach sur un pod de mon cluster, soit en me connectant en SSH sur un nœud et en exécutant ma propre commande docker, je constate que tous les paquets vers la base de données ne parviennent pas.

# En se connectant en SSH et en exécutant un conteneur docker.
docker run -it ubuntu /bin/bash -c 'apt update && apt install -y nmap && nping --tcp -p 5432 172.26.0.3'

Depuis un Conteneur sur un Nœud avec le Réseau de l'Hôte

Si je répète la commande ci-dessus mais en utilisant le réseau de l'hôte, je peux me connecter à la base de données.

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

Suggestions?

Étant donné que la plupart des questions sur la connexion à une instance Cloud SQL depuis GKE via une IP privée sont résolues lorsqu'ils configurent leur cluster pour être VPC-native, je suppose que mon problème réside quelque part dans ma configuration réseau. Je serais reconnaissant pour toute suggestion et je suis prêt à fournir des informations supplémentaires. Merci.

Questions Connexes

Problème de Connexion à Cloud SQL Postgres en utilisant une IP Privée depuis GKE

Mise à Jour 2019-12-05

En convertissant les commandes de la question connexe liée ci-dessus en Terraform (appelons cela la configuration MVP), je suis en mesure de me connecter à l'instance Postgres en utilisant une IP privée, je pense donc maintenant que le problème réside plus en profondeur dans ma configuration. Je n'ai toujours pas déterminé quel élément exact de mon infrastructure diffère de la configuration MVP.

Ma prochaine tentative consistera probablement à améliorer la configuration MVP pour utiliser un pool de nœuds configuré séparément plutôt que le pool de nœuds par défaut pour voir si cela explique le comportement que je constate.

2voto

Rawbie Thring Points 1

Ceci est une version entièrement fonctionnelle pour moi qui :

  • utilise un cluster GCP GKE natif au VPC
  • fonctionne avec une instance GCP PGSQL privée

    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

    cluster à une seule zone

    location = var.zone

    nous avons besoin de 1.17.6+ pour utiliser les 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

    Créer un cluster GKE natif au VPC au lieu d'un cluster basé sur des routes

    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
    }

    } }

    Pool de nœuds géré séparément

    resource "google_container_node_pool" "the_cluster_nodes" { name = "node-pool" project = var.project_id

    cluster à une seule zone

    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",

    nécessaire pour le téléchargement de l'image du conteneur

      "https://www.googleapis.com/auth/devstorage.read_only"
    ]
    
    machine_type = "g1-small"
    
    tags         = [ "${data.google_project.project.name}-gke" ]
    metadata = {
      disable-legacy-endpoints = "true"
    }

    } }

1voto

Bao Ngo Points 11

Il existe des exigences spécifiques en matière de réseau auxquelles les instances Cloud SQL doivent adhérer lorsqu'elles communiquent via une connexion privée. L'une de ces exigences est que vos instances CloudSQL et GKE sont situées dans la même région et le même réseau VPC. [1]

Concernant "Je ne peux pas accéder à la base de données à partir d'un conteneur sur le nœud", est-ce que cela signifie que votre base de données et votre conteneur sont situés dans des réseaux différents? Si tel est le cas, vous ne pouvez pas accéder à une instance Cloud SQL sur son adresse IP privée à partir d'un autre réseau en utilisant un tunnel VPN Cloud, un VPN basé sur une instance ou une interconnexion Cloud.

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

1voto

Nigel Savage Points 109

Je parviens à faire fonctionner cela avec la configuration VPC terraform suivante, la principale différence que je peux voir par rapport à la configuration OP est que je définis un réseau de niveau supérieur comme indiqué ci-dessous {"google_compute_network" "gke-sql-vpc-impl"} au lieu de l'utilisation de 'google_compute_network.vpc.self_link' par les OP.

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

Avec ce VPC, je peux me connecter depuis un pod à l'instance Cloud SQL en utilisant l'IP privée ci-dessus "mysql-private-ip-address-impl". De plus, j'ai configuré des règles de pare-feu pour le tcp et le port de base de données de l'instance Cloud SQL marqué sur les nœuds du cluster.

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

0voto

eset Points 1

Les conteneurs fonctionnent de la même manière en ce qui concerne le réseau que les machines virtuelles (hôte et invité). L'exemple de virtualbox montre différents types de réseaux https://www.nakivo.com/blog/virtualbox-network-setting-guide/ et ils sont très utiles dans d'autres scénarios réseau comme par exemple la conteneurisation. Ce que vous avez avec GKE est, je crois, un Réseau interne donc vous devriez utiliser iptables sur le nœud. Dans GCP par exemple, ce truc est utilisé pour les passerelles NAT lors de la création d'une instance NAT qui fournit l'accès à Internet pour toutes les autres VM.

Et aussi, le nœud devrait être dans la même région que le CloudSQL car sinon l'utilisation de l'adresse IP privée ne fonctionnera pas. P.S. Si vous envisagez de forcer SSL à l'avenir dans votre instance CloudSQL, ne le faites pas à moins que vous ne souhaitiez perdre la connectivité privée de manière permanente. Je viens de soumettre un ticket au support de GCP car je considère cela comme un bug.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X