首页 > 解决方案 > 从函数应用访问虚拟网络中的 Cosmos DB

问题描述

很抱歉这篇长文,但我已经在这个问题上工作了好几天,我似乎无法找到解决方案。

情况

我想通过将 Cosmos DB 放置在虚拟网络 (VNet) 中来限制对 Azure 中的 Cosmos DB 的访问,并且只允许通过函数应用程序进行访问。

方法

第一部分很简单:创建 Cosmos DB 和 VNet,并按照此处所述配置数据库的服务终结点。

可以通过两种方式将函数应用连接到 VNet。

使用网关

按照指南,我已为我的 VNet 配置了网关子网,并按所述添加和配置了 VPN 网关。

之后,我将网关子网添加到 Cosmos DB 服务端点配置并设置我的 Function App

使用 VNet(预览)功能选择子网

这种方法更容易设置,但如microsoft 文档中所述,它不适用于生产工作负载。
配置更容易,但由于结果相同,我在本文的其余部分省略了此选项。

配置

虚拟网络

网关子网配置

网关

点对点配置

宇宙数据库

Cosmos DB 配置

功能应用

函数应用 VNet 配置

问题

尝试从我的函数应用连接到 Cosmos DB 时,我不断收到连接错误:

{
    "Message": "An error has occurred.",
    "ExceptionMessage": "Unable to proceed with the request. Please check the authorization claims to ensure the required permissions to process the request.\r\nActivityId: f784890f-2e1a-4e36-bfb9-8f62ff32c034, Microsoft.Azure.Documents.Common/2.2.0.0, Windows/10.0.14393 documentdb-netcore-sdk/2.2.2",
    "ExceptionType": "Microsoft.Azure.Documents.DocumentClientException",
    "StackTrace": "   at Microsoft.Azure.Documents.Client.ClientExtensions.ParseResponseAsync(HttpResponseMessage responseMessage, JsonSerializerSettings serializerSettings, Boolean throwOnKnownClientErrorCodes)\r\n   at Microsoft.Azure.Documents.Client.GatewayServiceConfigurationReader.GetDatabaseAccountAsync(Uri serviceEndpoint)\r\n   at Microsoft.Azure.Documents.Routing.GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync(Uri defaultEndpoint, IList`1 locations, Func`2 getDatabaseAccountFn)\r\n   at Microsoft.Azure.Documents.Client.GatewayServiceConfigurationReader.InitializeReaderAsync()\r\n   at Microsoft.Azure.Documents.Client.DocumentClient.InitializeGatewayConfigurationReader()\r\n   at Microsoft.Azure.Documents.Client.DocumentClient.GetInitializationTask()\r\n   at Microsoft.Azure.Documents.Client.DocumentClient.EnsureValidClientAsync()\r\n   at Microsoft.Azure.Documents.Client.DocumentClient.ReadDatabasePrivateAsync(String databaseLink, RequestOptions options, IDocumentClientRetryPolicy retryPolicyInstance)\r\n   at Microsoft.Azure.Documents.BackoffRetryUtility`1.<>c__DisplayClass1_0.<<ExecuteAsync>b__0>d.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at Microsoft.Azure.Documents.BackoffRetryUtility`1.ExecuteRetryAsync(Func`1 callbackMethod, Func`3 callShouldRetry, Func`1 inBackoffAlternateCallbackMethod, TimeSpan minBackoffForInBackoffCallback, CancellationToken cancellationToken, Action`1 preRetryCallback)\r\n   at Microsoft.Azure.Documents.ShouldRetryResult.ThrowIfDoneTrying(ExceptionDispatchInfo capturedException)\r\n   at Microsoft.Azure.Documents.BackoffRetryUtility`1.ExecuteRetryAsync(Func`1 callbackMethod, Func`3 callShouldRetry, Func`1 inBackoffAlternateCallbackMethod, TimeSpan minBackoffForInBackoffCallback, CancellationToken cancellationToken, Action`1 preRetryCallback)\r\n   at Microsoft.Azure.Documents.BackoffRetryUtility`1.ExecuteAsync(Func`1 callbackMethod, IRetryPolicy retryPolicy, CancellationToken cancellationToken, Action`1 preRetryCallback)\r\n   at Microsoft.Azure.Documents.Client.DocumentClient.CreateDatabaseIfNotExistsPrivateAsync(Database database, RequestOptions options)\r\n   at VnetTestFunction.Function1.Run(HttpRequest req, ILogger log) in C:\\Development\\VnetTestFunction\\VnetTestFunction\\Function1.cs:line 39"
}

这些方法之间没有区别。在这两种情况下,我的函数应用程序和数据库之间都没有连接。

作为测试,我按照教程添加了一个虚拟机并设置了一个代理。这有效,因此函数应用可以访问 VNet。

我的直觉说这是某个地方的一些配置问题,但我无法找出在哪里。我会继续搜索,但非常感谢任何帮助。

使用的在线资源

标签: azure-functionsazure-cosmosdbazure-virtual-network

解决方案


我相信您的配置是正确的,因为这两种方法都不应该按您的意愿工作。

对于VNet 集成功能,您可以使用此网关安全地访问 VNet 中的资源。

VNet 集成使您的 Web 应用程序(或函数应用程序)可以访问您的虚拟网络中的资源,但不会授予您从虚拟网络对您的 Web 应用程序的专用访问权限。

此外,Cosmos DB 不是 Azure VNet 中的资源,实际上您并没有使用此方法限制从 Azure 函数到 Cosmos DB 的访问。您的 Function App 已连接到 Internet 和您的 VNET。它仍然可以通过 Internet 从 Function App 到 Cosmos DB 工作。

此外,一旦您在特定子网中启用 Cosmos DB 服务终结点,这确实会限制对 Azure Cosmos DB 帐户的访问,该帐户具有来自虚拟网络中此授权子网的连接。如果您只在 Cosmos DB 的防火墙中配置授权子网,我认为只有来自授权子网的请求才能绕过防火墙。在这种情况下,Azure 函数也不是授权子网中的资源。

当您在 Azure VNet 中添加 VM 并按照将 Function App 与 Azure 虚拟网络集成的过程设置代理时。在这种情况下,VM 是部署在 Azure VNet 中的资源。因此,您可以使用 VNet 集成功能在专用 VNet 中访问它。

据我所知,如果你想在 VNet 中使用 Azure Function App,你可以在App Service Environments中部署应用服务,它将 Azure App Service 直接部署到 Azure 虚拟网络中。当然,这是一个非常高的规模和成本。


推荐阅读