0

I can configure connection from local machine using sql auth proxy but I can't from cloud run springboot application with hikaricp to a cloud sql with public ip using unix socket. Somebody have a complete example? I read in gcp doc that I don't need to create a docker for sql auth proxy for connection from cloud run to cloud sql.It's created when you define db connection in configuration of cloud run.

POM.xml added below dependency:

    <dependency>
        <groupId>com.google.cloud.sql</groupId>
        <artifactId>mysql-socket-factory</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

I set it and next I defined in application the follow application properties (by classic jdbc works fine adding my ip in cloud sql to allow connection but I need to use sql auth proxy by unix socket to avoid to add a vpc, I will not explain reasone too long and boring) for hikariCP:

spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql:///DBSCHEMA
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.socketFactory=com.google.cloud.sql.mysql.SocketFactory
spring.datasource.cloudSqlInstance=GCP_PROJECT:GCP_REGION:DBNAME
spring.datasource.ipTypes=PUBLIC

logging.level.com.zaxxer.hikari=TRACE

Somebody can help me with some example that works fine? If in your example created docker for sql auth proxy please explain it. In internet I can't find resource clearly talking about this configuration.

Thanks a lot.

SkyBlackHawk
  • 95
  • 10

2 Answers2

0

Cloud Run sets a unix socket, so you need to use a path that uses that unixSocketPath.

jdbc:mysql:///<DATABASE_NAME>?unixSocketPath=</PATH/TO/UNIX/SOCKET>&cloudSqlInstance=<INSTANCE_CONNECTION_NAME>&socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=<MYSQL_USER_NAME>&password=<MYSQL_USER_PASSWORD>

a Cloud Run unixsocket path looks like:

/cloudsql/{connection_id}

the {connection_id} may have this format: GCP_PROJECT:GCP_REGION:DBNAME

so essentially in your connectionString, you should have:

?unixSocketPath=/cloudsql/myproject:us-central1:my_instance

Pentium10
  • 204,586
  • 122
  • 423
  • 502
  • Ok this means that I need to remove from dockefile download cloud auth proxy and launch before to launch springboot application. Then set url db as explained above username and password. I try it. Thanks for your help. – SkyBlackHawk Jun 25 '21 at 09:21
  • ok I set: `SPRING_DATASOURCE_URL=jdbc:mysql:///DB_NAME;unix_socket=/cloudsql/GCP_PROJECT_ID:GCP_REGION:GCP_CLOUD_SQL&socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=USERNAME&password=PASSWORD` Enabled logging hikariCp but doesn't connect. Is it possible that I need to create in dockerfile the directory /cloudsql/? But no error in startup about it – SkyBlackHawk Jun 25 '21 at 09:49
  • errors in cloud run logs: `[ main] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to create/setup connection: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Cannot acquire connection from data source com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.` – SkyBlackHawk Jun 25 '21 at 10:02
  • I changed unix_socket from /cloudsql to /tmp because I had in dockerfile a tmp volume: `SPRING_DATASOURCE_URL=jdbc:mysql:///DB_NAME;unix_socket=/cloudsql/GCP_PROJECT_ID:GCP_REGION:GCP_CLOUD_SQL&socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=USERNAME&password=PASSWORD` – SkyBlackHawk Jun 25 '21 at 10:03
  • I solved it thanks for your support. Your solution helped me but it doesn't solve. Thanks a lot for your time! – SkyBlackHawk Jun 25 '21 at 12:09
  • It's great that you've found a working solution. Yours need a service account key which can be a trouble factor. If you deploy your Cloud Run service by specifying the connection link, then the unix socket is automatically created for you. And that solution is simpler as it doesn't need any other per docker requirements. When you have time explore this solution as well. – Pentium10 Jun 25 '21 at 13:20
0

SOLUTION:

  1. Create json key for service account tipical name:

    GCP_PROJECT_ID-GCP_ID_SERVICE_ACCOUNT-compute_developer_gserviceaccount_com

    and save json key file in assets directory (under root of java project) where you have entrypoint.sh.

  2. In DockerFile add line for json service account key:

    RUN export GOOGLE_APPLICATION_CREDENTIALS=assets/GCP_PROJECT_ID-GCP_ID_SERVICE_ACCOUNT-compute_developer_gserviceaccount_com-GCP_KEY.json

  3. pom.xml add below:

Used for sql auth proxy unix socket

<dependency>
    <groupId>com.google.cloud.sql</groupId>
    <artifactId>mysql-socket-factory</artifactId>
    <version>1.3.0</version>
</dependency>
<dependency>
    <groupId>com.google.api-client</groupId>
    <artifactId>google-api-client</artifactId>
    <version>1.32.1</version>
</dependency>

Connector mysql:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
  1. In application.properties or application-test.properties (if you use spring profile to deploy in TEST GCP cloud run):

    spring.datasource.url=jdbc:mysql://google/DB_SCHEMA?cloudSqlInstance=GCP_PROJECT_ID:GCP_REGION:DB_ISTANCE&socketFactory=com.google.cloud.sql.mysql.SocketFactory&useSSL=false

    spring.datasource.username=*****

    spring.datasource.password=*****

  2. DEPLOY SOLUTION

I will use gitlab variables and I will pass url,username and password but this is other work...

N.B.: com.google.cloud.sql.mysql.SocketFactory tell to use unix socket! Cloud Run when start it start sql auth proxy if in cloud run configuration in connection section set database (if in same project you will see a drop down list in alternative if it's in other project you will add manually GCP_PROJECT:GCP_REGION:DB). You can define multiple DB to connect but it's another job ;)

SkyBlackHawk
  • 95
  • 10
  • In line: spring.datasource.url=jdbc:mysql://google/DB_SCHEMA?cloudSqlInstance=GCP_PROJECT_ID:GCP_REGION:DB_ISTANCE&socketFactory=com.google.cloud.sql.mysql.SocketFactory&useSSL=false I removed &useSSL=false and it's work fine too – SkyBlackHawk Jun 28 '21 at 07:52