You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Go SQL Connector连接Cloud SQL PostgreSQL(私有IP)遇权限错误

使用Go Cloud SQL Connector连接私有IP PostgreSQL实例时遇到403权限错误

错误信息

ERROR Failed to dial instance {"error": "failed to get instance: Refresh error: failed to get instance metadata (connection name = ""): Get "https://sqladmin.googleapis.com/sql/v1beta4/projects//instances/postgres/connectSettings?alt=json&prettyPrint=false": compute: Received 403 `Unable to generate access token; IAM returned 403 Forbidden: Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist).
This error could be caused by a missing IAM policy binding on the target IAM service account.

环境详情

  • Google Cloud:启用私有IP连接的PostgreSQL实例
  • 服务账号已配置权限:
    • Cloud SQL Admin
    • Cloud SQL Client
    • Compute Network Admin
    • Project IAM Admin
    • Service Account Admin
    • Service Account Token Creator
    • Storage Admin
    • Workload Identity User
  • 运行环境:代码部署在同一VPC下GKE集群内的VM实例中

相关Go代码

func connectDB() error {
    user := "postgres"
    password := "password"
    connectionName := "connectionName"
    sslmode := "require"
    dbName := "databaseName"

    config, err := pgx.ParseConfig(connStr)
    if err != nil {
        return err
    }

    opts := append([]cloudsqlconn.Option{},
        cloudsqlconn.WithDefaultDialOptions(cloudsqlconn.WithPrivateIP()),
    )

    d, err := cloudsqlconn.NewDialer(context.Background(), opts...)
    if err != nil {
        return err
    }

    config.DialFunc = func(ctx context.Context, network, instance string) (net.Conn, error) {
        log.FromContext(ctx).Info(fmt.Sprintf("Dialing instance: %s", instance))
        conn, err := d.Dial(ctx, connectionName)
        if err != nil {
            log.FromContext(ctx).Error(err, "Failed to dial instance")
        }
        return conn, err
    }

    dbURI := stdlib.RegisterConnConfig(config)
    dbPool, err := sql.Open("pgx", dbURI)
    if err != nil {
        return err
    }   

    err = dbPool.Ping()
    if err != nil {
        return err
    }   
    return nil
}

已完成排查

  • 验证数据库实例私有IP可在同一VPC内正常访问
  • 确认服务账号已配置Cloud SQL Admin、Cloud SQL Client、Service Account Token Creator、Workload Identity User等核心权限
  • 确认Go应用运行在可访问私有VPC的VM实例中

解决方案

1. 检查Workload Identity绑定有效性

确保GKE集群的K8s服务账号已与GCP IAM服务账号完成正确绑定:

gcloud iam service-accounts add-iam-policy-binding \
  [GCP_IAM_SERVICE_ACCOUNT_EMAIL] \
  --member="serviceAccount:[PROJECT_ID].svc.id.goog[K8S_NAMESPACE/K8S_SERVICE_ACCOUNT]" \
  --role="roles/iam.workloadIdentityUser"

同时确认K8s服务账号的注解iam.gke.io/gcp-service-account已正确指向对应的GCP IAM服务账号。

2. 确认iam.serviceAccounts.getAccessToken权限绑定

虽然已配置Service Account Token Creator角色,需确保该角色是绑定到目标服务账号资源上(即需要生成Token的服务账号本身),而非仅在项目层级绑定:

gcloud iam service-accounts add-iam-policy-binding \
  [TARGET_SERVICE_ACCOUNT_EMAIL] \
  --member="serviceAccount:[CALLER_SERVICE_ACCOUNT_EMAIL]" \
  --role="roles/iam.serviceAccountTokenCreator"

3. 验证Cloud SQL Admin API是否启用

检查项目中Cloud SQL Admin API状态,若未启用则需要开启:

# 检查API状态
gcloud services list --enabled | grep sqladmin.googleapis.com

# 启用API
gcloud services enable sqladmin.googleapis.com

4. 验证服务账号身份与Token生成能力

在GKE容器内执行以下命令,确认当前使用的服务账号是否正确,以及是否能正常生成访问Token:

# 获取当前服务账号邮箱
curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email

# 获取访问Token
curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token

若无法获取Token,说明Workload Identity配置存在问题,需重新检查绑定流程。

5. 确认Connection Name格式正确性

检查代码中connectionName的格式是否为项目ID:区域:实例名称,格式错误会导致元数据请求失败。


内容的提问来源于stack exchange,提问作者piyush

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 01:34:52