How to use Chef tags in following scenario?

Greetings Masters

###Problem statement is:
We need to manage 300 servers, We have created 4 environments for them: dev (50 servers), test(50 servers), pre-prod(100 servers) and prod(100 servers). I need to run Role1 for first 20 dev servers and Role2 for remaining 30 dev servers. My approach is: I will create 2 Tags: Tag1 for first 20 servers and Tag2 for remaining 30 servers. And run following knife exec ruby code

nodes.transform("chef_tag:tag1") \
{|n| puts n.run_list.add("role[role1]"); }

###Problem is
My approach is not working.

Could someone please help.
I am open for new approaches as well. Please feel free to share.

Manish Mehra

The search query for tags would be "tags:tag1".

1 Like

Indeed. It is “tags:tag1”. Thanks Noah.
Do you think there is a better approach to deal with my scenario?

Curious - it seems like the same effort that would go into tagging each of the nodes would be a similar effort to add the role to the node’s run list.
How are you adding the chef tags to these nodes?

Hi @Mike… I am using tags to group my servers and roles to group recipes. Effort and time taken are same. As a matter of fact the time taken in tag approach is little extra.
But, Instead of saying “push Role3 to the group of servers where Role1 and Role2 already exists, I am saying push Role3 to the group of servers where the tag value is Tag1”.
It makes my environment easier to manage and look more tidy. Do you still feel that using tag was a bad idea and I should go ahead with Roles?
I am always open for suggestions.

I think that makes sense.

Instead of knife exec transforms, I think I would approach it a little differently:

Every node would get the same run list, and the first recipe executed would evaluate the node’s tags, and add items (roles or recipes) as needed. Something like:

if node.tags.inculde? 'Tag1'
  node.run_list << 'role[Role3]'
  # or
  include_recipe 'something::else'

I think I’d prefer the include_recipe approach, as it’s “cleaner” and doesn’t change the run list that already in flight - I don’t know if that actually works correctly with resource loading.

This way, you are still controlling the “what” with a single piece of metadata, as opposed to having a requirement of both setting the tags, then having a manual operation to transform nodes based on tags to apply a run list item.

Again, I think I’d much rather launch nodes with sets of top-level role definitions - so a webapp node gets a webaap role, which can include many other roles and recipes.

Since tags are single-dimension, and not structured in any format other than whatever convention you decide on, they make for a lot more flexibility, but not always the best use case for deciding on what run list items to use.

The transform method is the one I favor the least, as it requires a manual interaction with the API, which can have unintended results and requires more human interaction than updating a role and shipping it to Chef Server.

1 Like

Thanks for detailed insight @Mike. I was looking for documentation on include_recipe, transform_recipe and other operations. But I am not able to locate something on this. All I get is some pieces of recipes where the are used. Could you please redirect me to certain documentation on these?

I’m not suggesting a change to your approach @manishmehra but I am curious if anyone has (or would advise) approaching this instead by using environments?

What he’s trying to do is to manage the run list of lots of nodes that should have identical run lists. Environments don’t control run lists, so they don’t help here. The options for solving this problem are:

  1. Roles are the original solution for this problem. The downside of this is that roles are not versioned, so you cannot roll out updates to a role gradually within a single Chef Server organization. Workarounds for this problem include using organizations to represent lifecycle stages (e.g., have a ‘dev’, ‘stage’, and ‘prod’ org instead of Chef Environment), enforcing minimal usage of roles, e.g., only use roles for run list management, but never use attributes (this isn’t foolproof but it can help), version roles via the name, e.g, ‘foo-1’, ‘foo-2’, etc. (though this basically re-introduces the problem, you have to mutate the run list property of all your nodes to upgrade to a new version).

  2. Use role cookbooks. The plus side of this is that cookbooks are versioned, so you can use environments to manage what version is allowed on which nodes. The downside is that cookbooks aren’t meant to be roles, so you will run into problems with the order in which attributes files are evaluated, among other things.

  3. Have nodes “self manage” their run lists via a cookbook that mutates the node’s run list. This gives you a nice way to bulk edit your nodes. The downside is that you need two chef runs for the change to take effect, and it rolls out gradually as the nodes run.

  4. Policyfiles. If you use policyfiles, the policy owns the run list; the run list property on the node object will be modified by chef-client to reflect whatever is in the policyfile. You can have an arbitrary number of nodes using the same revision of a policy, and you control which revision is available to a node via the policy group mechanism. In terms of managing run lists on lots of nodes, I think this is the best way, but policyfiles introduce a “build step” into the process of publishing updated cookbooks to your nodes which may imply some changes to your workflow. Also, policyfiles are newish and you need to be on the latest versions of everything (and be willing to stay updated for the next few months or so) to have a good experience.

1 Like

I think Dan covered this the most comprehensively.

To be fair, tags aren’t versioned either. :slightly_smiling:

The “use roles to manage run lists, not attributes” approach in conjunction with “use environments to set attributes that are specific to that environment” I think is the best, happy balance to use battle-hardened code paths.

While Policyfiles are likely to be the best new thing since roles, as @kallistec said, it’s bleeding edge.