Docker Desktop中本地Dapr无法调用K8s集群内服务排查
问题描述
Windows 10系统Docker Desktop已启用K8s集群,集群内多个微服务通过Dapr调用正常。本地使用dapr run -k ...启动.NET 8微服务,启动日志正常,但通过.NET Dapr Client调用K8s内k8sServiceName服务失败,报错连接10.1.0.145:50002超时(该IP端口对应服务正确,Postman可访问)。同时执行dapr invoke -a k8sServiceName -m myMethod提示app ID未找到。
已做配置:
- 转发Redis端口
- 使用Consul做服务发现
- 所有工具及NuGet包均为最新版
相关代码与配置如下:
.NET Dapr Client调用代码
async Task<TResponse> RequestAsyncTest<TRequest, TResponse>(string appId, string methodName, TRequest request, HttpMethod httpMethod = default, string apiKey = default) { // this.daprClient is an instance of Dapr.Client.DaprClient from the Dapr.Client by dapr.io nuget package. using var httpRequest = this.daprClient.CreateInvokeMethodRequest(httpMethod, appId, methodName, request); using var response = await this.daprClient.InvokeMethodWithResponseAsync(httpRequest); var resultContent = await response.Content.ReadAsStringAsync(); if (!response.IsSuccessStatusCode) { this.logger.LogError($"Calling {appId} {methodName} error response: {response} Result: {resultContent} Request:{httpRequest}"); } var resultString = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject<TResponse>(resultString, converters); return result; }
本地启动命令
dapr run -k --app-protocol https --enable-app-health-check --enable-profiling --app-id myAppId --app-port 44381 --resources-path "..\Solution Items\Dapr" --config "..\Solution Items\Dapr\daprConfig.yaml" dotnet watch run
Dapr组件配置(dapr.yml)
apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: pubsub-servicebus spec: type: pubsub.redis version: v1 metadata: - name: redisHost value: localhost:6379 - name: redisPassword value: "redisPasswordGoesHere" --- apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: consul namespace: default spec: type: state.consul version: v1 metadata: - name: datacenter value: dc1 # Required. Example: dc1 - name: httpAddr value: host.docker.internal:8500
Dapr配置文件(daprConfig.yml)
apiVersion: dapr.io/v1alpha1 kind: Configuration metadata: name: daprconfig-myAppId spec: nameResolution: version: v1 component: "consul" configuration: client: address: host.docker.internal:8500 selfRegister: true checks: - name: "Dapr Health Status-myAppId" checkID: "daprHealth:myAppId" http: "http://host.docker.internal:51044/systeminfo/configinfo" interval: "15m" timeout: "300s" deregisterCriticalServiceAfter: "2m"
解决方案
1. 解决跨环境网络访问问题
核心原因是K8s集群内部IP(10.1.0.145)无法被Windows本地环境直接访问,Postman能访问是因为做了端口转发,但Dapr通过服务发现拿到的是集群内部IP,导致调用超时。
- 配置K8s服务为NodePort类型,暴露可被本地访问的端口:
apiVersion: v1 kind: Service metadata: name: k8sServiceName spec: type: NodePort ports: - port: 80 # 服务内部端口 targetPort: 80 # Pod端口 nodePort: 30001 # 自定义未占用端口 selector: app: k8sServiceName - 修改K8s内服务的Dapr注解,指定注册到Consul的外部可访问地址:
annotations: dapr.io/enabled: "true" dapr.io/app-id: "k8sServiceName" dapr.io/app-port: "80" dapr.io/config: "daprconfig" # 需与本地使用的Consul配置一致 dapr.io/register-address: "host.docker.internal:30001" # 注册本地可访问的地址
2. 验证Consul服务注册一致性
- 访问Consul控制台(
http://localhost:8500),检查:k8sServiceName是否已注册,且注册地址为host.docker.internal:30001- 本地
myAppId是否正常注册,健康检查状态为passing
- 若健康检查失败,检查
daprConfig.yml中的健康检查地址http://host.docker.internal:51044/systeminfo/configinfo是否正确,确保该端口对应本地服务的健康检查接口,且接口能正常返回200状态码。
3. 调整本地Dapr运行模式
本地服务运行在Windows主机而非K8s Pod内,使用-k参数(K8s模式)可能导致网络隔离问题,建议改用本地模式启动:
dapr run --app-protocol https --enable-app-health-check --enable-profiling --app-id myAppId --app-port 44381 --resources-path "..\Solution Items\Dapr" --config "..\Solution Items\Dapr\daprConfig.yaml" dotnet watch run
4. 验证服务发现与连通性
- 执行
curl http://localhost:8500/v1/catalog/service/k8sServiceName,确认返回的服务地址是本地可访问的 - 执行
dapr list,确认本地myAppId的sidecar正常运行 - 重新执行
dapr invoke -a k8sServiceName -m myMethod,验证是否能正常调用
内容的提问来源于stack exchange,提问作者user25677466
相关产品推荐
相关产品推荐

