i'm implementing an API Gateway on openshift with spring cloud gateway and spring cloud kubernetes discovery.
I started from the project https://github.com/salaboy/s1p_gateway.
My gateway configuration is:
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"
When i view my /actuator/gateway/routes i can see services discovered:
{
"predicate":"Paths: [/common/**], match trailing slash: true",
"route_id":"ReactiveCompositeDiscoveryClient_common",
"filters":[
"[[RewritePath /common/(?<remaining>.*) = '/${remaining}'], order = 1]"
],
"uri":"http://common:8085",
"order":0
}
The problem is that 8085 is the targetPort (i.e. pod port) and not the service port:
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: {}
In order to get API gateway to work i MUST to align pod port and service port, but it sounds quite strange.
Why cannot you simply set Service port (port)
to 8085
so it exposes the same port as Pod
does ? Nothing actually prevents you from doing so.
When i try to call rest api via gateway i get
There was an unexpected error (type=Internal Server Error, status=500). finishConnect(..) failed: Host is unreachable: common/172.30.7.24:8085
and the service is
Name: common Type: ClusterIP IP: 172.30.7.24 Port: <unset> 8080/TCP TargetPort: 8085/TCP Endpoints: 10.129.3.101:8085
It seems uses the service IP and the pod port. I have also added
spring.cloud.kubernetes.ribbon.mode=SERVICE
but nothing has changed.
From what you posted it looks like when you're trying to call your rest api via gateway it expects it to be exposed using your Service
IP (172.30.7.24
) and port 8085
, so simply expose it on that port and it should work fine:
...
spec:
ports:
- protocol: TCP
port: 8085
targetPort: 8085
...
Please let me know if it helps.
Is Ribbon being used? Ribbon's default spring.cloud.kubernetes.ribbon.mode
is POD. From the docs (quote):
spring.cloud.kubernetes.ribbon.mode
supportsPOD
andSERVICE
modes.
The
POD
mode is to achieve load balancing by obtaining the Pod IP address of Kubernetes and using Ribbon. POD mode uses the load balancing of the Ribbon Does not support Kubernetes load balancing, The traffic policy of Istio is not supported.the
SERVICE
mode is directly based on the service name of the Ribbon. Get The Kubernetes service is concatenated intoservice-name.{namespace}.svc.{cluster.domain}:{port}
such as:demo1.default.svc.cluster.local:8080
. theSERVICE
mode uses load balancing of the Kubernetes service to support Istio’s traffic policy.