【问题标题】:Cannot connect to a Postgres SQL instance from inside a pod within a GKE无法从 GKE 中的 pod 内部连接到 Postgres SQL 实例
【发布时间】:2021-06-24 20:58:28
【问题描述】:

我是 Terraform 和 Google Cloud 的新手。

我正在尝试创建一个 K8 集群,其中集群内的 pod 可以与我在同一 VPC 中的 Postgres 服务器进行通信。

但是,当我尝试使用 psql -h <PRIVATE_IP_OF_POSTGRES_SERVER> -U postgresadmin 在集群内的 ubuntu pod 中使用 psql 客户端连接到服务器时,它会等待很长时间并引发以下超时错误。

psql: could not connect to server: Connection timed out
        Is the server running on host "<PRIVATE_IP_OF_POSTGRES_SERVER>" and accepting
        TCP/IP connections on port 5432?

我什至尝试telnet &lt;PRIVATE_IP_OF_POSTGRES_SERVER&gt;,但也没有用。 (PING 也不行)

这是我用于创建 VPC 和 K8 集群的 terraform 脚本:

variable "project_id" {
  description = "project id"
}

variable "region" {
  description = "region"
}

variable "gke_username" {
  default     = ""
  description = "gke username"
}

variable "gke_password" {
  default     = ""
  description = "gke password"
}

variable "gke_num_nodes" {
  default     = 1
  description = "number of gke nodes"
}

provider "google" {
  project = var.project_id
  region  = var.region
}

# VPC
resource "google_compute_network" "vpc" {
  name                    = "${var.project_id}-vpc"
  auto_create_subnetworks = "false"
}

# Subnet
resource "google_compute_subnetwork" "subnet" {
  name          = "${var.project_id}-subnet"
  region        = var.region
  network       = google_compute_network.vpc.name
  ip_cidr_range = "10.10.0.0/24"
}

# GKE cluster
resource "google_container_cluster" "primary" {
  name     = "${var.project_id}-gke"
  location = var.region

  remove_default_node_pool = true
  initial_node_count       = 1

  network    = google_compute_network.vpc.name
  subnetwork = google_compute_subnetwork.subnet.name

  # Create a VPC-native cluster by configuring `ip_allocation_policy` 
  ip_allocation_policy {
    cluster_ipv4_cidr_block  = "/16"
    services_ipv4_cidr_block = "/22"
  }

  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" "primary_nodes" {
  name       = "${google_container_cluster.primary.name}-node-pool"
  location   = var.region
  cluster    = google_container_cluster.primary.name
  node_count = var.gke_num_nodes

  node_config {
    oauth_scopes = [
      "https://www.googleapis.com/auth/logging.write",
      "https://www.googleapis.com/auth/monitoring",
    ]

    labels = {
      env = var.project_id
    }

    # preemptible  = true
    machine_type = "n1-standard-1"
    tags         = ["gke-node", "${var.project_id}-gke"]
    metadata = {
      disable-legacy-endpoints = "true"
    }
  }
}

这是我用于创建 Postgres 服务器的 terraform 脚本文件:

variable "project_id" {
  description = "project id"
}

variable "region" {
  description = "region"
}

terraform {
  required_providers {
    google = {
      source = "hashicorp/google"
      version = "3.61.0"
    }
  }
}

data "google_compute_network" "my_network" {
  name = "novade-lite-vpc"
}

provider "google" {
  project = var.project_id
  region  = var.region
}

resource "random_id" "db_name_suffix" {
  byte_length = 4
}

resource "google_compute_global_address" "private_ip_address" {
  name          = "private-ip-address"
  purpose       = "VPC_PEERING"
  address_type  = "INTERNAL"
  prefix_length = 16
  network       = data.google_compute_network.my_network.self_link
}

resource "google_service_networking_connection" "private_vpc_connection" {
  network                 = data.google_compute_network.my_network.self_link
  service                 = "servicenetworking.googleapis.com"
  reserved_peering_ranges = [google_compute_global_address.private_ip_address.name]
}

resource "google_sql_database_instance" "postgres" {
  name             = "postgres-instance-${random_id.db_name_suffix.hex}"
  database_version = "POSTGRES_11"
  depends_on = [google_service_networking_connection.private_vpc_connection]

  settings {
    tier = "db-f1-micro"

    ip_configuration {
      ipv4_enabled    = false
      private_network = data.google_compute_network.my_network.self_link
    }
  }
}

resource "google_sql_database" "default" {
  name       = "default"
  project    = var.project_id
  instance   = google_sql_database_instance.postgres.name
  collation  = "en_US.UTF8"
  depends_on = [google_sql_database_instance.postgres]
}

resource "google_sql_user" "users" {
  name     = "postgresadmin"
  instance = google_sql_database_instance.postgres.name
  password = "password"
  depends_on = [google_sql_database_instance.postgres]
}

这是我的变量文件(上述两个脚本相同):

project_id = "test-project"
region     = "europe-west2"

非常感谢任何帮助! ????

【问题讨论】:

  • 您好@Eranga,您可以通过多种方式连接到 GKE 集群外部的 SQL 实例。使用来自 GKE 的其他 GCP 产品的首选方式是使用 Workload Identity。在此处查看可用选项:cloud.google.com/sql/docs/mysql/connect-kubernetes-engine
  • 感谢您的快速回复@Shabirmean。我看到了这份文件,但坦率地说,在这个阶段对我来说似乎有点进步。我看到this article 有人为 MySQL 服务器做同样的事情但不使用 Terraform。我只是想了解我是否需要专门做一些事情来允许从 pod 内部访问服务器,或者我当前的脚本是否有错误。 :-)
  • 此外,我在这篇文章中面临的另一个问题是,我必须使用 cloud shell 做很多手动工作,而我希望这由 Terraform 处理。如果你能提供一个实现我需要的 terraform 示例,那就太棒了。 ????

标签: postgresql kubernetes google-cloud-platform terraform google-kubernetes-engine


【解决方案1】:

我不知道 GKE 设置是如何工作的,但我可以根据我对 AWS 中类似设置的理解给你一些指导。

您的集群 pod 将是节点之一,该节点将是某个子网的一部分,并且还会附加一些安全组(防火墙类型)。

类似地,postgres 数据库是在某个子网和附加到它的安全组中创建的。

现在确保数据库安全组在 5432 端口上的所有入站流量来自 pod 子网范围或来自安全组。

【讨论】:

  • 感谢您的洞察力。我设法解决了这个问题,我会在有时间的时候给出答案。
  • @ErangaHeshan 你还记得你是如何修复它的吗?
猜你喜欢
  • 2021-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
  • 2022-01-18
  • 2021-10-27
  • 1970-01-01
  • 2020-06-06
相关资源
最近更新 更多