SOLID is a mnemonic acronym for five basic principles of object-oriented design, originally coined by “Uncle Bob” Martin. From Wikipedia: “The principles when applied together intend to make it more likely that a programmer will create a system that is easy to maintain and extend over time.” While SOLID is designed to help guide developers, these principles can be very much applied to operations as well.
Single Responsibility (SRP)
A server should have only a single responsibility.
When first starting out, it’s common practice to run web server, the app server, and the database server on a single host. While that may be an accepted practice for development (though, I would argue against it even then), your applications will become more complex in time and the tangled mess of servers will become a nightmare to administer.
Each server should have a single purpose. By separating responsibilities, your servers are easier to care for, your metrics are easier to parse, your infrastructure audits go much more quickly, and service disruptions can be greatly minimized.
Capacity planning is an absolute must for reducing infrastructure costs. Proper planning requires clear and well-defined metrics. Virtualize parts of your infrastructure where performance will not be degraded to minimize expenses.
Servers should be open for extension, but closed for modification.
Once a server is provisioned, it should remain in the intended state until it is decommissioned. A server can be modified to correct errors, but adding new services or changing the functionality of a service means that a new server should be provisioned.
Adding new services to a server breaks the closed nature of the system, consequently increasing complexity and the time it takes to recover from failure.
Liskov Substitution (LSP)
Servers in an infrastructure should be replaceable with instances of similar types without altering the correctness of that infrastructure.
Servers are a disposable commodity. Never rely on providers to always have 100% uptime and never assume a server that exists today will be there tomorrow. Your application should not rely on a specific provider. It should not rely on a service that is only offered by one provider. Data that can’t be recreated must be backed up in a vendor-independent manner.
Knowledge should never be held by a single individual. The person responsible for a particular piece of infrastructure should document any and all information they have about it. Everyone on your team should be able to sub in for anyone else. They may not immediately know to resolve issues, but they should know where and how to find the necessary information.
Interface Segregation (ISP)
Many client specific tools are better than one general purpose interface.
Give your infrastructure the UNIX Philosophy treatment. The tools you use should do one thing and do it well. Your configuration management tool should only manage configurations. Your server provisioning tool should only provision servers. Your metric collection tool should only collect metrics.
Monolithic services force you to modify your processes to fit the service. Instead, use tools with single purposes and modify them to fit your processes.
Dependency Inversion (DIP)
Depend upon abstractions. Do not depend upon concretions.
Having your developers worrying about the underlying infrastructure is a needless and potentially dangerous distraction. Developers should not concern themselves with how much storage or memory a given system has. That doesn’t mean your developers should not understand or ignore the performance implications of their design decisions, but provisioning or configuring the systems they use should not be on their mind.
Provide your developers with a platform upon which they may deploy their applications; be it Heroku, Cloud Foundry, or even something home-rolled. Implement a simple interface with which they can deploy their applications and make the deployment process across multiple languages and data stores as uniform as possible.
In smaller organizations where cost is a much greater concern, following these principals does pose a greater challenge, but it is not impossible. Never assume your organization will always remain small. Growing will be so much easier in the long run. Likewise, if you simply don’t have enough time or people to implement one or more of these principles, make it a goal to work toward while focusing on the principals you can implement.
Like all ideals, meeting them completely is hard. Our common goal shouldn’t be “good enough”; we should shoot for the stars and sacrifice whenever we must.
2012/03/21 - Added "In Practice" section