action :periodic action :delete action :create // default action :install // also default action [:enable, :start] action [:stop, :disable]
Verify apache is running: curl -I localhost
Chef helps you express your infrastructure policy – how your software is delivered and maintained on your servers – as code. When infrastructure is code, it becomes more maintainable, versionable, testable, and collaborative.
A great way to get started with Chef is to log in to a server, or node, and configure it directly.
What the following should provide us:
In the next step, you'll install the Chef tools and a text editor on your own machine, or use a virtual machine in the cloud that we provide that already has everything set up. You'll use that machine in the lessons that follow.
The normal Chef workflow involves managing servers remotely from your workstation. But in this tutorial, you'll log in to a server and manage it directly to get a feel for how Chef works.
The easiest way to get started is to use a free trial Ubuntu 14.04 virtual machine that we provide. The virtual machine runs in your browser and has the set of Chef tools, called the Chef DK, and several popular text editors pre-installed. You can also set up your own server to use with this tutorial.
mkdir ~/chef-repo cd ~/chef-repo
In this step, you'll first create the file and set the initial MOTD. To keep things basic, you'll configure the file in the /tmp directory.
Next, you'll write what's called a recipe to describe the desired state of the MOTD file. Then you'll run chef-client, the program that applies your Chef code to place your system in the desired state. Typically, chef-client downloads and runs the latest Chef code from the Chef server, but in this lesson, you'll run chef-client in what's called local mode to apply Chef code that exists locally on your virtual machine.
From your ~/chef-repo directory, create a file named hello.rb, add these contents, and then save the file.
// in hello.rb
file '/tmp/motd' do content 'hello world' end
// from the terminal window, run the chef-client command to apply what you have written
chef-client --local-mode hello.rb
The output will tell us that a new file /tmp/motd was created (The warnings will relate to concepts we haven't covered just yet)
Now verify that the file was written. Run the more command, which prints a file to the console.
more /tmp/motd
What happens if you run the command a second time?
chef-client --local-mode hello.rb
It gives a different response, letting us know that the file is already up to date. This is beause Chef applies the configuration only when it needs to.
Chef looks at the current configuration state and applies the action only if the current state doesn't match the desired state. Here, Chef doesn't create or modify /tmp/motd because it already exists and its contents didn't change. We call this approach "test and repair".
// in hello.rb
file '/tmp/motd' do content 'hello chef' end
chef-client --local-mode hello.rb
This time Chef applies the action and shows the difference because you've changed the desired state of the file
echo 'hello robots' > /tmp/motd
chef-client --local-mode hello.rb
// the chef client ensures that the changes aren't kept and the original configuration is restored
In practice, it's common to configure chef-client to act as a service that runs periodically or in response to an event, such as a commit to source control. Running Chef through automation helps to ensure that your servers remain configured as you expect and also enables them to be reconfigured when you need them to be.
in the ~/chef-repo directory, create a new file named goodbye.rb and save the following...
// goodbye.rb
file 'tmp/motd' do action :delete end
chef-client --local-mode goodbye.rb
more /tmp/motd // gives No such file or directory
Summary
You ran a few basic Chef commands and got a flavor of what Chef can do. You learned that a resource describes one part of the system and its desired state. You worked with a file, which is one kind of resource.
** Resources describe the what, not the how
A recipe is a file that holds one or more resources. Each resource declares what state a part of the system should be in, but not how to get there. Chef handles these complexities for you.
In this lesson, you declared that the file /tmp/motd must exist and what its contents are, but you didn't specify how to create or write to the file. This layer of abstraction can not only make you more productive, but it can also make your work more portable across platforms.
** Resources have actions
When you deleted the file, you saw the :delete action.
Think of an action as the process that achieves the desired configuration state. Every resource in Chef has a default action, and it's often the most common affirmative one – for example, create a file, install a package, and start a service.
When we created the file we didn't specify the :create action because :create is the default. But of course you can specify it if you want.
The documentation for each resource type, file for example, explains the type's default action.
** Recipes organize resources
In Chef, hello.rb is an example of a recipe, or an ordered series of configuration states. A recipe typically contains related states, such as everything needed to configure a web server, database server, or a load balancer.
Our recipe states everything we need to manage the MOTD file. You used chef-client in local mode to apply that recipe from the command line.
Let's extend what you learned about file management in the previous lesson to manage the Apache HTTP Server package and its service.
Of course, you can set up one web server manually. But with Chef it'll be easier to manage your infrastructure as you scale, add complexity, and roll out new configuration policies.
In this part you'll configure Apache. Because we want to install the latest version of Apache, it's important to ensure that your system's package index contains the latest list of what packages are available.
You could run the apt-get update command manually when you bring up your instance. But over time, you would need to remember to periodically update the apt cache to get the latest updates. Chef provides the apt_update resource to automate the process.
From your ~/chef-repo directory, add this code to a file named webserver.rb
webserver.rb
apt_update 'Update the apt cache daily' do frequency 86_400 action :periodic end
In a production environment, you might run Chef periodically to ensure your systems are kept up to date. As an example, you might run Chef multiple times in a day. However, you likely don't need to update the apt cache every time you run Chef. The frequency property specifies how often to update the apt cache (in seconds.) Here, we specify 86,400 seconds to update the cache once every 24 hours. (The _ notation is a Ruby convention that helps make numeric values more readable.)
The :periodic action means that the update occurs periodically. Another option would be to use the :update action to update the apt cache each time Chef runs.
Now let's install the Apache package, apache2. Modify webserver.rb to look like this.
webserver.rb
apt_update 'Update the apt cache daily' do frequency 86_400 action :periodic end
package 'apache2'
To apply the recipe...
sudo chef-client --local-mode webserver.rb
Now let's first enable the Apache service when the server boots and then start the service. Modify webserver.rb to look like this.
webserver.rb
apt_update 'Update the apt cache daily' do frequency 86_400 action :periodic end
package 'apache2'
service 'apache2' do supports :status => true action [:enable, :start] end
Ubuntu 14.04 provides two init systems. The supports :status => true part tells Chef that the apache2 init script supports the status message. This information helps Chef use the appropriate strategy to determine if the apache2 service is running. If you're interested, read this blog post
Apply it with main command.
The package will already be installed, so there will be nothing to do.
webserver.rb
apt_update 'Update the apt cache daily' do frequency 86_400 action :periodic end
package 'apache2'
service 'apache2' do supports :status => true action [:enable, :start] end
file '/var/www/html/index.html' do content '<html
<body> <h1>hello world</h1> </body>
end
curl localhost // shows the data back
You saw how to work with the package and service resources. You now know how to work with four types of resources: file, apt_update, package, and service.
You also saw how to apply multiple actions. But how does Chef know what order to apply resources and actions?
Chef works in the order you specify
A cookbook provides structure to your recipes and enables you to more easily reference external files, such as our web server's home page. In essence, a cookbook helps you stay organized.
Let's create a cookbook to make our web server recipe easier to manage.
First, from ~/chef-repo
mkdir cookbooks cd cookbooks
chef generate cookbook learn_chef_apache2
Note the default recipe, named default.rb. This is where we'll move our Apache recipe in a moment.
chef generate template learn_chef_apache2 index.html
The file index.html.erb get created under learn_chef_apache2/templates/default
We can now move our html files to here
NOTE Here, you're adding the web site content directly to your cookbook for learning purposes. In practice, your web site content would more likely be some build artifact, for example a .zip file on your build server. With Chef, you could pull updated web content from your build server and deploy it to your web server.
Write our default.rb
apt_update 'Update the apt cache daily' do frequency 86_400 action :periodic end
package 'apache2'
service 'apache2' do supports :status => true action [:enable, :start] end
template '/var/www/html/index.html' do source 'index.html.erb' end
sudo chef-client --local-mode --runlist 'recipe[learn_chef_apache2]'
in this example, recipe[learn_chef_apache2] is the same as specifying recipe[learn_chef_apache2::default], meaning we want to run the learn_chef_apache2 cookbook's default recipe, default.rb
curl localhost
Summary
Your web server is shaping up! With a cookbook you're now better organized. A cookbook adds structure to your work. You can now author your HTML code in its own file and use a template resource to reference it from your recipe.
You also saw the run-list. The run-list lets you specify which recipes to run, and the order in which to run them. This is handy once you have lots of cookbooks, and the order in which they run is important.
Keep in mind that the web server cookbook you wrote in this lesson likely won't be the one you'd use in production. Only you know the specific needs for your infrastructure. You bring your requirements and Chef provides the tools that help you meet them.
Chef is comprised of 3 elements:
Chef server acts as a central repository for your cookbooks as well as for information about every node it manages. For example, the Chef server knows a node's fully qualified domain name (FQDN) and its platform.
A node is any computer that is managed by a Chef server. Every node has the Chef client installed on it. The Chef client talks to the Chef server. A node can be any physical or virtual machine in your network
Chef server acts as a central repository for your cookbooks as well as for information about every node it manages. The knife command enables you to communicate with the Chef server from your workstation.
There are two ways to work with a Chef server.
In production, the decision to use hosted Chef or manage your own Chef server depends on your organization's requirements and preferences. If you're interested in setting up your own Chef server, we recommend that you first complete this tutorial using hosted Chef. Then you can follow the Install and manage your own Chef server
knife is the command-line tool that provides an interface between your workstation and the Chef server. knife enables you to upload your cookbooks to the Chef server and work with nodes, the servers that you manage.
knife requires two files to communicate with the Chef server – an RSA private key and a configuration file.
The configuration file is typically named knife.rb. It contains information such as the Chef server's URL, the location of your RSA private key, and the default location of your cookbooks.
Both of these files are typically located in a directory named .chef. Every time knife runs, it looks in the current working directory for the .chef directory. If the .chef directory does not exist, knife searches up the directory tree for a .chef directory. This process is similar to how tools such as Git work.
The next step is to create the ~/learn-chef/.chef directory and add your RSA private key and knife configuration files.
Generate your knife configuration file
That is essentially "forking" an upstream cookbook eg one from the supermarket. If we add the upstream recipe to the metadata.rb
we can add depends 'haproxy'
to install the latest version of that dependency eg the supermarket here. We can all define the versions.
What we can now do is add an attribute to our cookbook.
We can then override the recipe in default.rb
using the following:
node.default['haproxy']['member'] = [{ "this_is_a_var_from_the_video" }]