write a report focused on the specific challenges and
issues that arise owing to the use of microservices architecture as
a software development philosophy
Answer
Over the past 18 months we’ve seen increasing attention placed
on microservices. Standard bearers such as Netflix and Facebook
have highlighted how microservices can be used to create more
nimble and responsive software applications.At Belatrix we have
just published a whitepaper examining microservices and outline
some of their many benefits for tech organizations. However it is
also clear that despite the benefits of modularization and
containerization, many organizations continue to struggle with
microservices.
The computing world has seen a vast adoption of the
microservices software architecture in an effort to enhance
software scalability and efficiency. However, implementing such an
architecture requires exemplary expertise; a team that can develop
complex system with optimal agility. While microservices
implementation is an idea that has been in existence for quite a
while, the recent buzz on social media, conference tracks, and
empirical evidence points out the latter to be a computing model
that can greatly enhance software performance. Nevertheless,
building a software that is reliant on this architecture is not a
walk in the park.
Before delving into the challenges, it is commendable to
focus on some of the benefits of using the microservices
architecture in software development.
- Different developers can work independently on the same
project, with each focusing on one or a set of different
microservices whose collaborative implementation with other
microservices from other developers would deliver the desired
functionality of the system. This shortens the software development
life cycle, leading to fast delivery of the software.
- Through the use of the backward compatibility concept, it is
possible to ensure constant releases while still maintaining system
availability and stability.
- Microservices software development approach often entails loose
coupling, thereby ensuring that the integrated elements for
collaboration purposes only depend on one another to the “least
extent practicable.”
- Microservices architecture can allow for the independent
development of the individual services, thereby enabling the use of
the most appropriate development methodologies and tools.
- At the services level, the entire system is built on
independent subcomponents with each subcomponent focussing on
excellent execution a particular task; this makes such a system
highly efficient
Besides the benefits that are ultimately overwhelming,
there exist various challenges and issues
Just as the name indicates, microservices-based application
comprises of numerous tiny independent services that are integrated
with each other to offer the desired software functionalities.
While these tiny individual services may be simple, there is a
significant complexity that arises from their interaction for them
to work collaboratively in an effort to orchestrate the desired
business operations through them. While in practice, the idea of
microservices works excellently, in reality, the complexity
exhibited by the latter is commendable.
Expert Skills in Development and Operations (DevOps) are
required
- To begin with, applications developed based on the
microservices concept have to be highly effective, and, therefore,
it is critical for the development team to remain operations and
production oriented since a microservices application requires
tight integration with its environmental context. This implies that
the development and operations must be compounded by emphasizing
the collaboration and communication of the system development
engineers and other Information Technology personnel, while still
ensuring automation of the software delivery process and
infrastructural changes.
- On a different note, the use of this architecture in some
instances may imply that some services may require their own data
stores, especially where different programming environments or
languages have been used to develop different microservices, This
implies that the existent database administrator only conversant
with management of data stores of monolithic applications may need
to be replaced with programmers with a better knowledge of how to
develop, test, optimize and deploy both SQL and NoSQL
databases
- In most cases, it is essentially difficult to find developers
with impeccable programming skills across discrete development
environments, an aspect that increases the magnitude of the
challenge in the adoption of the microservices application
development approach.
Operations Overhead
- Unlike a monolithic application whose deployment and management
is seemingly easier, a microservices-based application has numerous
independent services that have to be developed and tested to in
potentially different development environments. This implies that
significant effort is required to ensure the resilience of the
developed application and avoid any failovers. This implies that
the higher the number of services and processes, the more complex
it becomes in integrating the microservices and ensuring optimal
efficiency of the system. Such an aspect increases its operations
overhead, especially when compared to a monolithic application that
can otherwise carry out the similar functionality while retaining a
high throughput.
- Synchronizing all the microservices, therefore, require
impeccable operations and monitoring infrastructure. This implies
that not only must the application server stay up and running, but
also it is crucial to ensure that thousands of processes executed
by the microservices run smoothly, do not cause any deadlocks and
there is sufficient disk space. This may be a very challenging
task.
- From a software development perspective, there are presently
not many open source tools, frameworks, and models to support
microservices dependent software. This, therefore, implies that any
team embracing such an approach to system development may end up
investing significantly on custom development for the micro
services to convey out the intended services before a functional
system that bears business value is developed.
Tacit Interfaces
- As mentioned earlier, a microservices-based system is composed
of tiny micro services that are integrated and collaborate to carry
out the intended processes and offer the required functionality.
This implies that the micro services have to perfectly communicate.
Such an aspect bears the concept of interfaces whenever the micro
concept model is used in an effort to ensure message are exchanged
between the services in the same format and bearing the same
meaning for efficient execution of tasks. This further complicates
the development of the system.
- Therefore, whenever a change is effected in one microservice
with respect to semantics and syntax, the other microservices also
need to be readjusted in order to correspond with the change. In
reality, this may entail reprogramming different components of the
system then recompiling and testing. While backward compatibility
may be a sure way of avoiding such challenges, in some instances it
may not apply, especially where staged releases are unwelcomed by
the business requirements
- In the event that some interfaces are updated, and others are
not, the microservices collaboration synchronization may fall out.
Therefore, when effecting changes that affect the microservices
communication, the effect of altering the messaging formats and
other call procedures may become significantly difficult to
visualize.
Complexities Associated with Distributed
Computing
- From a development perspective, microservices implementation
borrows the concept of a distributed system, whereby application
tends to hide the system complexity to the users as much as
possible. However, beneath the front end is an integrated set of
components working in synchrony and making numerous remote
procedure calls in real time.
- From a distributed computing perspective, there are numerous
challenges that have to be considered and which may not exist in
monolithic applications. These include but not limited to varying
loads within the software tiers, versioning, and asynchronicity, an
unreliability of the network, fault tolerance and network latency
among others. Effective programming for these properties ensures
graceful degradation of the applications as well as backward
compatibility; these may not be achieved in the monolithic
approach, an aspect that makes a microservices application more
available and reliable.
- This, however, presents an additional challenge for the
software developer as they have to think about and develop these
components, which are definitely inexistent in monolithic
applications. Essentially, distributed systems are significantly
challenging to develop test and deploy as compared to the
monolithic apps.
Team Effort Duplication
- Owing to the nature of the architecture, in some applications,
it is crucial to share different resources such as the dependent
libraries and packages among the services. While this may be highly
useful and efficient in applications whose microservices have been
developed in a relatively same development environment, it may not
work in a polyglot context, whereby different microservices may
have been developed in different programming environments. Such an
aspect leads to the concept of coupling, whereby there would be the
need to sustain the tacit interfaces between the microservices by
running them in parallel. From an analytical perspective, coupling
significantly reduces the perceived benefits of the microservices
architecture.
- To deal with the monolithic application challenges, some
development teams tend to duplicate the business logic component of
a system across different modules, an aspect that jeopardizes
software engineering principles. This implies that designing,
developing and deploying a microservices system requires patience,
determination, and commitment.
Challenges in Asynchronicity
- As discussed, microservices-based applications often tend to be
asynchronous as compared to monolithic applications, and often
leverage on parallelism and interfacing to offer their
functionality. Indeed, microservices-based applications are
therefore more efficient and reliable when handling tasks that can
be decomposed into distinct subtasks that can be executed without a
particular order and at different times.
- On the other hand, tasks that have to be executed
transactionally or synchronously in a microservices architecture,
which is often asynchronous, the computation paradigm gets complex,
characterized by the need for correlation ID management as well as
distributed transactions and concurrency control to make sure the
required actions or tasks are executed together
Challenges in Application Testing
- Owing to the many microservices that have to be developed and
tested and which evolve at different paces characterized by canary
releases, consistent recreation of the testing environment for
either automated or manual testing is usually challenging. The
addition of the asynchronicity aspect, which is often associated
with microservices architecture as well as dynamic messaging loads
for interfacing purposes, it becomes significantly difficult to
test the developed microservices system before deploying it into
the production environment.
- While it is possible to test independent microservices, it may
be significantly difficult in a dynamic environment, especially
whenever there is the emergence of indistinct behaviors from the
microservices interactions, and which may be hard to identify or
speculate.
some additional
challenges including:
- Operations and Infrastructure: The development group has to
work closer with operations more than ever before. Otherwise,
things will spin out of control due to the multitude of operations
going on at once.
- Support: It is significantly harder to support and maintain a
microservices setup than a monolithic app. Each one may be made
from a wide variety of frameworks and languages. The infinite
complexities of support influence decisions on adding services. If
a team member wants to create a new service in an esoteric
language, it impacts the whole team because they have to make sure
it can work with the existing setup.
- Monitoring: When you add additional new services, your ability
to maintain and configure monitoring for them becomes a challenge.
You will have to lean on automation to make sure monitoring can
keep up with the changes in the scale of services.
- Security of Application: The proliferation of services in this
architecture creates more soft targets for hackers, crackers and
criminals. With a variety of operating systems, frameworks and
languages to keep track of, the security group has their hands full
making sure the system is not vulnerable.
- Requests: One way to send data between services is using
request headers. Request headers can contain details like
authentication that ultimately reduce the number of requests you
need to make. However, when this is happening across a myriad of
services, it can increase the need for coordination with members of
other teams.
- Caching: Caching helps reduce the number of requests you’ll
need to make. Caching requests that involve a multitude of services
can grow complicated quickly, necessitating communication from
different services and their development teams.
- Fault Tolerance: The watchword with microservices is
“interdependence.” Services have to be able to withstand outright
failures and inexplicable timeouts. Failures can multiply quickly,
creating a cascading effect through some services, potentially
spiking services needlessly. Fault tolerance in this environment is
much more complicated than a monolithic system.
Risk mitigation
strategies that can be applied to minimise privacy and security
risk in microservices-architected environments
Strategies to minimize privacy and security risks in
microservice architure environments
Authentication: Authentication to microservices
APIs that have access to sensitive data should not be done simply
by using API keys. Access to such APIs should require
authentication tokens that have either been digitally signed (e.g.,
client credentials grant) or that is verified with an authoritative
source. Additionally, some services may require either single-use
tokens or short-lived tokens (tokens that expire after a short time
period) to limit the damage a compromised token can cause.
Authentication tokens should be handle-based, cryptographically
signed, or protected by an HMAC scheme.Every API Key that is used
in the application should have restrictions specified both for the
applications (e.g., mobile app, IP address) and the set of APIs
where they can be used.The restriction scope for functionality of
every API Key should be commensurate with the level of assurance
provided during identity proofing, whether it be machine or human
driven identity proofing.
When stateless authentication tokens (e.g., JSON Web Tokens
(JWT)) are used by implementing shared libraries associated with a
microservice, the following security precautions must be observed:
(a) the token expiry times should be as short as possible since
they determine the duration of the session and an active session
cannot be revoked, and (b) the token secret key must not be a part
of the library code, it must be a dynamic variable represented by
an environmental variable or specified in an environment data file.
The key value should be stored in a data vault solution.
If standards-based techniques such as OAuth or OpenID connect
are implemented, they must be deployed securely.
Access management: Access policies to all APIs
and their resources should be defined and provisioned to an access
server. Access policies at a coarse level of granularity say
“Permit to Call for a given set of addressable functionalities”
should be defined and enforced at the initial API gateway while
authorizations at the finer level of granularity (e.g., related to
domain of the particular microservices’ business logic) should be
defined and enforced closer to the location of the microservices
(e.g., at the microgateway) or sometimes at the microservice
itself.
Caching Mechanism: It may be appropriate to allow microservices
to cache policy data; this cache should be only relied upon when an
access server is unavailable and should expire after a duration
appropriate for the environment/infrastructure.
The access server should be capable of supporting fine-grained
policies.•Access decisions from the access server should be
conveyed to individual and sets of microservices through
standardized tokens encoded in a platform-neutral format (e.g.,
OAuth 2.0 token encoded in JSON format). The token can be either a
handle-based token or an assertion bearing token.
The scope of internal authorization tokens appended by the micro
gateway or decision point to each request should be carefully
controlled; for example, in a request for transaction, the internal
authorization token should be limited in scope to only involve the
API endpoints that must be accessed for that transaction.
The API gateway can be leveraged to centralize enforcement of
authentication and access control for all downstream microservices,
eliminating the need to provide authentication and access control
for each of the individual services. If this design is chosen, any
component suitably positioned on the network can make anonymous
connections to the services bypassing the API gateway and its
protections. Mitigating controls such as mutual authentication
should be leveraged to prevent direct, anonymous connections to the
services."
Secure communication: Clients should not be
configured to call their target services directly but rather be
configured to point to the single gateway URL.
Client to API gateway as well as Service to Service
communication should take place after mutual authentication and be
encrypted (e.g., using mTLS protocol).Frequently interacting
services should create keep-alive TLS connections
Security monitoring: Security monitoring should
be performed at both the gateway and service level to detect, alert
and respond to inappropriate behavior, for example a bearer token
reuse attack and injection attacks. Further, input validation
errors and extra parameters errors, crashes and core dumps must be
logged. A class of software that can accomplish this is the OWASP
AppSensor which could potentially be implemented in the gateway,
service mesh and microservice itself.
A central dashboard displays the status of various services and
the network segments that link them. At a minimum, the dashboard
should show security parameters such as input validation failures
and unexpected parameters that are obvious signs of injection
attack attempts.A baseline for normal, uncompromised behavior in
terms of the outcome of business logic decisions, contact attempts,
and other behavior should be created. The placement and
capabilities of IDS nodes should be such that deviations from this
baseline can be detected.
Conclusion
In conclusion, while microservices approach in application
development is deemed to produce more reliable and highly
functional software, the development process is quite challenging
as compared to monolithic applications . The latter advocates for
impeccable DevOps skills by the development team, characterized by
intensive monitoring of the microservices in an effort to spot any
anomalies in the microservices integration and collaboration to
take action and deliver the desired business functionality. At
AuroraSolutions, we strive in ensuring that you get the best out of
your microservice based software by offering you expert advice
based on our long standing experience in the industry.