kentoh - Fotolia
While a distributed microservices architecture isn't a fit for all enterprises or application types, it works well in many situations.
Microservices -- which promote a modular application design -- facilitate flexibility, as they provide organizations with the freedom to choose development languages, frameworks, code builds, integration processes and runtime infrastructure. However, such freedom leaves developers and DevOps teams with a daunting array of choices.
There is no prescriptive or universal action plan to deploy microservices in a production environment. However, major online service providers that operate hyperscale distributed architectures -- such as Google, Amazon and Netflix -- have shown that there are principles and issues every DevOps team must address as they prepare for a microservices deployment. Here are six of those key lessons learned.
1. Use cloud services for production infrastructure
Simply stated, a microservices architecture is one in which applications consist of discrete, independently scalable components. Cloud services -- which encapsulate infrastructure resources or enterprise apps as on-demand services -- enable microservices, as they make it more cost-effective and convenient to disaggregate and run application functions as separate components. Rather than use traditional IT infrastructure, build and deploy microservices in the cloud.
While the decision to operate in the cloud still provides IT organizations with an array of choices for a microservices runtime environment, avoid partitioning microservices into discrete VM instances, as containers and serverless functions are better suited to microservices deployments. VM instances might still be necessary, since container users often deploy compute instances to build a cluster -- as opposed to using a fully managed containers as a service tool like Azure Container Instances. However, a cloud Kubernetes service, such as AWS Elastic Container Service for Kubernetes or Google Kubernetes Engine, should manage these instances.
Given the novelty of microservices deployments, never judge the feasibility, cost and performance of cloud services based on your history with legacy applications and servers. Likewise, don't assume cost-performance tradeoffs in storage, but rather research the financial and performance differences between solid-state drives and hard disk drives, since SSDs might be worth the incremental cost.
2. Design for failure
A microservices architecture is decoupled and distributed, which means individual application components have many dependencies. Such disaggregation enables components to operate, receive updates and scale independently -- without a base reliance on the availability or responsiveness of other microservices. The microservices infrastructure cannot be critically dependent on a single server. Without mutual independence, a microservices design becomes a convoluted monolithic system.
Organizations must design and deploy microservices to accommodate for failure: For example, microservices must treat servers -- or container nodes -- as stateless entities that can independently stop, restart, autoscale and patch. Applications must tolerate the failure of microservices components and recover gracefully from component-level failures. Chaos engineering tools, such as Gremlin and Netflix's Chaos Monkey, test the resilience of a microservices infrastructure.
3. Decentralize data management
Enterprise data centers often consolidate databases and storage volumes onto a few systems to improve operational efficiency, cut licensing costs and simplify application, policy and security management. This monolithic approach is anathema to microservices design, as the database features don't suit every situation. Similarly, with consolidation, several microservices application teams might share the same database, which becomes a problem once someone needs to update the database structure that other microservices depend upon.
Software developers need the freedom to choose the best database for the job. This is easy to ensure with cloud platforms, such as AWS or Microsoft Azure, which offer a myriad of database choices. Developers also need the flexibility to change and update the database schema and procedures without the fear they might break existing functional code.
4. Distribute governance
Enterprise IT organizations traditionally operate in functional silos -- separate storage, networking, database, development, operations and server teams -- where each silo handles one piece of the overall application lifecycle. In this traditional model, development teams become part of an unwieldy project to implement an application or IT service. Teams often communicate through existing processes, such as help desk tickets or feature requests, which are slow and often highly restrictive. This inhibits creativity and rapid development of new ideas.
Microservices should upend this structure. Replace IT silos with cross-functional microservices teams with a DevOps culture and agile development practices. Teams organize around the product -- the microservice or microservices-based application -- instead of a particular job role, with a manager responsible for its development and delivery. To design and deploy microservices successfully, create a culture with minimal restrictive processes balanced with the responsibility to acknowledge and fix problems when they occur. Optimize for speed, rather than efficiency.
Because the cloud service provider handles most operational tasks, the infrastructure team is small. Product-focused teams promote agility, tight communication and coordination; this team structure also eases the build process for necessary API interfaces that enable process automation and microservices integration.
5. Automate infrastructure deployment, embrace CI/CD processes
As mentioned above, microservices thrive in an agile DevOps environment, which requires fast, frictionless processes. To eliminate overhead and friction, automate processes so a particular team member's actions, such as updating a code module, trigger the necessary responses, such as software builds and tests. Process automation encourages rapid code development and an evolutionary design -- both critical attributes of microservices.
Netflix offers two other tactical recommendations based on its microservices experience:
- Keep code at a similar level of maturity. Immutable infrastructure entails the creation of a new microservice when an enterprise needs to add features or fix bugs in an existing one. The technique keeps the old microservice operational while developers test, patch and debug the new one. When it's ready for deployment, infrastructure admins swap out the old microservice container for the new one.
- Use separate builds for each microservice. Although various microservices might share files -- such as libraries and code functions -- they might require different versions. Since the microservices philosophy centers on minimizing dependencies, build each service independently to ensure that it pulls the correct version of a component file from a storage class memory. Independent builds also make it easier to prune outdated versions from the code base.
6. Monitor, log and troubleshoot from the start
The construction of applications from a set of microservice Legos considerably complicates system and performance monitoring and troubleshooting. This is because various microservices often trigger a cascade of events that leads to an application failure. To minimize failures -- which aren't a maybe, but instead a reality -- incorporate monitoring and troubleshooting into microservices design.