GKE连接私有Cloud SQL疑难问题排查实录

指南二:GKE连接私有Cloud SQL疑难问题排查实录

本文档记录了一次完整的、从GKE Pod无法连接到私有Cloud SQL实例的疑难问题的排查过程。

1. 问题描述

在成功创建私有Cloud SQL实例后,我们发现:

  • 从位于同一VPC的GCE虚拟机可以成功连接到Cloud SQL。
  • 从GKE集群的Pod中无法连接,psql客户端报告Connection timed out

这表明问题特定于GKE的网络环境。

2. 排查过程

我们按照从易到难、从高层到底层的顺序,系统地排查了所有可能性。

2.1. 检查VPC防火墙规则 (已解决)

怀疑: 是否有防火墙规则阻止了从GKE Pod到Cloud SQL的流量?

验证:

  1. 我们首先检查了GKE节点的IP范围,命令如下:

    bash 复制代码
    gcloud container clusters describe my-cluster2 --region=europe-west2 --project=jason-hsbc --format="json(clusterIpv4Cidr, servicesIpv4Cidr)"

    输出为 192.171.16.0/20 (Pods) 和 192.172.16.0/20 (Services)。

  2. 我们发现现有的防火墙规则没有覆盖这些IP段。因此,我们在Terraform-GCP-config项目中添加了一条新的防火墙规则,允许所有内部流量。

    terraform 复制代码
    # network/tf-vpc0.tf
    resource "google_compute_firewall" "allow_internal" {
      name      = "allow-all-internal-traffic"
      network   = google_compute_network.tf-vpc0.name
      direction = "INGRESS"
      allow {
        protocol = "all"
      }
      source_ranges = [
        "192.168.0.0/16",   # For VPC subnets
        "192.171.16.0/20",  # For GKE Pods
        "192.172.16.0/20"   # For GKE Services
      ]
    }
  3. 通过terraform apply成功应用了此规则。

结果: 问题依旧,连接仍然超时。这排除了VPC防火墙是问题根源的可能性。

2.2. 检查GKE网络策略 (已排除)

怀疑 : GKE集群内部是否有NetworkPolicy资源,默认拒绝了Pod的出站流量?

验证:

bash 复制代码
kubectl get networkpolicy --all-namespaces

输出 : No resources found

结果: 集群中没有任何网络策略。此可能性被排除。

2.3. 检查IP伪装 (IP Masquerade) (已排除)

怀疑: 从Pod发出的流量,其源IP是否被错误地"伪装"(NAT)成了节点的IP,导致防火墙规则不匹配?

验证:

  1. 我们创建了一个ConfigMap (ip-masq-agent-config.yaml),明确告诉GKE的IP伪装代理,所有到私有IP范围(10.0.0.0/8等)的流量都 应该被伪装。

    yaml 复制代码
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ip-masq-agent-config
      namespace: kube-system
    data:
      config: |
        nonMasqueradeCIDRs:
          - 10.0.0.0/8
          - 172.16.0.0/12
          - 192.168.0.0/16
  2. 通过kubectl apply应用了此配置。

结果: 问题依旧。这基本排除了IP伪装是问题根源的可能性。

2.4. 检查VPC Peering路由传播 (已尝试修复)

怀疑: 在排除了以上所有可能后,问题最终指向了VPC Peering的路由传播。即Cloud SQL所在的Google服务网络的路由,没有被正确地通告给GKE的子网。

验证:

  1. 我们首先确认了Peering连接确实存在。

    bash 复制代码
    gcloud compute networks peerings list --project=jason-hsbc

    输出显示名为servicenetworking-googleapis-comACTIVE连接。

  2. 我们尝试通过gcloud命令更新Peering连接,以期"刷新"路由。

    bash 复制代码
    gcloud compute networks peerings update servicenetworking-googleapis-com --network=tf-vpc0 --project=jason-hsbc --export-subnet-routes-with-public-ip --no-import-subnet-routes-with-public-ip

结果: 问题依旧。这表明问题是一个更深层次的、无法通过简单刷新解决的路由配置问题。

3. 最终解决方案:切换到Cloud SQL Auth Proxy

在对直接IP连接进行了详尽的排查后,我们确定问题出在难以直接干预的GCP高级网络层面。此时,我们切换到了Google官方推荐的最佳实践:使用Cloud SQL Auth Proxy

以下是我们成功实现连接的详细步骤:

3.1. 准备工作:服务账号与权限

我们决定使用节点绑定的服务账号vm-common@jason-hsbc.iam.gserviceaccount.com。首先,需要为它授予连接Cloud SQL的权限。

命令:

bash 复制代码
gcloud projects add-iam-policy-binding jason-hsbc --member="serviceAccount:vm-common@jason-hsbc.iam.gserviceaccount.com" --role="roles/cloudsql.client"

输出:

复制代码
Updated IAM policy for project [jason-hsbc].
...

结论 : vm-common服务账号现在拥有了Cloud SQL Client角色。

3.2. 创建测试Deployment (proxy-test-deployment.yaml)

我们创建了一个包含两个容器的Deployment:一个作为Auth Proxy边车,另一个作为psql客户端。我们让Proxy使用其从节点环境自动获取的服务账号凭证。

YAML配置:

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: proxy-test-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: proxy-test
  template:
    metadata:
      labels:
        app: proxy-test
    spec:
      containers:
      - name: cloud-sql-proxy
        image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.8.0
        args:
          - "--private-ip"
          - "jason-hsbc:europe-west2:my-database-instance"
        securityContext:
          runAsNonRoot: true
      - name: psql-client
        image: postgres:13
        command: ["/bin/sh", "-c"]
        args:
        - |
          sleep 5;
          echo "--- Attempting to connect via proxy ---";
          export PGPASSWORD=[YOUR_PASSWORD];
          psql -h 127.0.0.1 -U nvd11 -d default_db -c "\\l";
          echo "--- Test complete, sleeping forever ---";
          sleep infinity;

3.3. 部署并验证

  1. 应用Deployment:

    bash 复制代码
    kubectl apply -f proxy-test-deployment.yaml

    输出 : deployment.apps/proxy-test-deployment created

  2. 查看测试日志 : 我们等待Pod启动,然后查看psql-client容器的日志。

    bash 复制代码
    POD_NAME=$(kubectl get pods -l app=proxy-test -o jsonpath='{.items[0].metadata.name}') && kubectl logs $POD_NAME -c psql-client

最终测试日志 (成功):

复制代码
--- Attempting to connect via proxy ---
                                                List of databases
     Name      |       Owner       | Encoding |  Collate   |   Ctype    |            Access privileges
---------------+-------------------+----------+------------+------------+-----------------------------------------
 cloudsqladmin | cloudsqladmin     | UTF8     | en_US.UTF8 | en_US.UTF8 |
 default_db    | cloudsqlsuperuser | UTF8     | en_US.UTF8 | en_US.UTF8 |
 postgres      | cloudsqlsuperuser | UTF8     | en_US.UTF8 | en_US.UTF8 |
 ...
(5 rows)

--- Test complete, sleeping forever ---

4. 结论

当遇到从GKE到Cloud SQL私有IP的连接问题,并且已确认VPC防火墙和网络策略无误时,应高度怀疑是VPC Peering的路由传播问题。

在这种情况下,与其花费大量时间进行深层网络调试,切换到使用Cloud SQL Auth Proxy是最高效、最可靠、最安全的解决方案

相关推荐
马克学长1 天前
SSM青岛恒星科技学院机房管理系统0k0u9(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·科技·ssm 框架·教育信息化·机房管理系统·青岛恒星科技学院
7***68431 天前
Spring Boot 从 2.7.x 升级到 3.3注意事项
数据库·hive·spring boot
L***d6701 天前
Spring Boot 各种事务操作实战(自动回滚、手动回滚、部分回滚)
java·数据库·spring boot
java_logo1 天前
MySQL Server Docker 容器化部署指南
linux·运维·数据库·docker·容器
likuolei1 天前
XSL-FO 软件
java·开发语言·前端·数据库
p***95001 天前
Springboot3 Mybatis-plus 3.5.9
数据库·oracle·mybatis
CS_浮鱼1 天前
【MySQL】InnoDB存储引擎
数据库·mysql
合作小小程序员小小店1 天前
桌面开发,在线%信息管理%系统,基于vs2022,c#,winform,sql server数据。
开发语言·数据库·sql·microsoft·c#
q***18841 天前
解决phpstudy无法启动MySQL服务
数据库·mysql·adb
e***95641 天前
【HTML+CSS】使用HTML与后端技术连接数据库
css·数据库·html