I'm trying to develop a sample application using spring cloud and minikube which consist of 3 spring boot applications.
The first two are two different application (servers) which have the same endpoint but different functionality, and the third one is a client used to integrates the two other applications into one single exposed api.
I managed to deploy all three applications in minikube and managed to develop the full stack and make them communicate between each other, but now I want to go a step further and make the discovery of the two servers automatically, without hard coding the service names.
I deployed the two servers in minikube using the same label and would like to find something so that the client is able to find the services related to the two server apps automatically. This will allow expanding the application easily, so that when I add a new server to the stack the client will find it and expose it without need of any change.
Using Netflix Eureka this can be easily achieved by using something like
discoveryClient.getInstances("service-name").forEach((ServiceInstance s)
But I do no want to add an extra eureka server to the list of microservices since we are going to use kubernetes.
Is there any library which gives this functionality for kubernetes?
I found fabric8 library that helped me to achieve this. Still don't know if this is the correct answer, but it works :D
https://github.com/fabric8io/kubernetes-client/tree/master/kubernetes-client
@RequestMapping("/")
private String getResponse() {
String ret = "hello from Client L0L!!!\n";
//Config config = new ConfigBuilder().withMasterUrl("https://mymaster.com").build();
//KubernetesClient client = new DefaultKubernetesClient(config);
KubernetesClient client = new DefaultKubernetesClient();
ServiceList services = client.services().withLabel("APIService").list();
Service server = null;
log.warn("---------------------------------------------->");
for (Service s : services.getItems()) {
log.warn(s.getMetadata().getName());
log.warn(s.toString());
if (s.getMetadata().getLabels().containsKey("ServiceType") && s.getMetadata().getLabels().get("ServiceType").equals("server"))
server = s;
}
log.warn("---------------------------------------------->");
String s = "";
if (server != null) {
RestTemplate t = new RestTemplate();
String url = "http://" + server.getMetadata().getName() + ":" + server.getSpec().getPorts().get(0).getPort() + "/";
log.warn("Contacting server service on: " + url);
s = t.getForObject(url, String.class);
log.warn("Response: " + s);
} else {
log.warn("Didn't find service with label ServiceType=server!!!");
}
return ret + " - " + s;
}
I create the two services and added the two labels used in the code.
You can use:
CLI: kubectl get services --selector=YOUR-LABEL-NAME
.
API: GET /api/v1/namespaces/{namespace}/services
with labelSelector
parameter see API docs.
However be careful with dynamic service discovery inside services. As derSteve mentions in the comments below - The best practice for dependencies between services is to deploy them as logical bundles called deployments
for which it is not necessary to perform discovery of previously unknown services. See this link.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With