Skip to content
Advertisement

What is the best practice to make microservice aware about name of another microservice for interaction

I have couple of microservices written in spring boot which interact with each other to perform certain task. I need to deploy these microservices in AWS using Kubernetes. In order for microservices to interact with each other, one service need to know the name of other service. This is where I am not sure how to proceed.

Since I am planning to deploy using Kubernetes, I will create Kubernetes services for both microservices and also want to leverage DNS resolving of Kubernetes. Now my question is how do I make one microservice aware of Kubernetes service names. One option I can think of is, put the name of microservice in application.properties and create the Kubernetes service with same name but with this approach I have the impression that I am planning for failure. If somehow name of my service needs to be changed in future, then I also need to remember to change the name in each microservice which depends on this.

I assume this is very common scenario which people might be facing during microservices deployment using Kubernetes. So, What is the best practice to do this?

Answer

Pass the service names as environment variables. It’s okay to directly embed these in the clients’ YAML specifications (this is slightly easier if you’re using a templating tool like Helm), though using an indirect ConfigMap works too.

---
apiVersion: v1
kind: Service
metadata:
  name: other-service
spec:
  ports:
    - port: 80          # make the Service use the standard HTTP port
      targetPort: http  # even if the Pod uses something else
...
---
apiVersion: apps/v1
kind: Deployment
spec:
  ...
    env:
      - name: OTHERSERVICE_URL
        value: http://other-service

Every language has some way to retrieve environment variables (Python os.environ[], Node process.env, …) so you can use this approach regardless of the implementation language. If the environment variable isn’t set, make its default value be something that will be useful to a developer, perhaps a localhost URL on a known port.

In a Spring Boot client specifically, environment variables can be directly used as Spring properties (see also more specific rules for environment variable names) so your application.yml file can specify

other-service:
  url: http://localhost:12345

and then your client can be configured with

@ConfigurationProperties(prefix="other-service")
@Data
public class OtherServiceClient {
  private String url;
}

Do not try to use Spring property files to configure service URLs here. (In a Helm context you could dynamically construct a complete property file in a ConfigMap, but the environment-variable approach is more generic.) Since the URL could have pretty much any host name (again, especially in a Helm context, where the names are usually constructed) you don’t want to have to recompile your jar file to redeploy to somewhere new.

Advertisement