Friday, December 20, 2013

Upgrading Chef using Chef [feedly]

Upgrading Chef using Chef
http://feedly.com/e/DQCm59mW

One of our goals here at Chef (née Opscode) is to make installing Chef on a new node as easy as possible so that you can start enjoying the benefits of automation with minimal delay. But what happens to nodes that stick around for extended periods of time?

If you operate in an ecosystem where you cannot treat your infrastructure like garbage then you should have a plan for upgrading the copies of chef-client that are already running in your environment. With omnibus Chef 11, automatic in-place upgrades can be handled using Heavy Water Operations' omnibus_updater cookbook. Chef can update Chef!

Basic Usage

To get started, add the omnibus_updater cookbook to your run_list. For our example, we will add the omnibus_updater to the base role's run_list.

{     "name": "base",     "description": "All good Chefs have base roles!",     "chef_type": "role",     "json_class": "Chef::Role",     "run_list": [        "recipe[chef-client::delete_validation]",        "recipe[chef-client]",        "recipe[omnibus_updater]"     ]  }

When chef-client executes on your node, omnibus_updater will collect the required metadata (platform, platform_version and machine['kernel']) and use this information to download and install the correct package from Chef's omnitruck API.

Specifying The Version

The default behavior of omnibus_updater is to download and install the latest version of the Chef. You can specify which version of Chef you would like to install by setting the node['omnibus_updater']['version'] attribute appropriately.

Because the version of Chef you wish to download is stored as an attribute, you can leverage merge-order precedence to control what version of chef-client is installed in different scenarios. As an example, let's walk through an example where your team would like to promote versions of chef-client through your two Chef environments: staging and production.

In staging, you hard-code the latest release of Chef so that your team can test its stability in your infrastructure.

{     "name": "staging",      "description": "Test latest chef-client before moving to Prod.",      "chef_type": "environment",     "json_class": "Chef::Environment",     "default_attributes": {        "omnibus_updater": {           "version": "11.8.2"        }     }  }

In production, you hard-code the version of Chef that has been approved for use in production by your team.

{     "name": "production",      "description": "Use approved, well-tested version of chef in Prod.",      "chef_type": "environment",     "json_class": "Chef::Environment",     "default_attributes": {        "omnibus_updater": {           "version": "11.6.2"        }     }  }

Once the decision has been made that 11.8.2 is stable enough for use in production, all that would be required is to update the attribute in the environment. That version of Chef would be installed the next time chef-client is run.

{     "name": "production",      "description": "Use approved, well-tested version of chef in Prod.",      "chef_type": "environment",     "json_class": "Chef::Environment",     "default_attributes": {        "omnibus_updater": {           "version": "11.8.2"        }     }  }

Downloading From Custom Location

If you are unable to access the public Internet to download the omnibus packages from Chef or wish to download your packages from a mirror (e.g. a mirror behind your company's firewall), you can set the node['omnibus_updater']['direct_url'] attribute to point to a specific omnibus package.

One solution could be to set the node['omnibus_updater']['direct_url'] attribute in your Chef environment.

{     "name": "production",      "description": "Use approved, well-tested version of chef in Prod.",      "chef_type": "environment",     "json_class": "Chef::Environment",     "default_attributes": {        "omnibus_updater": {           "direct_url": "http://example.com/chef-11.8.2-1.el6.x86_64.rpm"        }     }  }

The downside of this implementation is that it will not work in a cross-platform ecosystem. To create a more robust solution, you could create a wrapper cookbook and build the node['omnibus_updater']['direct_url'] value based on your specific requirements.

To do this, you would specify the version of Chef you want in your production environment like we did before.

{     "name": "production",      "description": "Use approved, well-tested version of chef in Prod.",      "chef_type": "environment",     "json_class": "Chef::Environment",     "default_attributes": {        "omnibus_updater": {           "version": "11.8.2"        }     }  }

Then you would write a recipe, like the one in the example below, that uses cross-platform logic to set the node['omnibus_updater']['direct_url'] attribute to point to the appropriate chef-client package before calling the omnibus_updater cookbook via include_recipe.

# If no version is specified, use a default value (latest)  version = node['omnibus_updater']['version'] || '11.8.2'    if platform_family?('rhel')     node.default['omnibus_updater']['direct_url'] = "http://example.com/chef_#{version}-1.el#{node['platform_version'].to_i}.#{node['kernel']['machine']}.rpm"    elsif platform_family('debian')     node.default['omnibus_updater']['direct_url'] = "http://example.com/chef_#{version}-1.#{node['platform']}.#{node['platform_version']}_#{node['kernel']['machine']}.deb"    else    Chef::Log.warn "The platform #{node['platform']} has not been accounted for in the download logic. Please update this recipe accordingly."  end    include_recipe "omnibus_updater"

Summary

Using Heavy Water Operations' omnibus_updater cookbook you can avoid the laborious and time consuming practice of manually upgrading your chef-client. The omnibus_updater cookbook has other useful features that might interest you so I encourage you to read its documentation.

No comments:

Post a Comment