All about Chef - Shashankreddysunkara/Chef GitHub Wiki

Chef is pull based

**chef-client is an agent in node and chef server in the master relationship is need **

if there is no need of using chef-client to pull from chef server. You need to override default mode to local mode i.e., --local-mode or -z and You yourself have to run the recipe (i.e., sudo chef-client --local-mode hello.rb) but before that, you create a recipe as "name.rb" in /home/vagrant/.

file '/hello.txt' do content 'Hello, World!' end

That's it

chef will create a file for us in / as /hello.txt with content based on the recipe in /home/vagrant/

with that said, recipes are just .rb Ruby files.

Well, in Chef we manage any system component using the concept of a resource. Chef resources are a way to manage a system component.

When I write a recipe, those Ruby files, they are filled with Chef resources.

That's why when you execute a recipe, chef-client will look for cookbook directory existed in above the user folder or not.

That cookbook contains a bunch of resources like httpd package or ntp service to install or start respectively.

ex: Package

package 'httpd' do action :install end

ex: Service

service 'ntp' do action [ :enable, :start ] end

In general, Chef resources should be able to function on a variety of platforms in a variety of environments.

This is, again, an example of the file resource.

ex: File

file '/etc/motd' do content 'I am Jesus on bike' end

file '/etc/php.ini.default' do action :delete end

Now that you've seen some examples of some Chef resources, here's the formal definition: a resource is a statement of configuration policy. But what does the vague definition actually mean? A Chef resource describes the desired state of an element of our infrastructure and the steps needed to bring that item into the desired state.

So a resource is meant to configure a particular system component, usually a component of a server, and it describes how you want it configured. In other words, we use resources to declare how to configure a server and the Chef client will enforce that configuration for us.

When using Chef resources we should be aware that **they are defined inside of our Chef scripts which we call recipes, those .rb files. **

When calling a resource, how is the code actually written?

We always start by defining the type of resource we're working with. For ex: "file" declares what system component we're going to configure. In some of the previous examples, we saw other types of resources such as package and service.

ex:

file '/hello.txt' do content 'Hello, world!' end

SAY as The TYPE named NAME should be ACTION 'd with PROPERTIES.

TYPE => file NOTE: path to the file is described in NAME as "/hello.txt" NAME => /hello.txt ACTION => NONE PROPERTIES => content NOTE: content keyword is called as PROPERTY

ex:

file '/etc/php.ini.default' do action :delete end

TYPE => file NOTE: path to te file is described in NAME as "/etc/php.ini.default" NAME => /etc/php.ini.default ACTION => delete PROPERTIES => action

There are many built-in Chef resource types, and you can also create your own. After declaring the type of resource we're working with, we then need to name the resource. If you're working with a file or a directory, for example, the name of the resource is also the path to that component. When working with a service, it would typically be the name used to configure it manually such as httpd or apache two. Notice that after we've declared the type and name of the resource, we then define what the content of the file should be. The content keyword is called a property. Each built-in Chef resource has a list of properties that can be configured on that component. For files you could think of the permissions on a file as other properties that could be defined. For packages, you might think of the installation directory for the package or the version that should be installed, as properties.

It's often said that resources take action with the defined properties.

In order to place a resource in the desired state that we define with properties, we take action on that resource. **Action is always taken on a resource whether it is defined or not. **

ex:

file '/hello.txt' do content 'Hello, world!' end

In this ex: you can see that there is no action defined. This is going to cause the chef-client to take the default action for this resource. Default actions usually follow what's called the principle of least surprise.

What do you think the default action for the file resource could be? You may have guessed that we're going to take the action of create on this file. For us to fill it with content, it should exist.

So, above ex: will be considered as follows indirectly as default

file '/hello.txt' do content 'Hello, world!' action :create end

For other resources, you should be aware of their default actions, although it will usually be what is least surprising. The package resource's default action is "install" and for service is "nothing". Remember that you can always define the action that should be taken, but if no action is listed, the default action is taken.

Test and Repair This concept is nothing but testing the resource and repairing or bringing back to the defined desired state mentioned in the recipe.

Chef-client takes action only when it needs to. Think of it as test and repair.

chef looks at the current state of each resource and take action only when that resource is out of policy.

Remember, the policy is whatever we define inside of our recipe. Before the Chef client ever takes action, it examines the state of a resource. If that resource is out of policy, it will take whatever steps needed to bring that item back into the desired state.

How do we define a different policy for this file? This is where docs.chef.io comes in. READ IT

ex:

file '/hello.txt' do content 'Hello, world!' action :create mode 0644 owner 'root' group 'root' end

You can add properties in any order you'd like. And I'll state here that I'd like to define the mode. This will accept a string or an integer value, and I'll set read/write permissions for the owner. In addition to this, I'll specify who the owner and what group this file should belong to with the owner and group properties. Both of these accept a string, and I'll specify that the root user and the root group are the permissions that should be set on this file.

If you come from a developer background, I'm sure you're curious about documenting what this recipe does and how to track changes to it.

So, shouldn't we have a readme, some metadata, and version control?

A cookbook is Chef's fundamental unit of policy distribution. This means that once we're working with a Chef server we won't be distributing individual recipes to servers, we'll be distributing cookbooks.

These cookbooks contain all the instructions on how to use the recipes that come with it and any supporting components your recipes might need to function.

ex: chef generate cookbook cookbooks/apache

Thinking about the Hello.rb recipe we worked with so far, you're probably excited to see what else we can do with Chef recipes such as configuring web servers. If you come from a developer background, I'm sure you're curious about documenting what this recipe does and how to track changes to it. So, shouldn't we have a readme, some metadata, and version control? A cookbook is Chef's fundamental unit of policy distribution. This means that once we're working with a Chef server we won't be distributing individual recipes to servers, we'll be distributing cookbooks. These cookbooks contain all the instructions on how to use the recipes that come with it and any supporting components your recipes might need to function. Cookbooks can generally be thought of as containers for our recipes. When we author cookbooks, it's important to think about it as a standalone unit that defines a scenario and contains all the components needed to support that scenario. For example, a MySQL cookbook would contain all the instructions on how to install and configure a database. Let's look at how to generate a cookbook with the ChefDK. First, I'm going to be working out of the home directory. Next, I'm going to create a working directory for my cookbooks using the mkdir command. The Chef command comes with the Chef development kit and is primarily used for generating cookbooks and cookbook components. To learn more about any command that comes with the ChefDK, add the --help option to it to see the usage. For example, I'm going to head over to my terminal session. If I wanted to generate a cookbook, the chef generate command can help me out. Adding --help here shows how to actually select a generator like the cookbook generator here. If I want to learn more about how to use it, I can type chef generate cookbook --help and see all the usage. It states here that I need to provide a name for my cookbook, which, in our case, is also going to be the path to our cookbook. I'm going to run chef generate to create a web server cookbook, which I will call Apache. We'll say chef generate cookbook. I'm going to place this cookbook in the cookbooks directory and I'm going to name it Apache to symbolize setting up our web server. When the command completes successfully, you'll see a message that states that your cookbook is ready and change into it. Now, I would like to take a look at what this cookbook actually is structured like. So, to do this, we're actually going to install the tree package. You can do this the same way you installed your text editor before. I'll say sudo yum install tree and I'll add the -y command to just accept any prompts. Now, running the tree command allows me to take a look at the directory structure for our cookbook. You can see here that the Apache cookbook contains several components. We want to look at what these components are and what they're used for. So, in particular, if you want to follow along, take a look at a tree on your Apache cookbook. Now that we've generated this cookbook, let's look at the components that come with it starting with the readme. A readme is going to be nothing more than a description of the cookbook's features written in standard Markdown. In our case, we ought to document how to use the cookbook and also what each recipe inside of it is for. This is a human-readable file and is very similar to what you might see in a readme displayed on a GitHub page. Next, we should be aware of the metadata file. Each cookbook is going to have some amount of metadata associated with it. This might be the name of the cookbook, a description of what it's used for, and how to get ahold of the person responsible for maintaining it. Here's an example of what the metadata file looks like. And you can see, we describe what the cookbook is used for and we also document the version of our cookbook. Very important to understand that the version of the cookbook is maintained inside of its metadata file. You'll also notice a folder called Recipes. The Recipes directory contains all of those Ruby files we're interested in developing in this class. The recipes will all go in this directory and when you've scaffold out a cookbook with chef generate, you'll notice there's always going to be a default recipe. The default recipe is used to set up a default configuration for this cookbook. We'll chat more about this later on. But for now, understand that the default recipe contains nothing more than some comments about what the cookbook is used for and the recipe within it. Comments are those pound symbols that you see at the beginning of each line. Now, heading back over to my terminal session here, you'll also notice the spec and test directories. And depending on what version of the Chef development kit you're using, these directories might look slightly different. So, do keep that in mind. With newer versions of the ChefDK, you might see a slightly different directory structure here. The ChefDK builds testing components into each cookbook that you generate to make it easy to check your code for functional integrity and reliability. The spec directory is used for unit testing your cookbooks. This is something we won't go into detail within this class. The test directory is used for running integration tests for your cookbooks. You'll get to look forward to a short demo of Test Kitchen later in this class and definitely check out the further resources section to learn about where you can find more. Now, if you look at hidden files or folders inside of your Apache cookbook itself, you'll also notice a .git directory. This is assuming that you have installed Git for version control. If you've installed Git, when you run the chef generate cookbook command, you'll see that it creates a .git directory. This allows you to actually work with version control, something I won't go into in this class, but you should understand that you can track changes to your cookbook using Git or any other revision control system, such as Subversion. So, feel free to use that to track changes to your recipes as you go, but understand it's up to you to set up any upstream repositories for Git. I will not be tracking changes as I go throughout these demos. With that in mind, you now understand a little bit about how to actually create a cookbook and the different components that are inside of it.

The Apache Cookbook


ex: server.rb recipe in cookbooks/apache/recipes/

package 'httpd'

file '/var/www/html/index.html' do content '

Hello, World!

'

end

service 'httpd' do action [:start, :enable] end

With that said, Lets run the chef-client

**sudo chef-client --local-mode cookbooks/apache/recipes/server.rb **

To test it, run curl localhost

------------------------------ Welcome to Chef-------------------------

--runlist "recipe[COOKBOOK::RECIPE]"

or

-r "recipe[COOKBOOK::RECIPE]"

In local mode, chef needs a list of recipes to apply to the system. This is called a run list.

A run list is an ordered collection of recipes to execute.

ex: sudo chef-client -z -r "recipe[apache::server]"

ex: sudo chef-client -zr "recipe[COOKBOOK(::default)]" This syntax considers default recipe

include_recipe


A recipe can include one or more recipes located in cookbooks by using the include_recipe method.

ex: if u mention this include_recipe 'apache::server' inside ~/cookbooks/apache/recipes/default.rb

sudo chef-client -z -r "recipe[apache]" will run default as well as server

Resource


Resource is a statement of configuration policy.

It describes the desired state of an element of your infrastructure and the steps needed to bring that item to the desired state.

Ohai


If you're using Chef, you're probably curious about how we could actually configure many different servers at once.

In particular, think about the Apache cookbook we've written. It contains instructions on configuring a basic web server. Now, these instructions can be distributed to as many different web servers as you'd like. But what about when you make more advanced configurations? For example, there may come a time where you need to have the IP address inserted into some type of configuration file. How do you deal with configurations where some information, such as a host specific detail, like the host name or IP Address, might be different? In particular, you might think about gathering the IP Address, hostname, maybe the memory available to this server, or the speed of the processors. Now, you can gather this information manually, if you'd like.

So, **how can I capture this data in real time? Or as close to real time as possible? ** The answer is Ohai

**Ohai is the tool that will actually gather host-specific details for you. And it will present them to you in json. This is, quite literally, a command line tool, called Ohai. **

And you can run it anywhere that you have the Chef client or the chef development kit installed.

The amazing thing about Ohai is that every single time Chef runs, every time you execute the chef client, it actually executes an Ohai for you.

**And stores all this information in an object you can query called Node, the node object. **

The Node Object is going to be this json representation of our system. It stores all of the values that we gather with Ohai as attributes.

We call the values on the node object, like IP Address and hostname, node attributes.

The structure of the Node Object is very similar to json. It has a bunch of parent values with some child values. In particular, IP Address and hostname are parent attributes. Whereas attributes like memory or CPU have child elements beneath them.

Instead of actually hard-coating values into our recipes for IP Address and hostname, we can actually go through and reference the Node Object to, for example, extract the hostname. We do this by calling the Node Object and requesting the value of the hostname key.

ex: node['ipaddress']

similarly, Update the apache server.rb recipe

~/cookbooks/apache/recipes/server.rb

package 'httpd'*

file '/var/www/html/index.html' do content '

Hello, World!

'

**

ipaddress: #{node['ipaddress']}

//string interpolation **

hostname: #{node['hostname']}

end

service 'httpd' do action [:start, :enable] end

Then run sudo chef-client -z cookbooks/apache/recipes/server.rb and curl localhost to see results

Templates and embedded Ruby


Template: A cookbook template is an Embedded Ruby (ERB) template that is used to generate files.

A template may contain Ruby expressions and statements.

Place the corresponding ERB template in a cookbook's /template directory.

With that said, enter the following information in index.html.erb file in ~cookbooks/apache/templates

Firstly, cd ~ then sudo chef generate template cookbooks/apache index.html

secondly, Move your source to the template location as below

in this location ~/cookbooks/apache/templates/index.html.erb

Hello, World!

ipaddress: <%=node['ipaddress']%>

hostname: <%=node['hostname']%>

Thirdly Update the content of server.rb file in ~/cookbooks/apache/recipes/server.rb like below

package 'httpd'

template '/var/www/html/index.html' do source 'index.html.erb' end

service 'httpd' do action [:start, :enable] end

Now, after everything set up, do sudo chef-client -zr "recipe[apache]"

Chef Server


It is a hub for configuration data

how would you actually create more web servers? How would you distribute this information, your Apache cookbook, to many different servers that you might want to run your application code? We can use a Chef server to do this, or there's many other ways to accomplish the same task.

For example, using Chef to manage an additional web server, I would have to create a new server first.

We call this process provisioning a new node. Now, nodes can be created in many different ways.

Knife: A command line tool that provides an interface between a local chef-repo and the chef server.

knife --help

knife client --help

From chef-repo directory, run knife client list

knife cookbook list

knife cookbook upload apache

See you later

⚠️ **GitHub.com Fallback** ⚠️