No matter how resiliently you build your application, incidents will happen. And as your application grows, the complexity of troubleshooting and resolving an incident also grows. With prior virtualization technologies, this might involve a virtualization admin, a network admin, a storage admin, and an applications developer to sort through the issue, put a resolution in place, and determine a root cause. With microservices architectures and Docker containers, this complexity is taken to the next level.
Before an incident occurs, it is important to remember that the customer experience is paramount. If the infrastructure underlying the application can recover from a fault, or if the infrastructure can recover the portion of the application at fault, and this recovery is transparent and seamless to the user, then it is a job well done, and will result in less middle-of-the-night calls for the team. These kinds of failures can wait until morning. Resilience is a key first step in any incident management regime.
Step two is discoverability. Inherent in microservices architectures is the ability for each service to discover the other services it needs to find. It is important for the operations team to be able to find services that are underperforming or in a failed state. This is done with tooling, but also with strong documentation. Inline comments are very helpful for troubleshooting at a microlevel, but at a macrolevel, configuration documentation is invaluable in decreasing time to resolution.
When designing a microservices solution, it is also very important to limit non-isolation patterns (or eliminate them entirely. Microservices should only interact with each other through a strictly controlled, and well documented RESTful API. If the service is not self-contained, or shares a database with another service, it can exponentially increase the amount of time required to resolve the incident.
Sharing a database is a problem waiting to happen, an incident waiting to begin.
An application leveraging microservices should be relatively easy for a developer who has worked on the service to troubleshoot and resolve. If the code is well documented, it should also be relatively easy for other developers to review the service and discover the issues. This is another perk of having hard boundaries and single processes contained in one service.
At this point, the issue has been determined not be internal to the service. The next step, following an incident management process, is an escalation to the engineering team to review the state of the environment and see if there is an issue that underlies the service itself. This can happen for a number of reasons, but is most likely an issue with the most recent deployment of the service, or an underlying configuration change that was not captured by the change management process.
After the incident has been resolved, it is always important to debrief. In the heat of the moment, people forget to document a solution to the issue, and the priority is usually simply to resolve the issue. A regular debriefing after any incident helps to ensure there is information on how the issue first can be triggered, and if it occurs again, how it can be resolved is captured. A mandatory debriefing also helps inform a continual improvement process to further harden and refine development and deployment of the application.