Following the environment cookbook pattern (specifically using an app.rb recipe for deployment), if I have an application consisting of a front-end client, a back-end API, and some services, (each different Visual Studio projects & potentially running on different nodes) should each component be a recipe in the overall environment cookbook or each have their own cookbook?
I'm thinking that each component is itself a different application and should therefore have their own environment cookbook.
Otherwise I can't picture how the environment's app.rb recipe would deploy the application considering there are multiple nodes.
Am I thinking this through correctly? How have others implemented distributed applications with Chef?
Edit: After mulling things over for a couple days, I'm backpedaling and settling on the one environment cookbook pattern:
Thought Exercise - "MyApp"
"MyApp" consists of two software components compiled separately and residing on different nodes:
- WebApp
- REST API
The current cookbook setup:
myapp environment cookbook
- recipes
- webapp.rb
- restapi.rb
Is this logical or should each software component be its own cookbook instead?
In the current system, a release artifact looks like (each recipe knows how to deploy its artifact):
myapp-vX.X.X artifact
- webapp.tar.gz
- restapi.tar.gz
- cookbooks.tar.gz
Current releases:
- 1.0.0 - Initial development
- 1.0.1 - Bug fix in webapp
- 1.1.0 - New feature added to API and bug fixes in webapp
Dev Test Prod
1.1.0 1.1.0 1.0.1
"We need to move the webapp fixes in 1.1.0 up to prod, but we aren't done testing the new API feature." - Manager
Problem: The "MyApp" production environment requirements are different than the environment's v1.1.0 cookbook residing in dev and test.
Possible Solutions- Cut a 1.0.2 release without the API feature and promote it up through the environments. Then promote 1.1.0 back to dev and test; now we're back where we started, but the bug fixes are in prod as desired.
- Re-architect cookbooks: make the webapp and API components be separate cookbooks.
- Each have their own versions (API 1.0.0 could live with webapp 1.0.1 in prod)
- They produce their own deployment artifacts like before but the artifacts are published to app-specific repos (ex. myapp-webapp) instead of the "MyApp" artifact repo.
- The new "myapp" environment would just define the version of each application component cookbook it needs.
- The result: API v1.0.0 would be deployed alongside webapp v1.0.1 in production.
- Problems:
- Even though these pieces of software are part of the same logical distributed application, their shared data are not logically grouped together. Ex: both might need to define the API endpoint in an attribute (default[:myapp][:api][:endpoint]).
- It may be difficult to keep track of cross-compatibility. "Is version 1.0.1 of the webapp compatible with v1.2.0 of the API?"
There seem to be many ways to skin this cat, but if you can't tell, I'm liking option #1 more. I'd love to get more feedback before I decide on an answer. Does this make sense?