Setup for a SaltStack Vagrant Environment
Often when writing Salt related code, I need an environment in which ideas can quicly be tested and interated upon. I have found that Vagrant is usually suited perfectly for filling this need. If you want to use Vagrant as well, first you’ll need to install it from the VagrantUp Hashicorp website.
The idea here is to create an environment with a single master and minion from which changes to Salt formulas, modules, pillars, orchs, beacons, engines, etc. can quickly and easily be tested.
Setting Up Vagrant
Because I like to break out my Vagrant environments based on the project or environment for which I need to work on, I create the directory ~/Documents/vagrant/salt
and then change to it and run vagrant init
.
Inside this directory, I need a few files:
- Vagrantfile
- The salt bootstrap script aka
bootstrap-salt.sh
- A salt-master config file aka
salt_master_config
- A salt-minion config file aka
salt_minion_config
- A YAML file to describe the hosts to be created aka
vagrant_hosts.yml
Vagrantfile
Vagrant is Ruby based, and the Vagrantfile is also Ruby based. Meaning it can be glommed onto for things we want or need. In my case, I used a Vagrantfile derived from https://git.jeroened.be/JeroenED/Vagrant/raw/master/Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
require 'yaml'
hosts = YAML.load_file('vagrant_hosts.yml')
# Set options for the network interface configuration. All values are
# optional, and can include:
# - ip (default = DHCP)
# - netmask (default value = 255.255.255.0
# - mac
# - auto_config (if false, Vagrant will not configure this network interface
# - intnet (if true, an internal network adapter will be created instead of a
# host-only adapter)
def network_options(host)
options = {}
if host.has_key?('ip')
options[:ip] = host['ip']
options[:netmask] = host['netmask'] ||= '255.255.255.0'
else
options[:type] = 'dhcp'
end
if host.has_key?('mac')
options[:mac] = host['mac'].gsub(/[-:]/, '')
end
if host.has_key?('auto_config')
options[:auto_config] = host['auto_config']
end
if host.has_key?('intnet') && host['intnet']
options[:virtualbox__intnet] = true
end
options
end
def box_choice(host)
choice = ''
if host.has_key?('box')
choice = host['box']
else
choice = 'centos/7'
end
choice
end
$script = <<-SCRIPT
sudo yum -y install python3
sudo ln -s /srv/salt /etc/salt
SCRIPT
Vagrant.configure("2") do |config|
hosts.each do | host |
if host.has_key?('sync_folder')
config.vm.synced_folder host['sync_folder']['host'], host['sync_folder']['guest'], type: 'nfs'
end
config.vm.define host['name'] do | node |
node.vm.box = box_choice(host)
node.vm.hostname = host['name']
node.vm.network :private_network, network_options(host)
node.vm.provider :virtualbox do | vb |
vb.name = host['name']
vb.cpus = host['cpus'] ||= 1
vb.memory = host['memory'] ||= 512
end
if host.has_key?('sync_folder')
node.vm.provision 'shell',
inline: $script
end
node.vm.provision :salt do | salt |
if host.has_key?('sync_folder')
salt.install_master
salt.no_minion
salt.master_config = 'salt_master_config'
salt.bootstrap_script = 'bootstrap-salt.sh'
salt.bootstrap_options = '-M'
salt.python_version = '3'
else
salt.minion_config = 'salt_minion_config'
salt.run_highstate = false
salt.bootstrap_script = 'bootstrap-salt.sh'
end
salt.install_type = 'stable'
salt.install_args = '2019.2'
end
end
end
end
Salt-Bootstrap Script
The salt-bootstrap script should be retrieved directly from the SaltStack project with:
curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com
Salt-Master Config
The salt master config I use is usually exactly the same as the one I use in production just stripped of comments to make for easier deciphering.
grep -v '^$\|^#' master > salt_master_config
Salt-Minion Config
The minion config is about a simple as I can make it.
master: 172.28.128.10
file_client: remote
hash_type: sha512
Vagrant Hosts YAML
This is just a YAML file that describes the instances I want built for this environment.
- name: minion1
cpu: 1
memory: 1024
box: centos/7
- name: master1
cpu: 1
memory: 1024
box: centos/7
ip: 172.28.128.10
sync_folder:
host: "~/Documents/salt-master-configuration"
guest: "/srv/salt"
The magic in this setup is:
- The master uses an NFS mount to the host for the Salt pillars, states, etc.
- Using the
name
key in the Vagrant Hosts YAML, we can simulate any environment. - We can run a different version of Salt just by modifying the Vagrantfile.
- Minions come up automatically pointed to the Master. Their keys still must be approved manually, but that’s a small price to pay. Don’t forget, the salt pki is on your host, so you’re adding a minion key there.
Caveat
For this particular setup, the entirety of the Salt configuration is contained in the salt-master-configuration
directory. This is forumlas, pillars, everything.
Using Vagrant
If all the pieces are in place, just run vagrant up
and the machines will be created. Once they are running, you can access them with vagrant ssh master1
or vagrant ssh minion1
.
Typically, while I’m using this set up, I have an editor with the Salt related code I’m working on open as well as a terminal window with an SSH connection to minion1
running in Vagrant. Because Vagrant has setup an NFS mount between the salt-master-configuration
directory on my laptop and the master1
instance, as I make changes in the file in the editor, I can use salt-call
on the minion to check the effect.
Originally published at https://smartaleksolutions.com on September 8, 2020.