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

使用GoLang+Cloud Run部署微服务时Cloud SQL报No such host错误

解决Cloud Run连接Cloud PostgreSQL的主机解析错误

错误根源

你将Cloud SQL实例连接名(格式为project:region:instance)直接作为数据库的host参数使用,这个标识并非可解析的DNS域名,导致出现主机无法解析的错误。Cloud Run连接Cloud SQL必须通过Unix套接字或Cloud SQL Auth Proxy,而非直接用实例连接名作为host。

解决方案步骤

1. 修正数据库连接代码

需要调整DSN的host路径,并处理IAM认证的密码生成,以下提供两种可行方式:

方式一:用cloudsql-go-auth自动处理IAM认证

先安装依赖:

go get cloud.google.com/go/cloudsqlconn/postgres/pgxv4

修改连接函数:

import (
    "context"
    "fmt"
    "os"

    "cloud.google.com/go/cloudsqlconn"
    "cloud.google.com/go/cloudsqlconn/postgres/pgxv4"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

func connectDatabase() (*gorm.DB, error) {
    fmt.Println("Connecting to database")

    instanceConnName := os.Getenv("INSTANCE_CONNECTION_NAME")
    dbName := os.Getenv("DB_NAME")
    dbUser := os.Getenv("DB_USER")

    // 注册Cloud SQL专用驱动,自动处理IAM认证
    cleanup, err := pgxv4.RegisterDriver("cloudsql-postgres",
        cloudsqlconn.WithIAMAuthN())
    if err != nil {
        return nil, fmt.Errorf("failed to register driver: %w", err)
    }
    defer cleanup()

    // 构造DSN,使用Cloud Run挂载的Unix套接字路径
    dsn := fmt.Sprintf("host=/cloudsql/%s user=%s dbname=%s sslmode=require",
        instanceConnName, dbUser, dbName)

    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
        return nil, fmt.Errorf("error connecting to database: %w", err)
    }

    db.AutoMigrate(&User{})
    fmt.Println("Connected to database successfully")
    return db, nil
}

方式二:手动生成IAM认证令牌作为密码

若不想引入额外依赖,可手动获取IAM令牌:

import (
    "context"
    "fmt"
    "os"

    "golang.org/x/oauth2/google"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

func connectDatabase() (*gorm.DB, error) {
    fmt.Println("Connecting to database")

    instanceConnName := os.Getenv("INSTANCE_CONNECTION_NAME")
    dbName := os.Getenv("DB_NAME")
    dbUser := os.Getenv("DB_USER")

    // 获取IAM认证临时令牌
    ctx := context.Background()
    ts, err := google.DefaultTokenSource(ctx, "https://www.googleapis.com/auth/sqlservice.admin")
    if err != nil {
        return nil, fmt.Errorf("failed to create token source: %w", err)
    }
    token, err := ts.Token()
    if err != nil {
        return nil, fmt.Errorf("failed to get token: %w", err)
    }

    // 构造DSN,使用Unix套接字路径+IAM令牌作为密码
    dsn := fmt.Sprintf("host=/cloudsql/%s user=%s password=%s dbname=%s sslmode=require",
        instanceConnName, dbUser, token.AccessToken, dbName)

    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
        return nil, fmt.Errorf("error connecting to database: %w", err)
    }

    db.AutoMigrate(&User{})
    fmt.Println("Connected to database successfully")
    return db, nil
}

2. 修正Cloud Run部署命令

必须添加--add-cloudsql-instances参数,指定要连接的Cloud SQL实例,Cloud Run会自动将Unix套接字挂载到容器的/cloudsql目录:

gcloud run deploy api \
  --source=. \
  --add-cloudsql-instances="env-xxxx:us-west1:uxxx" \
  --set-env-vars INSTANCE_CONNECTION_NAME="env-xxxx:us-west1:uxxx" \
  --set-env-vars DB_NAME="dbxxxxxx" \
  --set-env-vars DB_USER="sxxxx-xxxx@sxxxx-xxxx.iam" \
  --service-account="sxxxx-xxxx@sxxxx-rxxxx.iam.gserviceaccount.com" \
  --allow-unauthenticated

3. 验证权限配置

  • 确保部署时指定的服务账号拥有Cloud SQL Client角色,可通过Google Cloud IAM控制台为该账号添加此角色。
  • 确认Cloud SQL实例已启用IAM数据库认证,且DB_USER对应的IAM账号已被创建为PostgreSQL的数据库用户。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:18:08