Spring Cloud Gateway в локаторе обнаружения Kubernetes использует порт модуля вместо порта службы

Я реализую API-шлюз на openshift с весенним облачным шлюзом и весенним облачным обнаружением кубернетов.

Я начал с проекта 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"

Когда я просматриваю свой / исполнительный механизм / шлюз / маршруты, я вижу обнаруженные службы:

{
   "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 (т. е. порт модуля), а не порт службы:

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 работал, я ДОЛЖЕН согласовать порт модуля и порт службы, но это звучит довольно странно.


person angcap    schedule 06.02.2020    source источник
comment
привет, вы решили проблему? Я получаю ту же ошибку, когда есть несколько экземпляров (модулей), но не ошибаюсь, когда есть один модуль.   -  person denizg    schedule 28.07.2020
comment
Привет, я выровнял порт стручка и сервисный порт. Каждый контейнер запускает весеннюю загрузку с -Dserver.port = 8080.   -  person angcap    schedule 29.07.2020


Ответы (2)


Лента используется? Лента по умолчанию spring.cloud.kubernetes.ribbon.mode - POD. Из документов (цитата ):

spring.cloud.kubernetes.ribbon.mode поддерживает режимы POD и SERVICE.

  • Режим POD предназначен для балансировки нагрузки путем получения IP-адреса Pod Kubernetes и использования ленты. В режиме POD используется балансировка нагрузки ленты. Не поддерживает балансировку нагрузки Kubernetes. Политика трафика Istio не поддерживается.

  • режим SERVICE напрямую основан на имени службы ленты. Получить сервис Kubernetes объединен в service-name.{namespace}.svc.{cluster.domain}:{port}, например: demo1.default.svc.cluster.local:8080. режим SERVICE использует балансировку нагрузки службы Kubernetes для поддержки политики трафика Istio.

person gears    schedule 06.02.2020
comment
Когда я пытаюсь вызвать 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-адрес службы и порт модуля. Я также добавил spring.cloud.kubernetes.ribbon.mode=SERVICE, но ничего не изменилось. - person angcap; 06.02.2020

Почему нельзя просто установить 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-адрес службы и порт модуля. Я также добавил spring.cloud.kubernetes.ribbon.mode=SERVICE, но ничего не изменилось.

Из того, что вы опубликовали, похоже, что когда вы пытаетесь вызвать свой rest api через шлюз, он ожидает, что он будет отображаться с использованием вашего Service IP (172.30.7.24) и порта 8085, поэтому просто выставьте его на этом порту, и он должен работать нормально:

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

Пожалуйста, дайте мне знать, если это поможет.

person mario    schedule 06.02.2020
comment
Именно так и заканчивается вопрос: ... Для того, чтобы шлюз API работал, я ДОЛЖЕН согласовать порт модуля и порт службы, но это звучит довольно странно. - person gears; 06.02.2020
comment
Да, я заметил это и спрашиваю, почему это звучит странно, потому что для меня нет ничего странного в том, чтобы выставить через Service правильный порт, который ожидает клиент api? Не могли бы вы это объяснить? - person mario; 06.02.2020
comment
Нет, я не могу этого объяснить. Думаю, это могла быть ошибка, но у меня не было возможности изучить код (некоторое время назад были проблемы с несколькими портами - был выбран только первый ... если я помню). Итак, установка одинаковых значений port и targetPort может быть обходным решением, я согласен. - person gears; 07.02.2020