machine¶
Use the machine resource to define one (or more) machines, and then converge entire clusters of machines. This allows clusters to be maintained in a version control system and to be defined using multi-machine orchestration scenarios. For example, spinning up small test clusters and using them for continuous integration and local testing, building clusters that auto-scale, moving a set of machines in one cluster to another, building images, and so on.
Each machine is declared as a separate application topology, defined using operating system- and provisioner-independent files. Recipes (defined in cookbooks) are used to manage them. The chef-client is used to converge the individual nodes (machines) within the cluster.
Warning
This functionality is available with Chef provisioning and is packaged in the Chef development kit. Chef provisioning is a framework that allows clusters to be managed by the chef-client and the Chef server in the same way nodes are managed: with recipes. Use Chef provisioning to describe, version, deploy, and manage clusters of any size and complexity using a common set of tools.
Syntax¶
The syntax for using the machine resource in a recipe is as follows:
machine 'name' do
attribute 'value' # see properties section below
...
action :action # see actions section below
end
where
machinetells the chef-client to use theChef::Provider::Machineprovider during the chef-client runnameis the name of the resource block and also the name of the machineattributeis zero (or more) of the properties that are available for this resourceactionidentifies which steps the chef-client will take to bring the node into the desired state
Actions¶
This resource has the following actions:
:allocate- Use to create a machine, return its machine identifier, and then (depending on the provider) boot the machine to an image. This reserves the machine with the provider and subsequent
:allocateactions against this machine no longer need to create the machine, just update it. :converge- Default. Use to create a machine, return its machine identifier, boot the machine to an image with the specified parameters and transport, install the chef-client, and then converge the machine.
:converge_only- Use to converge a machine, but only if the machine is in a ready state.
:destroy- Use to destroy a machine.
:nothing- Define this resource block to do nothing until notified by another resource to take action. When this resource is notified, this resource block is either run immediately or it is queued up to be run at the end of the Chef Client run.
:ready- Use to create a machine, return its machine identifier, and then boot the machine to an image with the specified parameters and transport. This machine is in a ready state and may be connected to (via SSH or other transport).
:setup- Use to create a machine, return its machine identifier, boot the machine to an image with the specified parameters and transport, and then install the chef-client. This machine is in a ready state, has the chef-client installed, and all of the configuration data required to apply the run-list to the machine.
:stop- Use to stop a machine.
In-Parallel Processing¶
In certain situations Chef provisioning will run multiple machine processes in-parallel, as long as each of the individual machine resources have the same declared action. The machine_batch resource is used to run in-parallel processes.
Chef provisioning will processes resources in-parallel automatically, unless:
- The recipe contains complex scripts, such as when a file resource sits in-between two machine resources in a single recipe. In this situation, the resources will be run sequentially
- The actions specified for each individual machine resource are not identical; for example, if resource A is set to
:convergeand resource B is set to:destroy, then they may not be processed in-parallel
To disable in-parallel processing, add the auto_machine_batch setting to the client.rb file, and then set it to false.
For example, a recipe that looks like:
machine 'a'
machine 'b'
machine 'c'
will show output similar to:
$ CHEF_DRIVER=fog:AWS chef-apply cluster.rb
...
Converging 1 resources
Recipe: @recipe_files::/Users/jkeiser/oc/environments/metal-test-local/cluster.rb
* machine_batch[default] action converge
- [a] creating machine a on fog:AWS:862552916454
- [a] key_name: "metal_default"
- [a] tags: {"Name"=>"a", ...}
- [a] name: "a"
- [b] creating machine b on fog:AWS:862552916454
- [b] key_name: "metal_default"
- [b] tags: {"Name"=>"b", ...}
- [b] name: "b"
- [c] creating machine c on fog:AWS:862552916454
- [c] key_name: "metal_default"
- [c] tags: {"Name"=>"c", ...}
- [c] name: "c"
- [b] machine b created as i-eb778fb9 on fog:AWS:862552916454
- create node b at http://localhost:8889
- add normal.tags = nil
- add normal.metal = {"location"=>{"driver_url"=>"fog:AWS:862552916454", ...}}
- [a] machine a created as i-e9778fbb on fog:AWS:862552916454
- create node a at http://localhost:8889
- add normal.tags = nil
- add normal.metal = {"location"=>{"driver_url"=>"fog:AWS:862552916454", ...}}
- [c] machine c created as i-816d95d3 on fog:AWS:862552916454
- create node c at http://localhost:8889
- add normal.tags = nil
- add normal.metal = {"location"=>{"driver_url"=>"fog:AWS:862552916454", ...}}
- [b] waiting for b (i-eb778fb9 on fog:AWS:862552916454) to be ready ...
- [c] waiting for c (i-816d95d3 on fog:AWS:862552916454) to be ready ...
- [a] waiting for a (i-e9778fbb on fog:AWS:862552916454) to be ready ...
...
Running handlers:
Running handlers complete
Chef Client finished, 0/0 resources updated in 4.053363945 seconds
- [c] run 'chef-client -l auto' on c
Running handlers:
Running handlers complete
Chef Client finished, 1/1 resources updated in 59.64014 seconds
At the end, it shows 1/1 resources updated. The three machine resources are replaced with a single machine_batch resource, which then runs each of the individual machine processes in-parallel.
Properties¶
This resource has the following properties:
adminRuby Type: true, false
Use to specify whether the chef-client is an API client.
allow_overwrite_keysRuby Type: true, false
Use to overwrite the key on a machine when it is different from the key specified by
source_key.attributeUse to specify an attribute, and then modify that attribute with the specified value. The following patterns may be used to specify the value.
attribute <name>, <value>
attribute [<path>], <value>
The following example will set attribute
atob:attribute 'a', 'b'
The following example will set attribute
node['a']['b']['c']todand will ignore attributesa.b.x,a.b.y, etc.:attribute %w[a b c], 'd'
The following example is similar to
%w[a b c], 'd':attribute 'a', { 'b' => { 'c' => 'd' } }
Each modified attribute should be specified individually. This attribute should not be used in the same recipe as
attributes.attributes- Use to specify a Hash that contains all of the normal attributes to be applied to a machine. This attribute should not be used in the same recipe as
attribute. chef_configRuby Type: String
Use to specify a string that contains extra configuration settings for a machine.
chef_environment- The name of the environment.
chef_serverRuby Type: Hash
The URL for the Chef server.
completeUse to specify if all of the normal attributes specified by this resource represent a complete specification of normal attributes for a machine. When
true, any attributes not specified will be reset to their default values. For example, if a machine resource is empty and setscompletetotrue, all existing attributes will be reset:machine "foo" do complete "true" end
convergeRuby Type: true, false
Use to manage convergence when used with the
:createaction. Set tofalseto prevent convergence. Set totrueto force convergence. Whennil, the machine will converge only if something changes.driverRuby Type: Chef::Provisioning::Driver
Use to specify the URL for the driver to be used for provisioning.
filesRuby Type: Hash
A list of files to upload. Syntax:
REMOTE_PATH => LOCAL_PATH_OR_HASH.For example:
files '/remote/path.txt' => '/local/path.txt'
or:
files '/remote/path.txt' => { :local_path => '/local/path.txt' }
or:
files '/remote/path.txt' => { :content => 'foo' }
from_imageRuby Type: String
Use to specify an image created by the machine_image resource.
ignore_failureRuby Type: true, false | Default Value:
falseContinue running a recipe if a resource fails for any reason.
machine_optionsRuby Type: Hash
A Hash that is specifies driver options.
nameRuby Type: String
The name of the machine.
notifiesRuby Type: Symbol, ‘Chef::Resource[String]’
A resource may notify another resource to take action when its state changes. Specify a
'resource[name]', the:actionthat resource should take, and then the:timerfor that action. A resource may notify more than one resource; use anotifiesstatement for each resource to be notified.A timer specifies the point during the Chef Client run at which a notification is run. The following timers are available:
:before- Specifies that the action on a notified resource should be run before processing the resource block in which the notification is located.
:delayed- Default. Specifies that a notification should be queued up, and then executed at the end of the Chef Client run.
:immediate,:immediately- Specifies that a notification should be run immediately, per resource notified.
The syntax for
notifiesis:notifies :action, 'resource[name]', :timer
ohai_hintsRuby Type: Hash
An Ohai hint to be set on the target node. For example:
'ec2' => { 'a' => 'b' } creates file ec2.json with json contents { 'a': 'b' }.private_key_optionsRuby Type: Hash
Use to generate a private key of the desired size, type, and so on.
public_key_formatRuby Type: String | Default Value:
pemUse to specify the format of a public key. Possible values:
pemandder.public_key_pathRuby Type: String
The path to a public key.
raw_jsonThe machine as JSON data. For example:
{ "name": "node1", "chef_environment": "_default", "json_class": "Chef::Node", "automatic": { "languages": { "ruby": { ... }, ... ... }
recipeUse to add a recipe to the run-list for a machine. Use this property multiple times to add multiple recipes to a run-list. Use this property along with
roleto define a run-list. The order in which therecipeandroleproperties are specified will determine the order in which they are added to the run-list. This property should not be used in the same recipe asrun_list. For example:recipe 'foo' role 'bar' recipe 'baz'
remove_recipe- Use to remove a recipe from the run-list for the machine.
remove_role- Use to remove a role from the run-list for the machine.
remove_tag- Use to remove a tag.
retriesRuby Type: Integer | Default Value:
0The number of times to catch exceptions and retry the resource.
retry_delayRuby Type: Integer | Default Value:
2The retry delay (in seconds).
roleUse to add a role to the run-list for the machine. Use this property multiple times to add multiple roles to a run-list. Use this property along with
recipeto define a run-list. The order in which therecipeandroleproperties are specified will determine the order in which they are added to the run-list. This property should not be used in the same recipe asrun_list. For example:recipe 'foo' role 'bar' recipe 'baz'
run_listAn array of strings that specifies the run-list to apply to a machine. This property should not be used in the same recipe as
recipeandrole. For example:[ 'recipe[COOKBOOK::RECIPE]','COOKBOOK::RECIPE','role[NAME]' ]
source_key- Use to copy a private key, but apply a different
formatandpassword. Use in conjunction withsource_key_pass_phrase`andsource_key_path. source_key_pass_phraseRuby Type: String
The pass phrase for the private key. Use in conjunction with
source_key`andsource_key_path.source_key_pathRuby Type: String
The path to the private key. Use in conjunction with
source_key`andsource_key_pass_phrase.subscribesRuby Type: Symbol, ‘Chef::Resource[String]’
A resource may listen to another resource, and then take action if the state of the resource being listened to changes. Specify a
'resource[name]', the:actionto be taken, and then the:timerfor that action.Note that
subscribesdoes not apply the specified action to the resource that it listens to - for example:file '/etc/nginx/ssl/example.crt' do mode '0600' owner 'root' end service 'nginx' do subscribes :reload, 'file[/etc/nginx/ssl/example.crt]', :immediately end
In this case the
subscribesproperty reloads thenginxservice whenever its certificate file, located under/etc/nginx/ssl/example.crt, is updated.subscribesdoes not make any changes to the certificate file itself, it merely listens for a change to the file, and executes the:reloadaction for its resource (in this examplenginx) when a change is detected.A timer specifies the point during the Chef Client run at which a notification is run. The following timers are available:
:before- Specifies that the action on a notified resource should be run before processing the resource block in which the notification is located.
:delayed- Default. Specifies that a notification should be queued up, and then executed at the end of the Chef Client run.
:immediate,:immediately- Specifies that a notification should be run immediately, per resource notified.
The syntax for
subscribesis:subscribes :action, 'resource[name]', :timer
tag- Use to add a tag.
tags- Use to add one (or more) tags. This will remove any tag currently associated with the machine. For example:
tags :a, :b, :c. validatorRuby Type: true, false
Use to specify if the chef-client is a chef-validator.
Examples¶
The following examples demonstrate various approaches for using resources in recipes. If you want to see examples of how Chef uses resources in recipes, take a closer look at the cookbooks that Chef authors and maintains: https://github.com/chef-cookbooks.
Build machines dynamically
machine 'mario' do
recipe 'postgresql'
recipe 'mydb'
tag 'mydb_master'
end
num_webservers = 1
1.upto(num_webservers) do |i|
machine "luigi#{i}" do
recipe 'apache'
recipe 'mywebapp'
end
end
Get a remote file onto a new machine
A deployment process requires more than just setting up machines. For example, files may need to be copied to machines from remote locations. The following example shows how to use the remote_file resource to grab a tarball from a URL, create a machine, copy that tarball to the machine, and then get that machine running by using a recipe that installs and configures that tarball on the machine:
remote_file 'mytarball.tgz' do
url 'https://myserver.com/mytarball.tgz'
end
machine 'x'
action :allocate
end
machine_file '/tmp/mytarball.tgz' do
machine 'x'
local_path 'mytarball.tgz'
action :upload
end
machine 'x' do
recipe 'untarthatthing'
action :converge
end
Build machines that depend on each other
The following example shows how to create two identical machines, both of which cannot exist without the other. The first machine resource block creates the first machine by omitting the recipe that requires the other machine to be defined. The second resource block creates the second machine; because the first machine exists, both recipes can be run. The third resource block applies the second recipe to the first machine:
machine 'server_a' do
recipe 'base_recipes'
end
machine 'server_b' do
recipe 'base_recipes'
recipe 'theserver'
end
machine 'server_a' do
recipe 'theserver'
end
Use a loop to build many machines
1.upto(10) do |i|
machine "hadoop#{i}" do
recipe 'hadoop'
end
end
Converge multiple machine types, in-parallel
The machine_batch resource can be used to converge multiple machine types, in-parallel, even if each machine type has different drivers. For example:
machine_batch do
machine 'db' do
recipe 'mysql'
end
1.upto(50) do |i|
machine "#{web}#{i}" do
recipe 'apache'
end
end
end
Define machine_options for a driver
require 'chef/provisioning_driver'
machine 'wario' do
recipe 'apache'
machine_options :driver_options => {
:base_image => {
:name => 'ubuntu',
:repository => 'ubuntu',
:tag => '14.04'
},
:command => '/usr/sbin/httpd'
}
end
where provisioning_driver and :driver_options specify the actual driver that is being used to build the machine.
Build a machine from a machine image
machine_image 'web_image' do
recipe 'apache2'
end
machine 'web_machine' do
from_image 'web_image'
end
Set up a VPC, route table, key pair, and machine for Amazon AWS
require 'chef/provisioning/aws_driver'
with_driver 'aws::eu-west-1'
aws_vpc 'test-vpc' do
cidr_block '10.0.0.0/24'
internet_gateway true
end
aws_route_table 'ref-public1' do
vpc 'test-vpc'
routes '0.0.0.0/0' => :internet_gateway
end
aws_key_pair 'ref-key-pair'
m = machine 'test' do
machine_options bootstrap_options: { key_name: 'ref-key-pair' }
end