【问题标题】:Spring Cloud Gateway on Kubernetes discovery locator use pod port instead o service portKubernetes 发现定位器上的 Spring Cloud Gateway 使用 pod 端口而不是服务端口
【发布时间】:2020-05-22 12:52:58
【问题描述】:

我正在使用 spring cloud gateway 和 spring cloud kubernetes discovery 在 openshift 上实现一个 API 网关。

我从项目https://github.com/salaboy/s1p_gateway开始。

我的网关配置是:

cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          url-expression: "'http://'+serviceId+':'+port"
    kubernetes:
      reload:
        enabled: true
        mode: polling
        period: 5000
      discovery:
        service-labels:
           type: "java-api"

当我查看我的 /actuator/gateway/routes 时,我可以看到发现的服务:

{
   "predicate":"Paths: [/common/**], match trailing slash: true",
   "route_id":"ReactiveCompositeDiscoveryClient_common",
   "filters":[
      "[[RewritePath /common/(?<remaining>.*) = '/${remaining}'], order = 1]"
   ],
   "uri":"http://common:8085",
   "order":0
}

问题在于 8085 是 targetPort(即 pod 端口)而不是服务端口:

kind: Service
apiVersion: v1
metadata:
  name: common
  namespace: p4p
  selfLink: /api/v1/namespaces/myspace/services/common
  uid: 1851a76f-4764-11ea-a02c-000d3aa9b693
  resourceVersion: '28657990'
  creationTimestamp: '2020-02-04T15:36:21Z'
  labels:
    app: common
    type: java-api
spec:
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8085
  selector:
    app: common
    deploymentconfig: common
  clusterIP: 172.30.7.24
  type: ClusterIP
  sessionAffinity: None
status:
  loadBalancer: {}

为了让 API 网关工作,我必须对齐 pod 端口和服务端口,但这听起来很奇怪。

【问题讨论】:

  • 你好,你解决问题了吗?当有多个实例(pod)时我会出现同样的错误,但当有一个 pod 时不会出错。
  • 嗨,我对齐了 pod 端口和服务端口。每个容器都使用“-Dserver.port=8080”启动spring-boot。

标签: spring-boot kubernetes spring-cloud spring-cloud-kubernetes


【解决方案1】:

是否正在使用功能区?功能区的默认 spring.cloud.kubernetes.ribbon.mode 是 POD。来自docs(引用):

spring.cloud.kubernetes.ribbon.mode 支持PODSERVICE 模式。

  • POD模式是通过获取Pod IP实现负载均衡 Kubernetes 的地址并使用 Ribbon。 POD 模式使用负载 Ribbon 的平衡 不支持 Kubernetes 负载平衡, 不支持 Istio 的流量策略。

  • SERVICE 模式直接基于 Ribbon 的服务名称。 获取 Kubernetes 服务被串联成 service-name.{namespace}.svc.{cluster.domain}:{port} 如: demo1.default.svc.cluster.local:8080SERVICE 模式使用负载 平衡 Kubernetes 服务以支持 Istio 的流量策略。

【讨论】:

  • 当我尝试通过网关调用 rest api 时,我得到 There was an unexpected error (type=Internal Server Error, status=500). finishConnect(..) failed: Host is unreachable: common/172.30.7.24:8085 并且服务是 Name: common Type: ClusterIP IP: 172.30.7.24 Port: &lt;unset&gt; 8080/TCP TargetPort: 8085/TCP Endpoints: 10.129.3.101:8085 似乎使用了服务 IP 和 pod 端口。我还添加了spring.cloud.kubernetes.ribbon.mode=SERVICE,但没有任何改变。
【解决方案2】:

您为什么不能简单地将Service port (port) 设置为8085,以便它公开与Pod 相同的端口?实际上没有什么能阻止你这样做。

当我尝试通过网关调用 rest api 时,我得到了

There was an unexpected error (type=Internal Server Error, status=500). finishConnect(..) failed: Host is unreachable: common/172.30.7.24:8085

服务是

Name: common Type: ClusterIP IP: 172.30.7.24 Port: <unset> 8080/TCP TargetPort: 8085/TCP Endpoints: 10.129.3.101:8085

似乎使用了服务 IP 和 pod 端口。我还添加了 spring.cloud.kubernetes.ribbon.mode=SERVICE 但没有任何改变。

从您发布的内容来看,当您尝试通过网关调用您的 rest api 时,它希望使用您的Service IP (172.30.7.24) 和端口8085 公开它,所以只需公开它该端口应该可以正常工作:

...
spec:
  ports:
    - protocol: TCP
      port: 8085
      targetPort: 8085
...

如果有帮助请告诉我。

【讨论】:

  • 这正是问题的结尾:“...为了让 API 网关正常工作,我必须对齐 pod 端口和服务端口,但这听起来很奇怪”。
  • 是的,我注意到了这一点,我在问为什么这听起来很奇怪,因为对我来说,通过Service 公开 api 客户端期望的正确端口并没有什么奇怪的?你能解释一下吗?
  • 不,我无法解释。我猜这可能是一个错误,但还没有机会查看代码(前段时间存在多个端口的问题 - 只有第一个被选中......如果我记得的话)。所以,我同意,将 porttargetPort 设置为相同可能是一种解决方法。
猜你喜欢
  • 2020-07-14
  • 1970-01-01
  • 2015-02-10
  • 2018-10-16
  • 2018-10-31
  • 1970-01-01
  • 1970-01-01
  • 2019-01-28
  • 1970-01-01
相关资源
最近更新 更多