2024-07-22 | Benedikt Hunger | 4 min read
Cross-Cutting Concerns for microservice architectures - part 2
In the first blog post on the cross-cutting concepts of microservice architectures, we introduced you to the characteristics of microservices and the challenges they face. In the second part, we will look at specific examples of how cross-cutting concepts for microservices can be implemented.
Cloud Infrastructure
In order for microservices to remain small enough to deserve the name, it must be easy to create new microservices. In addition to the code base, this requires some infrastructure that in principle differs little across different services. It therefore makes sense to have these recurring elements managed and maintained by a dedicated infrastructure team. This includes the following elements:
Provision of computing resources
Over the last decade, container technology has proven to be a profitable concept for the efficient utilization of resources. Here, individual processes are encapsulated from one another using Linux kernel features, which facilitates the shared use of computing resources by independent processes. It is essential for the use of container technology that individual containers can be restarted at any time (e.g. on another computer), as this achieves an orchestrated high utilization of the available computing time. The de facto standard for orchestrating containers is the open source system Kubernetes, which provides an interface for developers to easily deploy containers (and other resources), if configured well.
As a good configuration of a Kubernetes cluster is a relatively complex task, a specialized team should be set up to deal with the network architecture, communication between containers, secret management and basic logging and monitoring in connection with Kubernetes.
Network connectivity
The inner simplicity of microservices comes at the cost of a great deal of complexity being shifted to communication between services. It is therefore important that microservices can establish a network connection to each other and to the internet. The connection should be automatically secured by mTLS. This automation can also be best ensured by a central infrastructure team. It should also be easy for the microservice teams to set up basic allow lists for accessing services and, if necessary, some network rules should be made binding by the infrastructure team for compliance reasons. Communication between microservices is much easier to achieve if the infrastructure is hosted by a single cloud provider.
Persistence
Microservice containers should be able to be restarted at any time without losing data. This implies that persistent data storage must take place outside the microservices, typically in databases or persistent volumes. In addition to general difficulties such as authentication and authorisation as well as connectivity to the data storage systems, there are specialized challenges such as the creation of data backups and snapshots to ensure the recoverability of persistent data. For different needs, different types of databases should be made available for microservice teams to choose from, such as an SQL database, a document database and a cache system. This is important to ensure technology openness in the implementation of microservices so that microservice teams can choose the best technology for their use case. The provision of databases or volumes should be as automated as possible, which requires close collaboration with the Kubernetes team.
Logging and monitoring
In order to be able to reproduce and rectify errors, it is crucial that there is an easy way to access the logs produced by the individual microservices. The industry standard for this is an Elastic Stack, which is ideally hosted and managed by a central team so that the microservice teams do not have to worry about setting up logging infrastructure. Solutions other than an Elastic Stack are also conceivable here, but a standard solution should be specified centrally and the log format (e.g. JSON with certain predefined fields) should also be standardized across microservices.
It must also be possible to link logs across multiple services, especially across REST requests or asynchronous messaging. Request tracing via OpenTelemetry is suitable for this by propagating the traces across requests, for example with the help of the B3 specification. In addition, the resulting traces can of course be used to recognise and eliminate bottlenecks in requests.
A monitoring/alerting stack (typically with the help of Prometheus and Grafana) should also be centrally maintained and be able to be filled with standardized metrics as well as individually configurable metrics. Alerts should be individually configurable by the microservice teams.
API design
Depending on the microservice, the requirements for the APIs for communication with the microservice can be very different. Nevertheless, it can make sense to set common requirements for the API structure (e.g. HATEOAS or gRPC), which are only not taken into account in justified exceptional cases. For HTTP APIs, OpenAPI can be a good solution for documentation. If necessary, a decision can be made to make the provision of OpenAPI specifications for microservices mandatory so that client developers can rely on the existence of these specifications. In any case, a common schema for the documentation of APIs (including error cases) should be created to make it easier to find relevant documentation.
Messaging
Asynchronous communication via messaging systems can significantly help to make the overall system more resilient. The temporary inconsistency in data storage caused by asynchronicity is deliberately accepted ("eventual consistency") in order to achieve faster requests and decoupling of different microservices. To ensure that communication between different microservices via messaging works, the messaging system itself should be provided and managed by a central team. As with the APIs, the format of the messages should be documented using a common schema.
Authentication and authorisation
Authentication and authorisation are central tasks that cannot be handled by individual microservice teams. A centralized solution, for example based on OpenID, should be provided for this purpose.
Summary
A microservice architecture can be a good solution, especially for complex systems, in order to quickly implement improvements to the system and new features. However, this creates dependencies between microservices and therefore also between the microservice teams. The cross-cutting concerns described here help to ensure consistency, security and efficiency in a microservice environment.
Scandiolife on Instagram.
Connect with us on LinkedIn.
Look what Scandio is tweeting.