Get Cookin' with Chef

Get Cookin’ with Chef

Hello, Level1Techs!

During this guide you will become intimately familiar with Chef, a configuration management system. Chef targets nodes in your control with status files and configures those nodes to meet the state declared in those files, if not already there. Phew, what a mouthful. But! After this walkthrough and demonstration, I hope you are as excited to get started with Chef and configuration management as I am!

First, for this demonstration, you will need three computers. All three can be VMs, physical, whatever. This guide is going to use RedHat Linux derivatives, but hopefully I can write well enough to provide enough understanding that you can go Debian or Windows based OS’es if you so choose.

So, here we go!

The Workstation

I am using Fedora 28 for my workstation. From a vanilla install, you’ll need the Chef Development Kit. To get the most recent version head on over to https://downloads.chef.io/chefdk and find the link for your operating system.
Being a fan of wget, I used that to fetch the source.

wget https://packages.chef.io/files/stable/chefdk/2.5.3/el/7/chefdk-2.5.3-1.el7.x86_64.rpm

From here, I used dnf to install the rpm. Why dnf? The cool bit about DNF is it checks for dependencies missing that are needed for the rpm, and it will install those as well. If you prefer rpm, or aren’t using Fedora, but RHEL or CentOS, check out the second command.

sudo dnf install chefdk-2.5.3-1.el7.x86_64.rpm

Or

sudo rpm -Uvh chefdk-2.5.3-1.el7.x86_64.rpm

If you’re not familiar with rpm, the U will check if the software is installed and update it to the latest version or install the latest version if it’s not there. The v is for verbose, and the h is for the “hashtag” progression.
You’ve got your workstation up and running. Fantastic! To confirm success, go ahead and run

chef --version

w00t! WHO’S THE (WO)MAN?! YOU ARE!

*Chest bump bro out fist smash keg party*

Now let’s get your server up and running.

The server

You’ll need wget installed:

sudo yum install wget -y

Then you’ll pull the latest Chef server installation. (https://downloads.chef.io/chef-server)

wget https://packages.chef.io/files/stable/chef-server/12.17.33/el/7/chef-server-core-12.17.33-1.el7.x86_64.rpm

The server is a lot beefier than the DK, so don’t be concerned if it takes a bit longer to download.

sudo rpm -Uvh chef-server-core-12.17.33-1.el7.x86_64.rpm

With this install comes a template, and your server is not in the desired state. To reach that desired state, you’ll want to run:

sudo chef-server-ctl reconfigure

This could take a while, depending on the specs of your server. Don’t worry, just sit back and enjoy the console output, or go get a cup of coffee.
Now that that is done, we’ll want to install the GUI, which is a web front end.

sudo chef-server-ctl install chef-manage

Then, you’ll run reconfigure for chef-server (again) and you’ll reconfigure chef-manage. The second time around, chef-server doesn’t take nearly as long because most of the desired state is set.

sudo chef-server-ctl reconfigure

sudo chef-manage-ctl reconfigure

Nice, still in the game? GOOD!
Let’s create our admin user. The format is:

chef-server-ctl user-create userName userFirstName userLastName userEmailAddress ‘password’

You’ll want to put your password in single quotes. There are a couple of optional variables, but this is the base template to get you into the web front end.
Open a browser and hit up your chef-server IP Address


A note about firewalls and DNS

If you’re doing this exercise as an “on prem” exercise, versus Azure, AWS, or another cloud platform, you might run into some DNS issues.
The easiest way to remedy that is add an entry to /etc/hosts for the Chef server.

ip-address-of-chef-server chef-serv

That should do it for you. So, mine is

10.0.0.110 chef-serv

You can always add an entry to your DNS server, but that is outside the scope of this demonstration (you sysadmin, you :wink: ).
Next, if you’re having an issue accessing the Chef server from the browser, either disable the firewall on the server or add a public zone entry for http and https. Again, unfortunately, that is outside the scope of this demonstration. I just wanted to offer a heads up in case you ran into an issue.


Once you log into the Chef server with your new user, you’re going to have to create an organization. The first entry can be as elaborate as you want.
“Super Awesome Tech Company, LLC”
The next line you’ll want to have something small and simple.
“awesome-tech”
Next, you’ll be given two links, one to download the starter kit and another to “Learn Chef”. Hopefully I’m doing an okay job, so go ahead and click Download Starter Kit. You’ll get a zip file on your workstation, which you can unzip with… unzip.

unzip chef-starter.zip

That is going to extract a chef-repo directory, which you can move wherever you desire.
I strongly recommend creating a ~/chef directory and moving the chef-repo there. You can also create a ~/Projects directory if that makes you feel better :blush:

Either way, once you have your chef-repo directory where you desire it most, we can create our first cookbook!

The Node

At this point you’re going to want to fire up a third VM. This can be whatever you want, but for this example, I am using CentOS 7. It is the base install, with nothing on it.
From our workstation, we are going to bootstrap the node. The bootstrap process primes the node for receiving communication from the Chef server. You’ll also name the node for configuration purposes.
From the workstation, run:

knife bootstrap *IP Address of Node* -N *name you desire for your node* -x *user with sudo permissions* --sudo

Knife is an awesome command, it allows you to interface with the Chef server from your workstation. In the above command, you’re essentially sending the chef-client payload instructions to the server and directing the execution of the command on the node. You’ll need to enter the password a couple of times in some instances, once for ssh connection and another for sudo permission.
Watch the command execute, and you can check the server by either checking your Chef server GUI for the node or ssh into the node and run

chef-client

You can also run, from the workstation:

knife node show *name you gave to the node*

Great job! Almost there! But, we kind of have a node reporting to Chef server, and not much else… So, let’s give a desired state.

Remember the chef-repo directory? Good, go ahead and cd into that and go into the cookbooks directory.
From here, you’ll want to pwd and make sure you’re in ~/…/chef-repo/cookbooks
Go ahead and create your first cookbook. We’ll call it apache, for demonstration purposes.

chef generate cookbook apache

Ta-da! Magnifique!
Now, we’ll cd into apache/recipes, and you’ll have your default.rb file. This is kind of like “main” for big programming languages.

Use your favorite editor, Sublime, Atom, vim, Emacs, Visual Studio Code, whatever, and open up that file.
It’s blank, with some generic comments as the templates. No biggie. We’re going to create some cool stuff.

package 'httpd' do
  action :install
end

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

This is one of the beautiful things about Ruby and Chef, is the above needs little to no explanation. We have a package called httpd, and we want to install it. Then, we have a service called httpd, and we want to enable and start that service.

This is the equivilant to running

sudo yum install httpd -y

sudo systemctl enable httpd && sudo systemctl start httpd

But, we have reusable, scalable code that we can use and tailor to fit any series of servers and workstations that we see fit. You can use some cool features of ruby and Chef to see if the code checks out.

ruby -c default.rb

foodcritic default.rb

Foodcritic might have given some weird errors. Does it make sense? What do you think the issue is?

Hint:

Checkout the README.md in the apache directory, I’m sure you’ll find something TODO. :wink:

So, how do we use our recipe?

First, we need to upload the cookbook to the server. Backup a few directories, so you’re in the ~/chef-repo directory.

Then, use knife to upload the cookbook.

knife upload cookbook apache

And you’re set.

Syncing Recipes to Nodes

At the basic level, you can create a run list with a series of recipes for nodes. At a complex level, you can assign various cookbooks, recipes, and dependecies into roles and create a run list with a series of roles for nodes. This early, we’re just going to go over the single recipe.

From your workstation

knife node run_list add *name of node* 'recipe[apache]'

knife node show *name of node*

The first command will associate your recipe from the apache cookbook to your node, and the second command will verify that the recipe is now part of the run list.

Now, to execute chef-client, we can use knife.

knife ssh 'name:*node name*' 'sudo chef-client' --ssh-user *user with sudo permissions* --identity-file *This will be in ~/chef-repo/.chef/user.pem* --attribute ipaddress

For --attribute you want to actually type in “ipaddress”, you don’t need to type in the number, this is telling knife what it’s using to ssh into. Your identify file came with the Starter Kit. It’s name_of_user.pem, so whatever your user’s name is, it’s probably that with a .pem appended.

But! From here you can see that httpd was successfully installed, enabled, and started successfully. If you have a firewall disabled, you can go ahead and visit the IP Address of the node for the landing page. If you have a firewall, you can disable it, or add some code to your “default.rb” in ~/chef-repo/cookbooks/apache/recipes/default.rb

execute 'firewalld_rule' do
  command '/usr/bin/firewall-cmd --permanent --zone=public --add-service=http'
end

execute 'firewalld_rule' do
  command '/usr/bin/firewall-cmd --permanent --zone=public --add-service=https'
end

execute 'firewalld_reload' do
  command '/usr/bin/firewall-cmd --reload'
end

cd back to ~/chef-repo/cookbooks and do a knife upload cookbook apache to upload the current cookbook. If you want to do what the pros do, edit ~/chef-repo/cookbooks/apache/metadata.rb and change the version, since you did a pretty decent update. Then upload the cookbook.

From there, we’ll do another knife ssh

knife ssh 'name:*node name*' 'sudo chef-client' --ssh-user *user with sudo permissions* --identity-file *This will be in ~/chef-repo/.chef/user.pem* --attribute ipaddress

And, check out the IP Address of the node in the browser. BAM! Apache landing page!

What’s REALLY cool is, later on, when you get roles, you can knife ssh based on role instead of node names, so every node with the role in the run list will receive that ssh command.

Chef is an amazing tool, and the service is free for up to 25 nodes. I hope you enjoyed this intro demonstration. If this garners enough attention I will definitely add to it. Others feel free as well, we can get the whole LAMP stack built.

Useful Links



https://downloads.chef.io/chefdk
https://downloads.chef.io/chef-server

https://linuxacademy.com/devops/training/learningpath/name/certified-chef-developer

https://training.chef.io/basic-chef-fluency-badge

5 Likes

Very entertaining article. I have been hearing a lot about chef lately. Now I need to go play with it since you made it so easy to get into.

1 Like

It is definitely my favorite tool of Configuration Management. When you get into Kitchen… That blew my mind. I did all my Kitchen (testing) converging in Vagrant, but then wrote some configs for AWS. Now within about 15 minutes we test entire client infrastructure and tear it down upon success. You can integrate it with everything, Docker, Azure, AWS, whatever you need. Very powerful.

Bringing Ruby back lol

Ruby and Perl are my jam.

Nice! I was too late for Perl :grin:

Appreciate your feedback! Glad you enjoyed it

Is there a ready made chef image for Drupal 7? What’s the recommended way to for example have a folder synced outside the container? E.g. volumes in the docker vernacular. I would want mysql and user uploaded files to persist across rebuilds but the php files/program itself to be part of the image itself.

Hello Wendell!

To answer your first question, yes, there are some cookbooks with Drupal in the Chef Supermarket. But, they don’t have very good scores. I would definitely try them out in a local environment and see if they meet your needs.

This one has an above average score, but it looks like it’s more for an environment to host Drupal rather than Drupal itself (not familiar with the platform, sorry!)

https://supermarket.chef.io/cookbooks/aegir3

From the description:

For folders, you can declare ‘file’ and ‘folder’ resources with chef.

So, something like

directory /var/www/newsite do
  owner 'admindev'
  group 'www-data'
  mode '0755'
end

Would create that directory if that doesn’t exist. You could also specify content, files, and other resources to go in that directory.

Regarding the container and image, Chef isn’t so much as a containerization as much as it is just Infrastructure as Code. The node with the recipe checks in with the Chef server whenever the client is run (generally as a cron job), and if the node is not in the desired state, it changes based on what the recipe says. In the case above, it would check for /var/www/newsite, see it doesn’t exist, look for an action (I didn’t put one, but the default is create), and make the directory. The next time chef-client runs, it would skip that action since the folder exists.

But, you would still need an environment to run all this on. I’ve seen where Chef can run Dockerfile and pull containers (I’ve never done it, sorry again :frowning: ). But! The idea is the same.

I think Docker has a page on their site that walks through how to integrate with Chef.

I hope this helped! Definitely let me know if I didn’t answer your questions or if you want more information.

EDIT

Actually, Docker doesn’t have the docs anymore. They said to refer to Chef.

Holy crap, Chef has a pretty beast documentation regarding Docker

https://supermarket.chef.io/cookbooks/docker

Interesting. I was just looking into using chef to deploy a series of repos into a series of folders and then mapping some folders for ‘user data’