使用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
相关产品推荐
相关产品推荐

