Spring Cloud Kubernetes + Spring Cloud Gateway:无法找到 k8s 服务的实例
Posted
技术标签:
【中文标题】Spring Cloud Kubernetes + Spring Cloud Gateway:无法找到 k8s 服务的实例【英文标题】:Spring Cloud Kubernetes + Spring Cloud Gateway: Unable to find instance for k8s service 【发布时间】:2019-12-26 21:16:11 【问题描述】:我正在使用 Spring Cloud Kubernetes + Spring Cloud Gateway(SCG),但在 GKE 上部署我的应用程序时遇到了一些麻烦。 SCG没有找到k8s服务,我还是报这个错:
There was an unexpected error (type=Service Unavailable, status=503).
Unable to find instance for uiservice
uiservice
是 Angular 应用程序。
当我查看.../actuator/gateway/routes
时,我得到了这个结果:
[
"route_id": "CompositeDiscoveryClient_gateway",
"route_definition":
"id": "CompositeDiscoveryClient_gateway",
"predicates": [
"name": "Path",
"args":
"pattern": "/gateway/**"
],
"filters": [
"name": "RewritePath",
"args":
"regexp": "/gateway/(?<remaining>.*)",
"replacement": "/$remaining"
],
"uri": "lb://gateway",
"order": 0
,
"order": 0
,
"route_id": "CompositeDiscoveryClient_uiservice",
"route_definition":
"id": "CompositeDiscoveryClient_uiservice",
"predicates": [
"name": "Path",
"args":
"pattern": "/uiservice/**"
],
"filters": [
"name": "RewritePath",
"args":
"regexp": "/uiservice/(?<remaining>.*)",
"replacement": "/$remaining"
],
"uri": "lb://uiservice",
"order": 0
,
"order": 0
,
"route_id": "uiservice_route",
"route_definition":
"id": "uiservice_route",
"predicates": [
"name": "Path",
"args":
"_genkey_0": "/*"
],
"filters": [],
"uri": "lb://uiservice",
"order": 0
,
"order": 0
,
....
]
请注意,服务很容易被发现,因为:"route_id": "CompositeDiscoveryClient_gateway"
和 "route_id": "CompositeDiscoveryClient_uiservice"
,这些路由不是我的(我没有定义它们)。
我看了一下这个帖子:How to set up Spring Cloud Gateway application so it can use the Service Discovery of Spring Cloud Kubernetes? 没有成功。
我的配置:
spring:
profiles:
active: prod
cloud:
kubernetes:
reload:
enabled: true
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: uiservice
allowedMethods: "*"
allowCredentials: true
maxAge: 7200
allowedHeaders: "*"
exposedHeaders:
- "Access-Control-Allow-Origin"
- "Access-Control-Allow-Methods"
- "Access-Control-Max-Age"
- "Access-Control-Allow-Headers"
- "Cache-Control"
- "Authorization"
- "Content-Type"
routes:
#======UISERVICE========
- id: uiservice_route
uri: lb://uiservice
predicates:
- Path=/* #default route
- id: uiservice_route_assets
uri: lb://uiservice
predicates:
- Path=/assets/**
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
restart:
enabled: true
另外,如何禁用网关自动发现?我不想要"route_id": "CompositeDiscoveryClient_gateway"
依赖关系:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-all</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
感谢您的帮助
【问题讨论】:
【参考方案1】:在浪费了一个下午之后,我终于找到了解决方案。我认为使用 Ribbon 时服务发现存在问题。我使用 k8s dns 服务发现而不是依赖 Ribbon,所以我的新配置是:
routes:
- id: uiservice_route
uri: http://uiservice:4200 # switch 'lb://' to 'http://'
predicates:
- Path=/*
K8s uiservice 配置:
apiVersion: v1
kind: Service
metadata:
name: uiservice
spec:
sessionAffinity: ClientIP
selector:
app: uiservice
ports:
- name: http
port: 4200
targetPort: ui-port
出现了一个新问题:为什么要使用 Ribbon 来负载均衡请求,因为 k8s 服务本身就是这样做的?
【讨论】:
我知道这是旧的,但回答你的“新问题”,你可能不需要使用功能区(见docs.spring.io/spring-cloud-kubernetes/docs/current/reference/…),除非你特别想要客户端负载平衡:spring-cloud-starter -kubernetes-ribbon【参考方案2】:设置以下属性
spring:
cloud:
gateway:
discovery:
locator:
enabled: false
【讨论】:
谢谢,将属性设置为false
解决了自动发现问题,但我仍然有Unable to find instance for uiservice
。
您认为这可能是功能区问题吗,因为当我设置 url-expression: "uri"
时一切正常,但这是一个糟糕的解决方案,因为请求不再是负载平衡的。
我终于找到了解决办法,见上,你能回答最后一个问题吗?谢谢
@akuma8 看来您已经花了很多时间来解决这个问题。你能解决吗?我在同一条船上,我的网关无法发现服务。你能提供一些指导吗?
@Amit 在下面看到我的回答***.com/a/57605600/6643803【参考方案3】:
应该是这样的:
spring:
application.name: gateway
cloud:
gateway:
discovery:
locator:
enabled: true
url-expression: "'http://'+serviceId+':'+getPort()"
lower-case-service-id: true
当调用http://gateway/my-service-name/api/etc
时,如果服务存在于kubernetes中则调用my-service-name/api/etc
所以你需要确保有这样的服务:
apiVersion: v1
kind: Service
metadata:
name: my-service-name
namespace: default
labels:
app: my-service-name
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30080
selector:
app: my-service-name
【讨论】:
以上是关于Spring Cloud Kubernetes + Spring Cloud Gateway:无法找到 k8s 服务的实例的主要内容,如果未能解决你的问题,请参考以下文章
spring-cloud-kubernetes官方demo运行实战
部署 spring-cloud-kubernetes kubernetes-hello-world-example 失败
Spring Cloud Kubernetes 支持 Spring Cloud 负载均衡器吗?