无法从在具有自定义运行时的 Docker 中运行 .NET Core 应用程序的 App Engine 连接到 Google Cloud SQL 中的 postgres

Posted

技术标签:

【中文标题】无法从在具有自定义运行时的 Docker 中运行 .NET Core 应用程序的 App Engine 连接到 Google Cloud SQL 中的 postgres【英文标题】:Unable to connect to postgres in Google Cloud SQL from App Engine running a .NET Core app in Docker with Custom runtime 【发布时间】:2020-07-04 14:54:09 【问题描述】:

我尝试了很多方法,但在尝试从我的 Google Cloud App Engine 连接到 Google Cloud PostgreSQL 实例时似乎无法通过 Exception while connecting

这可能是我作为开发人员处理过的最令人沮丧的事情。连接数据库应该没那么难。

我做错了什么?

没用的东西:

How to connect Google Cloud SQL via Google App engine Flex to botnet core app? Unable to connect to postgres in cloud sql from google app engine nodes https://cloud.google.com/sql/docs/postgres/connect-app-engine-flexible https://github.com/GoogleCloudPlatform/dotnet-docs-samples/tree/master/appengine/flexible/CloudSql

app.yaml:

runtime: custom
env: flex
beta_settings:
  cloud_sql_instances: "<project-id>:<region>:<sql-instance>=tcp:5432"

最终使用的连接字符串:

Uid=<db_user>;Pwd=<db_password>;Host=cloudsql;Database=<db_name>

// other attempts:
Uid=<db_user>;Pwd=<db_password>;Host=cloudsql;Database=<db_name>;Port=5432
Uid=<db_user>;Pwd=<db_password>;Host=/cloudsql/<project-id>:<region>:<sql-instance>;Database=<db_name>
Uid=<db_user>;Pwd=<db_password>;Host='/cloudsql/<project-id>:<region>:<sql-instance>';Database=<db_name>
Uid=<db_user>;Pwd=<db_password>;Server='/cloudsql/<project-id>:<region>:<sql-instance>';Database=<db_name>

用法:

var connectionString = new NpgsqlConnectionStringBuilder(<connection string>)

    SslMode = SslMode.Disable
;

NpgsqlConnection connection =
    new NpgsqlConnection(connectionString.ConnectionString);

connection.Open();

相关堆栈跟踪:

Exception while connecting
   at Npgsql.NpgsqlConnector.Connect(NpgsqlTimeout timeout)
   at Npgsql.NpgsqlConnector.RawOpen(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
   at Npgsql.NpgsqlConnector.Open(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
   at Npgsql.ConnectorPool.AllocateLong(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
   at Npgsql.NpgsqlConnection.<>c__DisplayClass32_0.<g__OpenLong|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Npgsql.NpgsqlConnection.Open()

Dockerfile(也许这很重要,因为我在 app.yaml runtime 中使用了custom?):

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 8080
EXPOSE 443
ENV ASPNETCORE_URLS=http://*:8080

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
COPY . /src
WORKDIR /src
RUN dotnet restore --packages /packages
RUN dotnet publish -c Release -o /published

FROM base AS final
COPY --from=build /published /app/
WORKDIR /app
ENTRYPOINT [ "dotnet", "myapp.dll" ]

部署脚本:

gcloud beta app deploy --project <project-id>

编辑:

从我的 sql 实例的云控制台检查 PostgreSQL 错误,我在最终的 Exception while connecting 错误之前看到以下错误:

System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (99): Cannot assign requested address /cloudsql/<my connection instance id>/.s.PGSQL.5432

【问题讨论】:

只是为了排除几个常见问题:您是否检查过 SQL Admin API 已启用? App Engine 服务帐户是否还具有docs 中列出的权限?使用 aspnet GCP 提供的运行时而不是自定义运行时,您是否遇到过同样的问题? 是的,为项目启用了 SQL Admin API。为了排除 App Engine 服务帐户权限,我目前将Cloud SQL Client 角色分配给我的 IAM 列表中列出的每个帐户。我也尝试过使用Cloud SQL Admin 角色。最后,希望是在我的app.yaml 中使用custom 运行时而不是aspnetcore 运行时的问题,我也将其更改为使用aspnetcore,但仍然看到相同的结果。 【参考方案1】:

您是否查看过 Cloud SQL here 的示例应用程序?

更新:

很难确定哪里出了问题,因为您提供了几个不同的选项,而且还不清楚哪些组合会导致哪些错误。但是,基本上有 2 种不同的连接方式,重要的是您的代码与 app.yaml 中的配置相匹配:

通过 TCP 端口连接

要通过 TCP 端口连接,请在 app.yaml 中使用以下内容:

beta_settings:
  cloud_sql_instances: "<PROJECT_ID>:<REGION_ID>:<INSTANCE_ID>=tcp:5432"

然后为您的连接字符串使用以下格式:

"Host=172.17.0.1;Uid=<DB_USER>;Pwd=<DB_PASS>;Database=<DB_NAME>"

请注意,Host=172.17.0.1; 是部署到 Flex 时的 IP,但如果在本地使用 Cloud SQL 代理,则为 127.0.0.1

通过 Unix 域套接字连接

要通过 Unix 套接字连接,请在 app.yaml 中使用以下内容:

beta_settings:
  cloud_sql_instances: "<PROJECT_ID>:<REGION_ID>:<INSTANCE_ID>"

然后为您的连接字符串使用以下格式:

"Server=/cloudsql/<PROJECT_ID>:<REGION_ID>:<INSTANCE_ID>/.s.PGSQL.5432;Uid=<DB_USER>;Pwd=<DB_PASS>;Database=<DB_NAME>"

注意:您的驱动程序可能会自动添加 /.s.PGSQL.5432 - 有些会,有些不会。

疑难解答

如果您确定您的 app.yaml 和代码正确匹配,但仍然收到超时消息,下一步是检查您的应用程序日志。您可以使用 Stackdriver 并按 appengine.googleapis.com/cloud_sql_proxy 过滤以仅查看您的实例的日志。

一些常见的错误是:

    实例没有公共 IP(私有 IP 连接步骤不同) App Engine 所在的项目中未启用 Cloud SQL Admin API 使用的服务帐户(默认为 service-PROJECT_NUMBER@gae-api-prod.google.com.iam.gserviceaccount.com)不具有数据库所在项目的 Cloud SQL Client IAM 角色或更高级别

【讨论】:

是的。在将我的具体详细信息添加到appsettings.json 中找到的连接字符串(Uid、Pwd、数据库)并离开Host=cloudsql; 后,我收到一条错误消息Cannot find service or name。如果我限定主机的值,如下所示:Host=/cloudsql/&lt;project-id&gt;:&lt;region&gt;:&lt;sql-instance&gt;;,那么我会得到与原始帖子中提到的相同的错误。 @MichaelHarris - 我添加了一些可能有用的额外上下文。如果有帮助,请告诉我。

以上是关于无法从在具有自定义运行时的 Docker 中运行 .NET Core 应用程序的 App Engine 连接到 Google Cloud SQL 中的 postgres的主要内容,如果未能解决你的问题,请参考以下文章

在 Docker 中运行的自定义 Azure DevOps 构建代理上具有卷装载的测试容器

使用 DynamoDB 和 Graal 自定义运行时的 Micronaut 无服务器应用程序抛出无法构造 com.amazonaws.partitions.model.Partitions 的实例

如何运行自定义 docker 镜像 testContainer

具有自定义 php.ini 文件设置的 Docker Wordpress 容器

如何从在 AWS ecs 上使用 docker 部署的应用程序获取日志

自定义镜像-docker