Until now we used to think that the best practices would be to define the attributes in the cookbook and then if those needs to be overwritten, to do that using environment attributes.
But as I started be more involved in cookbook development, I started refactor some old cookbooks and I found that it’s easier for some cookbooks to use in recipe search for nodes, thus means that instead of having attributes in environment, they should be on nodes. But that prevents having an environment defining all the application deployment on the same. What I’m trying to say is that before I started refactoring cookbooks, all the attributes from cookbooks, if they were needed to be overwritten, they were using environment attributes and so all the machines from that env could had been replaced at once, because they would contain no other information than OHAI attributes and run list.
Any thoughts on that approach?
The major downsides of environment attributes are that
- they instantly change all nodes in that environment, which means that any errors might break the whole environment
- and they can not be tested by kitchen or anything similar
Thats the reason why a more modern approach suggests using wrapper cookbooks for everything because they can be tested in many ways (kitchen, chefspec, rubocop/cookstyle, foodcritic…) and they are versioned, so you can easily roll back in case an error happens. You can read more about this here: http://blog.vialstudios.com/the-environment-cookbook-pattern/
One other limitation that I would like to point out about environments is that it is static and does not allow for any sort evaluation such as settings an attribute based on say an ohai attribute.You could use the environment override cookbook pattern which solves this problem but as @joerg.herzinger pointed out unless you account for the fact that everything is changing at once you risk issues being pushed and breaking all nodes at once. There are several ways to mitigate this either by using blue/green attributes or by having your orchestration stop all your chef client services and then converge groups at a time (we do this by AZ) that way if something fails the chef-client service is stopped and rest of the nodes will not get in a broken state. As for the environment changes in our cookbooks each comes with a mock environment that we use to validate many things but there is always a risk but in my opinion that is the price of separating logic from configuration.