Salt in 60 seconds

Quickstart

Before we dive too far into the weeds, let's get up and running on Salt in less than 5 minutes.

In our quickstart, we're not going to worry about the separation of master/minion roles quite yet. Let's look at how to set up configuration management with SaltStack.

Getting setup

In our quickstart, we'll talk only about SaltStack, although we'll be using other tools to assist in the process. Everything that we're using in the quickstart is available online and free and can be found in the resources section.

First, you will need a text editor and a way to send files to your VM. We'll be using Sublime Text 2 and rsync in this tutorial.

If you are using OSX, we highly recommend Homebrew to install dependencies.

First, we'll need to make sure you have Python and Pip installed:

If you're on a mac, open up terminal and type:

brew install python
easy_install virtualenv
pip install virtualenv

Once you have those dependencies installed, all we'll need to do is set your current working environment to the virtualenv we'll create:

virtualenv --no-site-packages quickstart

Making a virtualenv

In just a minute, your virtualenv will be ready to go and we just need to source it to be ready to go:

cd quickstart
source bin/activate

Activating your virtualenv

Last thing, install boto:

pip install boto

Install boto

Launching our first machine!

You'll need an AWS account to launch a machine in AWS. If you don't have one, check out our getting setup on aws guide.

To use SaltStack, we need run a machine to deploy infrastructure. To do this, we'll use python and boto to launch a machine in ec2. Like so:

import boto, time, os

access_key    = os.environ['AWS_ACCESS_KEY']
secret_key    = os.environ['AWS_SECRET_ACCESS_KEY']
keypair_name  = 'mydemokey'

user_data = """#!/bin/bash
# Install saltstack
curl -L http://bootstrap.saltstack.org | sudo sh -s -- -M stable

echo '''### This is controlled by the hosts file
master: localhost
id: localhost
file_roots:
  base:
    - /srv/salt/states
log_file: /var/log/salt/minion
log_level: debug
log_level_logfile: garbage
''' > /etc/salt/minion

# Set salt master location and start minion
sed -i 's/#master: salt/master: localhost/' /etc/salt/minion
salt-minion -d
  """

conn  = boto.connect_ec2(access_key, secret_key)
try:
  key   = conn.create_key_pair(keypair_name)
  key.save("./")
except:
  True # Key already created

group_name = "quickstart"
try:
  groups = [g for g in conn.get_all_security_groups() if g.name == group_name]
  group = groups[0] if groups else None
  if not group:
    group = conn.create_security_group(group_name, "A group for %s"%(group_name,))
  group.authorize(ip_protocol='tcp',
                  from_port=str(22),
                  to_port=str(22),
                  cidr_ip='0.0.0.0/0')
  group.authorize(ip_protocol='tcp',
                  from_port=str(80),
                  to_port=str(80),
                  cidr_ip='0.0.0.0/0')
except:
  True

reservation = conn.run_instances(image_id='ami-0cdf4965',
                                 key_name=keypair_name,
                                 security_groups=[group_name],
                                 user_data=user_data)

running_instance = reservation.instances[0]
status = running_instance.update()
while status == 'pending':
    time.sleep(10)
    status = running_instance.update()
print(running_instance.ip_address)

Make sure you export your AWSACCESSKEY and AWSSECRETACCESS_KEY in your environment:

export AWS_ACCESS_KEY=""
export AWS_SECRET_ACCESS_KEY=""
IP=$(python quickstart.py)

Start your vm

After you get a cup of tea, your machine will be up and ready to go with salt running already. To check it out, use the key that the script downloaded with SSH:

$ IP=$(python quickstart.py)
$ ssh ubuntu@$IP -i `pwd`/mydemokey.pem
  ...

Take note of the IP that the script prints you back. We'll be using this throughout the quickstart. If you use the convention we set up above, you can simply run echo $IP to give you the ip of your new vm.

Quickstart with SaltStack

Let's set up our system to install apache. Create a directory structure that looks like:

deploy/
  salt/
    states/
      apache.sls

You can do this by running the following commands in your terminal:

mkdir -p deploy/salt/states
touch deploy/salt/states/apache.sls

Creating your states

Let's setup and install apache. Inside your apache.sls file, add the following:

apache2:
  pkg:
    - installed
  service:
    - running
    - require:
      - pkg: apache2

Your first SaltStack state

When we run highstate (meaning, when we start the saltstack runner), this .sls file will ensure that the apache package is installed. The SaltStack pkg is smart enough to choose which package manager to use depending upon the environment you are running SaltStack in. That is, if you are using ubuntu, it will use apt-get, while if you are using RedHat/CentOS, it will use yum to install the package.

Second, it will ensure that the apache service is running only if the apache package is installed correctly. By using require, Salt creates a simple dependency graph that looks like this:

[pkg:apache2] -> [service:apache2]

Anyway, there's time for theory later, let's build our box. First, we'll need to sync our local states to the remote machine. This can be easily accomplished using rsync, like so:

ssh ubuntu@$IP -i `pwd`/mydemokey.pem "sudo mkdir -p /srv/salt && sudo chown ubuntu -R /srv/salt"
rsync -az -v -e "ssh -p 22 -i '`pwd`/mydemokey.pem'" `pwd`/deploy/salt/ ubuntu@$IP:/srv/salt

Let's log into the machine and run the first highstate

$ ssh ubuntu@$IP -i `pwd`/mydemokey.pem
$ sudo salt-call --local state.sls apache

You'll see a lot of output, you'll see apache installing and the service will be running. To get this running, we're using the --local option so we don't have to set up a remote master server yet. This simply changes the flow to tell salt to pull the states from the local filesystem instead of the remote salt master.

Once this is done, you'll see that not only has apache been installed, but it's running too.

Start your vm

Now, let's expand our example. Let's add an apache user so that we can run apache under the apache user. Modify your apache.sls file to look something like:

apache2:
  pkg:
    - installed
  service:
    - running
    - require:
      - pkg: apache2
    - watch:
      - file: apache2
  user:
    - present
    - home: /var/www
    - shell: /bin/nologin
    - groups: 
      - apache2
    - require:
      - group: apache2
  group:
    - present
    - require:
      - pkg: apache2
  file.managed:
    - name: /etc/apache2/apache2.conf
    - source: salt://apache2.conf
    - template: jinja
    - user: apache2
    - group: apache2
    - mode: 644
    - require:
      - user: apache2

Run the salt-call command once again after you sync it to your server:

rsync -az -v -e "ssh -p 22 -i '`pwd`/mydemokey.pem'" `pwd`/deploy/salt/ ubuntu@$IP:/srv/salt
ssh ubuntu@$IP -i `pwd`/mydemokey.pem
sudo salt-call --local state.sls apache

Start your vm

This new declaration will set us up with an apache2 user and group, as well as set a managed file at /etc/apache2/apache2.conf. If you sync this to your server and run it, you'll notice that some things will work and some will fail (If you are running this command after logging in, errors show up red, new things blue and existing states show up green).

The failure is because we referenced a file that is in the SaltStack filesystem (that's right, SaltStack has a built-in distributed filesystem) but SaltStack cannot find it.

When you use the salt:// prefix, SaltStack will look into it's file_root declaration and try to find it for you. In our quickstart, we set the file_root to be at /srv/salt/states, so salt://apache2.conf will be at /srv/salt/states/apache2.conf.

Let's create a apache2.conf template there. On your local machine, make a new file deploy/salt/states/apache2.conf:

echo "
  DocumentRoot /var/www
  User apache2
  Group apache2

  ErrorLog /var/www/error.log
  Include mods-enabled/*.load
  Include mods-enabled/*.conf
  Include ports.conf

  Include conf.d/
  Include sites-enabled/
" > deploy/salt/states/apache2.conf

Just as before, sync this to your servers and rerun highstate:

rsync -az -v -e "ssh -p 22 -i '`pwd`/mydemokey.pem'" `pwd`/deploy/salt/ ubuntu@$IP:/srv/salt
ssh ubuntu@$IP -i `pwd`/mydemokey.pem "sudo salt-call --local state.sls apache"

Now that your states run correctly, let's go to the webpage in a browser:

echo $IP

You should see the default “It works” page at your IP.

Let's make it a bit more interesting now. Let's create our own page. Make any sort of html document in your deploy/salt/states directory and put it at deploy/salt/states/index.html.

echo '<!DOCTYPE html>
<head>
  <meta http-equiv="Content-type" content="text/html; charset=utf-8">
  <title>Test page</title>
</head>
<body id="index">
  <h1>My own homepage</h1>
</body>
' > deploy/salt/states/index.html

Let's add this as a file to our state declaration. This time, we'll need a new state declaration because each declaration can only have one of each state type.

apache2:
  pkg:
    - installed
  service:
    - running
    - require:
      - pkg: apache2
    - watch:
      - file: apache2
      - file: apache2_index_page
  user:
    - present
    - home: /var/www/html
    - shell: /bin/nologin
    - groups: 
      - apache2
    - require:
      - group: apache2
  group:
    - present
    - require:
      - pkg: apache2
  file.managed:
    - name: /etc/apache2/apache2.conf
    - source: salt://apache2.conf
    - template: jinja
    - user: apache2
    - group: apache2
    - mode: 644
    - require:
      - user: apache2

apache2_index_page:
  file.managed:
    - name: /var/www/index.html
    - source: salt://index.html
    - user: apache2
    - group: apache2
    - mode: 644
    - require:
      - pkg: apache2

Here we did two things. First, we added a new state declaration and called it apache2_index_page. This state will set up our new /var/www/index.html page. We also added a watch statement to the apache2 service. This will restart the apache2 service everytime the /var/www/index.html page is changed.

Run the sls again and we'll see the page as now changed.

rsync -az -v -e "ssh -p 22 -i '`pwd`/mydemokey.pem'" `pwd`/deploy/salt/ ubuntu@$IP:/srv/salt
ssh ubuntu@$IP -i `pwd`/mydemokey.pem "sudo salt-call --local state.sls apache"

After the last highstate

We hope you enjoyed this quickstart and now have a good handle on working with SaltStack. In later chapters, we'll discuss how to use SaltStack in more production-ready ways, how to build states using dynamic data, and more.

Your email is required. Your email is required to be at least 3 characters That is not a valid email. Please input a valid email.

Comments

comments powered by Disqus