使用 Spring 引导将云 运行 应用程序连接到云 SQL 时出现问题

Problems connecting Cloud Run Application to Cloud SQL using Spring boot

我正在尝试将 Spring 应用程序(使用 Kotlin 和 Gradle)连接到 Google 云 SQL 实例和数据库。我收到错误消息

java.lang.RuntimeException: [<project-name>:europe-west1:<db-instance>] The Cloud SQL Instance does not exist or your account is not authorized to access it. Please verify the instance connection name and check the IAM permissions for project "<project-name>"

我已经仔细按照guide如何连接,但是没有用。

相关文件

src/main/resources/application.yml

server:
  port: ${PORT:8080}

spring:
  liquibase:
    change-log: classpath:liquibase/db.changelog.xml
    contexts: production

  cloud:
    appId: <project-id>
    gcp:
      sql:
        instance-connection-name: <instance-connection-name>
        database-name: <db-name>
  jpa:
    hibernate:
      dialect: org.hibernate.dialect.MySQL8Dialect
      default_schema: <schema>
      show_sql: true
      ddl-auto: none

  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    continue-on-error: true
    initialization-mode: always
    url: jdbc:mysql:///<db-name>?cloudSqlInstance=<instance-connection-name>&socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=<user>&password=<password>
    username: <user>
    password: <password>

---
spring:
  config:
    activate:
      on-profile: dev

  jpa:
    hibernate:
      ddl-auto: create-drop
    spring.jpa.database-platform: org.hibernate.dialect.H2Dialect

  datasource:
    url: jdbc:h2:mem:mydb
    username: sa
    password: password
    driverClassName: org.h2.Driver

  cloud:
    gcp:
      sql:
        enabled: false

build.gradle.kts

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
        id("org.springframework.boot") version "2.6.5"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
    kotlin("jvm") version "1.6.10"
    kotlin("plugin.spring") version "1.6.10"
    kotlin("plugin.allopen") version "1.4.32"
    kotlin("plugin.jpa") version "1.4.32"
    kotlin("kapt") version "1.4.32"
}

allOpen {
    annotation("javax.persistence.Entity")
    annotation("javax.persistence.Embeddable")
    annotation("javax.persistence.MappedSuperclass")
}

group = "com.<company>"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17

repositories {
    mavenCentral()
}

dependencies {

    implementation("org.springframework.boot:spring-boot-starter-web:2.6.5")
    implementation("org.springframework.boot:spring-boot-starter-webflux:2.6.5")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa:2.6.5")
    implementation("org.springframework.cloud:spring-cloud-gcp-starter-sql-mysql:1.2.8.RELEASE")

    implementation("org.jetbrains.kotlin:kotlin-reflect:1.6.10")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.10")

    implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.13.2")
    implementation("com.fasterxml.jackson.core:jackson-annotations:2.13.2")
    implementation("com.fasterxml.jackson.core:jackson-core:2.13.2")
    implementation("com.fasterxml.jackson.core:jackson-databind:2.13.2.2")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.2")
    implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2")

    implementation("org.hibernate:hibernate-core:5.6.7.Final")
    implementation("javax.persistence:javax.persistence-api:2.2")

    implementation( "commons-codec:commons-codec:1.15")

    implementation("io.github.microutils:kotlin-logging-jvm:2.1.21")
    implementation("ch.qos.logback:logback-classic:1.2.11")

    implementation("com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.4.4")
    runtimeOnly("com.h2database:h2:2.1.210")
    runtimeOnly("org.springframework.boot:spring-boot-devtools:2.6.5")

    testImplementation("org.springframework.boot:spring-boot-starter-test:2.6.5")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "17"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

Docker文件

FROM openjdk:17-alpine
ENV USER=appuser
# <placeholder> Replace context path for your own application
ENV JAVA_HOME=/opt/openjdk-17 \
    HOME=/home/$USER \
    CONTEXT_PATH=/aws-service-baseline

RUN adduser -S $USER
# <placeholder> Add additional packages for the docker container here
RUN apk add --no-cache su-exec

# <placeholder> Replace baseline.jar with your applications JAR file (defined in build.gradle.kts)
COPY Docker/runapp.sh build/libs/<application-name>-0.0.1-SNAPSHOT.jar $HOME/
RUN chmod 755 $HOME/*.sh && \
    chown -R $USER $HOME


WORKDIR /home/$USER
CMD [ "./runapp.sh"]

Docker/runapp.sh

#!/bin/sh
set -e

# The module to start.
# <placeholder> Replace this with your own modulename (from module-info)
APP_JAR="<application-name>-0.0.1-SNAPSHOT.jar"
JAVA_PARAMS="-XshowSettings:vm"

echo " --- RUNNING $(basename "[=17=]") $(date -u "+%Y-%m-%d %H:%M:%S Z") --- "
set -x

/sbin/su-exec "$USER:1000" "$JAVA_HOME/bin/java" "$JAVA_PARAMS $JAVA_PARAMS_OVERRIDE" -jar -Dserver.port=$PORT "$APP_JAR"

GCP 详细信息

我已确保 SQL 实例连接已添加到云端 运行 修订版。计算服务帐户的 IAM 角色似乎也是正确的。查看图片

IAM:https://i.stack.imgur.com/yYaC5.png

数据库:https://i.stack.imgur.com/NErad.png

云运行连接https://i.stack.imgur.com/fKTSZ.png

其他详细信息

当在我的本地机器上 运行ning ./gradlew bootRun 时(存在 GCP 凭据),应用程序可以在 SQL 连接下正常工作。它也可以在 运行ning ./gradle bootRun 构建 JAR 文件和直接 运行 JAR 之后工作。在 Docker 中 运行ning 时,它无法开箱即用,但如果我将 GCP 凭据添加到本地 Docker 容器,它会连接到数据库。

有人对可能出现的问题有任何建议吗?非常感谢任何帮助!

我已经尝试在 Docker 容器中进行本地和本地连接。

想通了!当然是人为错误。 Cloud 运行 服务最初配置了另一个服务帐户,而不是默认的 Compute Engine 服务帐户。