google-cloud-platformgoogle-cloud-sqlgoogle-cloud-rungo-gormgo-gin

No such host error on Cloud SQL- Using Gcloud postgressal and Gcloud Run for deploying Microservice using GoLang


I am using gin framework to develop my go microservice. I am using google cloud as the provider and using google cloud run for deploying the microservice and google cloud postgressql for database. I am using IAM authentication.

Below is the code I am using for creating database object

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

    // Construct the DSN
    dsn := fmt.Sprintf("host=%s dbname=%s user=%s sslmode=disable",
        os.Getenv("INSTANCE_CONNECTION_NAME"), // Cloud SQL instance connection name
        os.Getenv("DB_NAME"),                  // Database name
        os.Getenv("DB_USER"),                  // Database password
    )

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

    // Auto-migrate your models
    db.AutoMigrate(&User{})

    fmt.Println("Connected to database successfully")
    return db, nil
}

Below is the cmd I am using for deploying the microservice

gcloud run deploy api \
  --source=. \
  --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

With the above code, Once I deploy the microsevice I am getting error as "[0m[31m[error] [0mfailed to initialize database, got error failed to connect to host=sxxxx-xxxxx:us-west1:uxxx user=sxxxx-xxxx@sxxxx-xxxx.iam database= dbxxxxxx : hostname resolving error (lookup sxxxx-xxxx:us-west1:uxxxx: no such host)"


Solution

  • I assume you're using public IP.

    You have a few options to do this:

    1. Run a multi-container setup with the Cloud SQL Proxy, enable whatever options you want (e.g., IAM Authentication), and connect to the Proxy as if it were a Postgres database running on the same machine
    2. Use the Cloud SQL Go Connector and configure Gorm like so:
    package main
    
    import (
            "fmt"
            "time"
    
            "cloud.google.com/go/cloudsqlconn"
            "cloud.google.com/go/cloudsqlconn/postgres/pgxv5"
            "gorm.io/driver/postgres"
            "gorm.io/gorm"
    )
    
    func main() {
            cleanup, err := pgxv5.RegisterDriver(
                    "cloudsql-postgres",
                    cloudsqlconn.WithLazyRefresh(),
                    cloudsqlconn.WithIAMAuthN(),
            )
            if err != nil {
                    panic(err)
            }
            // cleanup will stop the driver from retrieving ephemeral certificates
            // Don't call cleanup until you're done with your database connections
            defer cleanup()
    
            dsn := "host=my-project:us-central1:my-instance user=postgres password=postgres dbname=postgres sslmode=disable"
    
            db, err := gorm.Open(postgres.New(postgres.Config{
                    DriverName: "cloudsql-postgres",
                    DSN:        dsn,
            }))
            if err != nil {
                    panic(err)
            }
    
            // get the underlying *sql.DB type to verify the connection
            sdb, err := db.DB()
            if err != nil {
                    panic(err)
            }
    
            var t time.Time
            if err := sdb.QueryRow("select now()").Scan(&t); err != nil {
                    panic(err)
            }
    
            fmt.Println(t)
    }
    

    From a convenience standpoint, #2 is easier. Note the "lazy refresh" option which ensures the Go Connector doesn't try to run background goroutines outside of a request, since Cloud Run throttles the CPU by default and causes problems with background goroutines.