spring-cloud-kubernetes
spring-cloud-kubernetes copied to clipboard
spring-cloud-kubernetes-discoveryserver: Null key for a Map not allowed in JSON for mssql service
Describe the bug
springcloud/spring-cloud-kubernetes-discoveryserver:2.1.1-SNAPSHOT (and 2.1.0 as well)
"http://127.0.0.1:35795/apps" gives 500 "EncodingException: JSON encoding error: Null key for a Map not allowed in JSON " when deploy mssql
image
When i remove mssql
service with next command it works fine.
minikube kubectl -- delete service mssql2
Sample deployment scripts have been attached
minikube version: v1.24.0 commit: 76b94fb3c4e8ac5062daf70d60cf03ddcc0a741b Docker version 20.10.12, build e91ed57
NAME="Ubuntu" VERSION="20.04.3 LTS (Focal Fossa)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.04.3 LTS" VERSION_ID="20.04"
Exception: 2021-12-16 06:46:28.109 ERROR 1 --- [undedElastic-16] a.w.r.e.AbstractErrorWebExceptionHandler : [c379292a-1] 500 Server Error for HTTP GET "/apps"
org.springframework.core.codec.EncodingException: JSON encoding error: Null key for a Map not allowed in JSON (use a converting NullKeySerializer?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Null key for a Map not allowed in JSON (use a converting NullKeySerializer?) (through reference chain: java.util.ArrayList[0]->org.springframewok.cloud.kubernetes.discoveryserver.DiscoveryServerController$Service["serviceInstances"]->java.util.ArrayList[0]->org.springframework.cloud.kubernetes.commons.discovery.KubernetesServiceInstance["metadata"]) at org.springframework.http.codec.json.AbstractJackson2Encoder.encodeValue(AbstractJackson2Encoder.java:229) ~[spring-web-5.3.13.jar:5.3.13] Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): *__checkpoint ? Handler org.springframewok.cloud.kubernetes.discoveryserver.DiscoveryServerController#apps() [DispatcherHandler] *__checkpoint ? org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain] *__checkpoint ? HTTP GET "/apps" [ExceptionHandlingWebHandler]
I'm getting the exact same exception with a simple Nginx deployment like the following:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx-deployment
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: nginx-deployment
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-deployment
spec:
ports:
- port: 80
selector:
app: nginx-deployment
Calling the /apps endpoint on the discovery server yields HTTP 500 and the stack trace appears in the discover server's output. I have spring-cloud-kubernetes-discoveryserver:2.1.0 installed. Also, this is on Docker Desktop for Windows.
Alright, I did some more digging into this, and I think there is a bug here: https://github.com/spring-cloud/spring-cloud-kubernetes/blob/ff50c9c2dcfab281bd6c3df8cdd978299e73d165/spring-cloud-kubernetes-client-discovery/src/main/java/org/springframework/cloud/kubernetes/client/discovery/KubernetesInformerDiscoveryClient.java#L151 It seems to assume a service port has a name defined like so ("default-http" in this example):
apiVersion: v1
kind: Service
metadata:
name: nginx-deployment
labels:
app: nginx-deployment
spec:
ports:
- port: 80
name: "default-http"
selector:
app: nginx-deployment
If the name is missing, a null key is inserted to the map, hence the exception.
So the workaround is to add names for service ports. Permanent fix might be to just skip adding a port to the metadata map if the name is missing?
@pbloigu thank you!
your workaround worked for me,
regarding permanent fix we can probably use "default" if name
does not exist
@pbloigu thank you! your workaround worked for me, regarding permanent fix we can probably use "default" if
name
does not exist
Yeah, well, I really don't have enough insight into what's the desired outcome in this case. Leave the unnamed ports out of the metadata map or make up some names for them?
thank you both for triaging this, very helpful!
In theory, this is not complicated to "fix", but we need to think on either sensible defaults or a correct failure. I do not have an answer now, but will spent some time reflective on it.
I think maybe the best solution would be to just set the name to be <unset>
as that is what the label is in k8s.