Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Practice for setting unique Chef Node Attributes

Tags:

chef-infra

I am attempting to use Chef to manage new virtual machines. I'm using a dedicated Chef server and doing all this work from a separate workstation vm.

The way I am currently doing it is cloning a base vm image then using knife bootstrap to install Chef and bring the vm to a consistent state.

I can specify an environment or run list for the vm; I can override certain settings in my environment, e.g. I have the chef-client interval in the "overrides" block of the test environment set to run the client every 60 while I'm testing so I don't have to manually run chef-client every time.

For instance, my workflow is this:

  • clone vm template and start vm

  • set the hostname manually (update /etc/hostname and /etc/hosts) and reboot

  • Bootstrap the node with the initial recipes

    knife bootstrap chef-test1 -r 'recipe[ntp],recipe[chef-client]'

  • edit the node to reflect the new environment

The problem I am having is setting per-node attributes. I would like to use the hostname cookbook to set the node's hostname, if I set this in a role then each server would have to have a new role created. But when I attempt to bootstrap and include this role I get an error:

chef-test1   * log[Please set the set_fqdn attribute to desired hostname] action write[2013-12-09T16:26:56-07:00] WARN: Please set the set_fqdn attribute to desired hostname

When I bootstrap without that recipe and attempt to edit the node and set the "set_fqdn" attribute, I am unable to save the attribute, e.g. this json:

{
  "name": "chef-test1",
  "set_fqdn": "chef-test1.local.fqdn",
  "chef_environment": "test-dev1",
  "normal": {
    "tags": [

    ]
  },
  "run_list": [
    "recipe[ntp]",
    "recipe[chef-client]",
    "recipe[hostname]"
  ]
}

when I exit out of my editor, knife tells me:

Node not updated, skipping node save

I attempted to edit this attribute in the chef gui and the attribute won't save.

I found this guy who is creating the json in /etc/chef/chef.json, doing basically what I would expect, but I'm not sure how /etc/chef/chef.json comes into play (update it for each new node? I'm not using chef-solo so maybe that's where my confusion is).

According to this email thread it's not possible to override default attributes with knife node edit, but "set_fqdn" isn't a default. I would like to avoid creating a role for each node, and I think I can use the hostname cookbook to alleviate the need to manually set the hostname, something like:

knife bootstrap saucy64 -r 'recipe[ntp],recipe[chef-client],recipe[hostname]' --json '"{ set_fqdn": "chef-test1.local.tld", "chef_client": { "interval": "600" }'

knife bootstrap fedora19 -r 'recipe[ntp],recipe[chef-client],recipe[hostname]' --json '"{ set_fqdn": "chef-test2.local.tld", "chef_client": { "interval": "60" }'

I appreciate the assistance.

like image 414
user1106405 Avatar asked Dec 09 '13 23:12

user1106405


People also ask

How do chefs use attributes?

The sources of Chef attribute in Recipes (in cookbooks) We can specify the attribute at node level while running chef-client. Those attributes are referred to as node attributes. You must precede the attribute name with node. when you set an attribute directly in a recipe.

How are nodes configured in Chef?

In order for Chef to configure a node the chef-client needs to be installed on the node. The chef-client is responsible for making sure the node is authenticated and registered with the Chef server. The chef-client uses RSA public key-pairs to authenticate between a node and the Chef server.


2 Answers

I see some problems:

  • during knife node edit, you can't set the attribute as a top-level attribute next to fqdn etc. You have to place it below normal. This is the hierarchy between default and override. See Attribute Precedence
  • using knife node edit smells. I'd rather not do this (might be okay for the host name, but for everything else it's impossible to track such changes in version control). Try to get the hostname cookbook running instead.
  • writing attributes out to a chef.json file should be IMHO also avoided. Your logic should be inside your cookbooks
  • you should have a base role / cookbook or similar that includes the trivial things that every node has (like ntp, chef-client and also the hostname).
  • you can set the environment also directly during bootstrapping: -E myenv (but yes, I'm wondering why this isn't documented)
  • you can set the node name during bootstrapping, too: -N NAME or --node-name NAME.
like image 190
StephenKing Avatar answered Oct 19 '22 16:10

StephenKing


how about a recipe that sets the hostname based on the defined node.name when you bootstrap the node, I wrote one which is a fork of the original chef-hostname cookbook.

like image 28
user1106405 Avatar answered Oct 19 '22 17:10

user1106405